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
4505                        default:
4506                                if (plci->internal_command_queue[0])
4507                                {
4508                                        (*(plci->internal_command_queue[0]))(Id, plci, rc);
4509                                        if (plci->internal_command)
4510                                                return;
4511                                }
4512                                break;
4513                        }
4514                        next_internal_command(Id, plci);
4515                }
4516        }
4517        else /* appl==0 */
4518        {
4519                Id = ((word)plci->Id << 8) | plci->adapter->Id;
4520                if (plci->tel) Id |= EXT_CONTROLLER;
4521
4522                switch (plci->internal_command)
4523                {
4524                case BLOCK_PLCI:
4525                        return;
4526
4527                case START_L1_SIG_ASSIGN_PEND:
4528                case REM_L1_SIG_ASSIGN_PEND:
4529                        if (global_req == ASSIGN)
4530                        {
4531                                break;
4532                        }
4533                        else
4534                        {
4535                                dbug(1, dprintf("***L1 Req rem PLCI"));
4536                                plci->internal_command = 0;
4537                                sig_req(plci, REMOVE, 0);
4538                                send_req(plci);
4539                        }
4540                        break;
4541
4542                        /* Call Deflection Request pending, just no appl ptr assigned */
4543                case CD_REQ_PEND:
4544                        SSparms[1] = S_CALL_DEFLECTION;
4545                        if (rc != OK)
4546                        {
4547                                Info = 0x300E; /* not supported */
4548                        }
4549                        for (i = 0; i < max_appl; i++)
4550                        {
4551                                if (application[i].CDEnable)
4552                                {
4553                                        if (!application[i].Id) application[i].CDEnable = 0;
4554                                        else
4555                                        {
4556                                                sendf(&application[i], _FACILITY_R | CONFIRM, Id,
4557                                                      plci->number, "wws", Info, (word)3, SSparms);
4558                                                if (Info) application[i].CDEnable = 0;
4559                                        }
4560                                }
4561                        }
4562                        plci->internal_command = 0;
4563                        break;
4564
4565                case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4566                        return;
4567
4568                case PERM_COD_CALL:
4569                        plci->internal_command = PERM_COD_CONN_PEND;
4570                        dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc));
4571                        return;
4572
4573                case PERM_COD_ASSIGN:
4574                        dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc));
4575                        plci->internal_command = 0;
4576                        if (rc != ASSIGN_OK) break;
4577                        plci->internal_command = PERM_COD_CALL;
4578                        sig_req(plci, CALL_REQ, 0);
4579                        send_req(plci);
4580                        return;
4581
4582                case LISTEN_SIG_ASSIGN_PEND:
4583                        if (rc == ASSIGN_OK)
4584                        {
4585                                plci->internal_command = 0;
4586                                dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci->Sig.Id));
4587                                add_p(plci, ESC, "\x02\x18\x00");             /* support call waiting */
4588                                sig_req(plci, INDICATE_REQ, 0);
4589                                send_req(plci);
4590                        }
4591                        else
4592                        {
4593                                dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc));
4594                                a->listen_active--;
4595                                plci_remove(plci);
4596                                plci->State = IDLE;
4597                        }
4598                        break;
4599
4600                case USELAW_REQ:
4601                        if (global_req == ASSIGN)
4602                        {
4603                                if (rc == ASSIGN_OK)
4604                                {
4605                                        sig_req(plci, LAW_REQ, 0);
4606                                        send_req(plci);
4607                                        dbug(1, dprintf("Auto-Law assigned"));
4608                                }
4609                                else
4610                                {
4611                                        dbug(1, dprintf("Auto-Law assign failed"));
4612                                        a->automatic_law = 3;
4613                                        plci->internal_command = 0;
4614                                        a->automatic_lawPLCI = NULL;
4615                                }
4616                                break;
4617                        }
4618                        else if (req == LAW_REQ && rc == OK)
4619                        {
4620                                dbug(1, dprintf("Auto-Law initiated"));
4621                                a->automatic_law = 2;
4622                                plci->internal_command = 0;
4623                        }
4624                        else
4625                        {
4626                                dbug(1, dprintf("Auto-Law not supported"));
4627                                a->automatic_law = 3;
4628                                plci->internal_command = 0;
4629                                sig_req(plci, REMOVE, 0);
4630                                send_req(plci);
4631                                a->automatic_lawPLCI = NULL;
4632                        }
4633                        break;
4634                }
4635                plci_remove_check(plci);
4636        }
4637}
4638
4639static void data_rc(PLCI *plci, byte ch)
4640{
4641        dword Id;
4642        DIVA_CAPI_ADAPTER *a;
4643        NCCI *ncci_ptr;
4644        DATA_B3_DESC *data;
4645        word ncci;
4646
4647        if (plci->appl)
4648        {
4649                TransmitBufferFree(plci->appl, plci->data_sent_ptr);
4650                a = plci->adapter;
4651                ncci = a->ch_ncci[ch];
4652                if (ncci && (a->ncci_plci[ncci] == plci->Id))
4653                {
4654                        ncci_ptr = &(a->ncci[ncci]);
4655                        dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr->data_out, ncci_ptr->data_pending));
4656                        if (ncci_ptr->data_pending)
4657                        {
4658                                data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4659                                if (!(data->Flags & 4) && a->ncci_state[ncci])
4660                                {
4661                                        Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4662                                        if (plci->tel) Id |= EXT_CONTROLLER;
4663                                        sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, data->Number,
4664                                              "ww", data->Handle, 0);
4665                                }
4666                                (ncci_ptr->data_out)++;
4667                                if (ncci_ptr->data_out == MAX_DATA_B3)
4668                                        ncci_ptr->data_out = 0;
4669                                (ncci_ptr->data_pending)--;
4670                        }
4671                }
4672        }
4673}
4674
4675static void data_ack(PLCI *plci, byte ch)
4676{
4677        dword Id;
4678        DIVA_CAPI_ADAPTER *a;
4679        NCCI *ncci_ptr;
4680        word ncci;
4681
4682        a = plci->adapter;
4683        ncci = a->ch_ncci[ch];
4684        ncci_ptr = &(a->ncci[ncci]);
4685        if (ncci_ptr->data_ack_pending)
4686        {
4687                if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4688                {
4689                        Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4690                        if (plci->tel) Id |= EXT_CONTROLLER;
4691                        sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4692                              "ww", ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle, 0);
4693                }
4694                (ncci_ptr->data_ack_out)++;
4695                if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4696                        ncci_ptr->data_ack_out = 0;
4697                (ncci_ptr->data_ack_pending)--;
4698        }
4699}
4700
4701static void sig_ind(PLCI *plci)
4702{
4703        dword x_Id;
4704        dword Id;
4705        dword rId;
4706        word i;
4707        word cip;
4708        dword cip_mask;
4709        byte *ie;
4710        DIVA_CAPI_ADAPTER *a;
4711        API_PARSE saved_parms[MAX_MSG_PARMS + 1];
4712#define MAXPARMSIDS 31
4713        byte *parms[MAXPARMSIDS];
4714        byte *add_i[4];
4715        byte *multi_fac_parms[MAX_MULTI_IE];
4716        byte *multi_pi_parms[MAX_MULTI_IE];
4717        byte *multi_ssext_parms[MAX_MULTI_IE];
4718        byte *multi_CiPN_parms[MAX_MULTI_IE];
4719
4720        byte *multi_vswitch_parms[MAX_MULTI_IE];
4721
4722        byte ai_len;
4723        byte *esc_chi = "";
4724        byte *esc_law = "";
4725        byte *pty_cai = "";
4726        byte *esc_cr  = "";
4727        byte *esc_profile = "";
4728
4729        byte facility[256];
4730        PLCI *tplci = NULL;
4731        byte chi[] = "\x02\x18\x01";
4732        byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4733        byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4734        /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4735        /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4736        /* SMSG is situated at the end because its 0 (for compatibility reasons */
4737        /* (see Info_Mask Bit 4, first IE. then the message type)           */
4738        static const word parms_id[] =
4739                {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4740                 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4741                 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4742                 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4743        /* 14 FTY repl by ESC_CHI */
4744        /* 18 PI  repl by ESC_LAW */
4745        /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4746        static const word multi_fac_id[] = {1, FTY};
4747        static const word multi_pi_id[]  = {1, PI};
4748        static const word multi_CiPN_id[]  = {1, OAD};
4749        static const word multi_ssext_id[]  = {1, ESC_SSEXT};
4750
4751        static const word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4752
4753        byte *cau;
4754        word ncci;
4755        byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4756        byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4757        byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4758        byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\x00\x00\x00\x00";
4759        byte force_mt_info = false;
4760        byte dir;
4761        dword d;
4762        word w;
4763
4764        a = plci->adapter;
4765        Id = ((word)plci->Id << 8) | a->Id;
4766        PUT_WORD(&SS_Ind[4], 0x0000);
4767
4768        if (plci->sig_remove_id)
4769        {
4770                plci->Sig.RNR = 2; /* discard */
4771                dbug(1, dprintf("SIG discard while remove pending"));
4772                return;
4773        }
4774        if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4775        dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4776                        Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4777        if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4778        {
4779                plci->Sig.RNR = 1;
4780                return;
4781        }
4782        if (plci->Sig.Ind == HANGUP && plci->channels)
4783        {
4784                plci->Sig.RNR = 1;
4785                plci->hangup_flow_ctrl_timer++;
4786                /* recover the network layer after timeout */
4787                if (plci->hangup_flow_ctrl_timer == 100)
4788                {
4789                        dbug(1, dprintf("Exceptional disc"));
4790                        plci->Sig.RNR = 0;
4791                        plci->hangup_flow_ctrl_timer = 0;
4792                        for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4793                        {
4794                                if (a->ncci_plci[ncci] == plci->Id)
4795                                {
4796                                        cleanup_ncci_data(plci, ncci);
4797                                        if (plci->channels)plci->channels--;
4798                                        if (plci->appl)
4799                                                sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4800                                }
4801                        }
4802                        if (plci->appl)
4803                                sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4804                        plci_remove(plci);
4805                        plci->State = IDLE;
4806                }
4807                return;
4808        }
4809
4810        /* do first parse the info with no OAD in, because OAD will be converted */
4811        /* first the multiple facility IE, then mult. progress ind.              */
4812        /* then the parameters for the info_ind + conn_ind                       */
4813        IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4814        IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4815        IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4816
4817        IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4818
4819        IndParse(plci, parms_id, parms, 0);
4820        IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4821        esc_chi  = parms[14];
4822        esc_law  = parms[18];
4823        pty_cai  = parms[24];
4824        esc_cr   = parms[25];
4825        esc_profile = parms[27];
4826        if (esc_cr[0] && plci)
4827        {
4828                if (plci->cr_enquiry && plci->appl)
4829                {
4830                        plci->cr_enquiry = false;
4831                        /* d = MANU_ID            */
4832                        /* w = m_command          */
4833                        /* b = total length       */
4834                        /* b = indication type    */
4835                        /* b = length of all IEs  */
4836                        /* b = IE1                */
4837                        /* S = IE1 length + cont. */
4838                        /* b = IE2                */
4839                        /* S = IE2 length + cont. */
4840                        sendf(plci->appl,
4841                              _MANUFACTURER_I,
4842                              Id,
4843                              0,
4844                              "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4845                              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);
4846                }
4847        }
4848        /* create the additional info structure                                  */
4849        add_i[1] = parms[15]; /* KEY of additional info */
4850        add_i[2] = parms[11]; /* UUI of additional info */
4851        ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4852
4853        /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4854        /* indication returns by the card if requested by the function           */
4855        /* AutomaticLaw() after driver init                                      */
4856        if (a->automatic_law < 4)
4857        {
4858                if (esc_law[0]) {
4859                        if (esc_law[2]) {
4860                                dbug(0, dprintf("u-Law selected"));
4861                                a->u_law = 1;
4862                        }
4863                        else {
4864                                dbug(0, dprintf("a-Law selected"));
4865                                a->u_law = 0;
4866                        }
4867                        a->automatic_law = 4;
4868                        if (plci == a->automatic_lawPLCI) {
4869                                plci->internal_command = 0;
4870                                sig_req(plci, REMOVE, 0);
4871                                send_req(plci);
4872                                a->automatic_lawPLCI = NULL;
4873                        }
4874                }
4875                if (esc_profile[0])
4876                {
4877                        dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4878                                        UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
4879                                        GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
4880                                        GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
4881
4882                        a->profile.Global_Options &= 0x000000ffL;
4883                        a->profile.B1_Protocols &= 0x000003ffL;
4884                        a->profile.B2_Protocols &= 0x00001fdfL;
4885                        a->profile.B3_Protocols &= 0x000000b7L;
4886
4887                        a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
4888                                GL_BCHANNEL_OPERATION_SUPPORTED;
4889                        a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
4890                        a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
4891                        a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
4892                        a->manufacturer_features = GET_DWORD(&esc_profile[46]);
4893                        a->man_profile.private_options = 0;
4894
4895                        if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
4896                        {
4897                                a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
4898                                a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
4899                        }
4900
4901
4902                        if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
4903                                a->man_profile.private_options |= 1L << PRIVATE_RTP;
4904                        a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
4905                        a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
4906
4907
4908                        if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
4909                                a->man_profile.private_options |= 1L << PRIVATE_T38;
4910
4911
4912                        if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
4913                                a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
4914
4915
4916                        if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
4917                                a->man_profile.private_options |= 1L << PRIVATE_V18;
4918
4919
4920                        if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
4921                                a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
4922
4923
4924                        if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
4925                                a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
4926
4927
4928                        if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
4929                                a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
4930
4931
4932                        if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
4933                                a->man_profile.private_options |= 1L << PRIVATE_VOWN;
4934
4935
4936                        if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
4937                                a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
4938
4939                }
4940                else
4941                {
4942                        a->profile.Global_Options &= 0x0000007fL;
4943                        a->profile.B1_Protocols &= 0x000003dfL;
4944                        a->profile.B2_Protocols &= 0x00001adfL;
4945                        a->profile.B3_Protocols &= 0x000000b7L;
4946                        a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
4947                }
4948                if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
4949                                                MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
4950                {
4951                        a->profile.Global_Options |= GL_DTMF_SUPPORTED;
4952                }
4953                a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
4954                dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
4955                                UnMapController(a->Id), a->profile.Global_Options,
4956                                a->profile.B1_Protocols, a->profile.B2_Protocols,
4957                                a->profile.B3_Protocols, a->manufacturer_features));
4958        }
4959        /* codec plci for the handset/hook state support is just an internal id  */
4960        if (plci != a->AdvCodecPLCI)
4961        {
4962                force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
4963                force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
4964                SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
4965                SendInfo(plci, Id, parms, force_mt_info);
4966
4967                VSwitchReqInd(plci, Id, multi_vswitch_parms);
4968
4969        }
4970
4971        /* switch the codec to the b-channel                                     */
4972        if (esc_chi[0] && plci && !plci->SuppState) {
4973                plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
4974                mixer_set_bchannel_id_esc(plci, plci->b_channel);
4975                dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
4976                if (plci->tel == ADV_VOICE && plci->appl) {
4977                        SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
4978                }
4979        }
4980
4981        if (plci->appl) plci->appl->Number++;
4982
4983        switch (plci->Sig.Ind) {
4984                /* Response to Get_Supported_Services request */
4985        case S_SUPPORTED:
4986                dbug(1, dprintf("S_Supported"));
4987                if (!plci->appl) break;
4988                if (pty_cai[0] == 4)
4989                {
4990                        PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
4991                }
4992                else
4993                {
4994                        PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
4995                }
4996                PUT_WORD(&CF_Ind[1], 0);
4997                PUT_WORD(&CF_Ind[4], 0);
4998                sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
4999                plci_remove(plci);
5000                break;
5001
5002                /* Supplementary Service rejected */
5003        case S_SERVICE_REJ:
5004                dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5005                if (!pty_cai[0]) break;
5006                switch (pty_cai[5])
5007                {
5008                case ECT_EXECUTE:
5009                case THREE_PTY_END:
5010                case THREE_PTY_BEGIN:
5011                        if (!plci->relatedPTYPLCI) break;
5012                        tplci = plci->relatedPTYPLCI;
5013                        rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5014                        if (tplci->tel) rId |= EXT_CONTROLLER;
5015                        if (pty_cai[5] == ECT_EXECUTE)
5016                        {
5017                                PUT_WORD(&SS_Ind[1], S_ECT);
5018
5019                                plci->vswitchstate = 0;
5020                                plci->relatedPTYPLCI->vswitchstate = 0;
5021
5022                        }
5023                        else
5024                        {
5025                                PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5026                        }
5027                        if (pty_cai[2] != 0xff)
5028                        {
5029                                PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5030                        }
5031                        else
5032                        {
5033                                PUT_WORD(&SS_Ind[4], 0x300E);
5034                        }
5035                        plci->relatedPTYPLCI = NULL;
5036                        plci->ptyState = 0;
5037                        sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5038                        break;
5039
5040                case CALL_DEFLECTION:
5041                        if (pty_cai[2] != 0xff)
5042                        {
5043                                PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5044                        }
5045                        else
5046                        {
5047                                PUT_WORD(&SS_Ind[4], 0x300E);
5048                        }
5049                        PUT_WORD(&SS_Ind[1], pty_cai[5]);
5050                        for (i = 0; i < max_appl; i++)
5051                        {
5052                                if (application[i].CDEnable)
5053                                {
5054                                        if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5055                                        application[i].CDEnable = false;
5056                                }
5057                        }
5058                        break;
5059
5060                case DEACTIVATION_DIVERSION:
5061                case ACTIVATION_DIVERSION:
5062                case DIVERSION_INTERROGATE_CFU:
5063                case DIVERSION_INTERROGATE_CFB:
5064                case DIVERSION_INTERROGATE_CFNR:
5065                case DIVERSION_INTERROGATE_NUM:
5066                case CCBS_REQUEST:
5067                case CCBS_DEACTIVATE:
5068                case CCBS_INTERROGATE:
5069                        if (!plci->appl) break;
5070                        if (pty_cai[2] != 0xff)
5071                        {
5072                                PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5073                        }
5074                        else
5075                        {
5076                                PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5077                        }
5078                        switch (pty_cai[5])
5079                        {
5080                        case DEACTIVATION_DIVERSION:
5081                                dbug(1, dprintf("Deact_Div"));
5082                                Interr_Err_Ind[0] = 0x9;
5083                                Interr_Err_Ind[3] = 0x6;
5084                                PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5085                                break;
5086                        case ACTIVATION_DIVERSION:
5087                                dbug(1, dprintf("Act_Div"));
5088                                Interr_Err_Ind[0] = 0x9;
5089                                Interr_Err_Ind[3] = 0x6;
5090                                PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5091                                break;
5092                        case DIVERSION_INTERROGATE_CFU:
5093                        case DIVERSION_INTERROGATE_CFB:
5094                        case DIVERSION_INTERROGATE_CFNR:
5095                                dbug(1, dprintf("Interr_Div"));
5096                                Interr_Err_Ind[0] = 0xa;
5097                                Interr_Err_Ind[3] = 0x7;
5098                                PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5099                                break;
5100                        case DIVERSION_INTERROGATE_NUM:
5101                                dbug(1, dprintf("Interr_Num"));
5102                                Interr_Err_Ind[0] = 0xa;
5103                                Interr_Err_Ind[3] = 0x7;
5104                                PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5105                                break;
5106                        case CCBS_REQUEST:
5107                                dbug(1, dprintf("CCBS Request"));
5108                                Interr_Err_Ind[0] = 0xd;
5109                                Interr_Err_Ind[3] = 0xa;
5110                                PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5111                                break;
5112                        case CCBS_DEACTIVATE:
5113                                dbug(1, dprintf("CCBS Deactivate"));
5114                                Interr_Err_Ind[0] = 0x9;
5115                                Interr_Err_Ind[3] = 0x6;
5116                                PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5117                                break;
5118                        case CCBS_INTERROGATE:
5119                                dbug(1, dprintf("CCBS Interrogate"));
5120                                Interr_Err_Ind[0] = 0xb;
5121                                Interr_Err_Ind[3] = 0x8;
5122                                PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5123                                break;
5124                        }
5125                        PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5126                        sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5127                        plci_remove(plci);
5128                        break;
5129                case ACTIVATION_MWI:
5130                case DEACTIVATION_MWI:
5131                        if (pty_cai[5] == ACTIVATION_MWI)
5132                        {
5133                                PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5134                        }
5135                        else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5136
5137                        if (pty_cai[2] != 0xff)
5138                        {
5139                                PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5140                        }
5141                        else
5142                        {
5143                                PUT_WORD(&SS_Ind[4], 0x300E);
5144                        }
5145
5146                        if (plci->cr_enquiry)
5147                        {
5148                                sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5149                                plci_remove(plci);
5150                        }
5151                        else
5152                        {
5153                                sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5154                        }
5155                        break;
5156                case CONF_ADD: /* ERROR */
5157                case CONF_BEGIN:
5158                case CONF_DROP:
5159                case CONF_ISOLATE:
5160                case CONF_REATTACH:
5161                        CONF_Ind[0] = 9;
5162                        CONF_Ind[3] = 6;
5163                        switch (pty_cai[5])
5164                        {
5165                        case CONF_BEGIN:
5166                                PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5167                                plci->ptyState = 0;
5168                                break;
5169                        case CONF_DROP:
5170                                CONF_Ind[0] = 5;
5171                                CONF_Ind[3] = 2;
5172                                PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5173                                plci->ptyState = CONNECTED;
5174                                break;
5175                        case CONF_ISOLATE:
5176                                CONF_Ind[0] = 5;
5177                                CONF_Ind[3] = 2;
5178                                PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5179                                plci->ptyState = CONNECTED;
5180                                break;
5181                        case CONF_REATTACH:
5182                                CONF_Ind[0] = 5;
5183                                CONF_Ind[3] = 2;
5184                                PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5185                                plci->ptyState = CONNECTED;
5186                                break;
5187                        case CONF_ADD:
5188                                PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5189                                plci->relatedPTYPLCI = NULL;
5190                                tplci = plci->relatedPTYPLCI;
5191                                if (tplci) tplci->ptyState = CONNECTED;
5192                                plci->ptyState = CONNECTED;
5193                                break;
5194                        }
5195
5196                        if (pty_cai[2] != 0xff)
5197                        {
5198                                PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5199                        }
5200                        else
5201                        {
5202                                PUT_WORD(&CONF_Ind[4], 0x3303); /* Time-out: network did not respond
5203                                                                  within the required time */
5204                        }
5205
5206                        PUT_DWORD(&CONF_Ind[6], 0x0);
5207                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5208                        break;
5209                }
5210                break;
5211
5212                /* Supplementary Service indicates success */
5213        case S_SERVICE:
5214                dbug(1, dprintf("Service_Ind"));
5215                PUT_WORD(&CF_Ind[4], 0);
5216                switch (pty_cai[5])
5217                {
5218                case THREE_PTY_END:
5219                case THREE_PTY_BEGIN:
5220                case ECT_EXECUTE:
5221                        if (!plci->relatedPTYPLCI) break;
5222                        tplci = plci->relatedPTYPLCI;
5223                        rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5224                        if (tplci->tel) rId |= EXT_CONTROLLER;
5225                        if (pty_cai[5] == ECT_EXECUTE)
5226                        {
5227                                PUT_WORD(&SS_Ind[1], S_ECT);
5228
5229                                if (plci->vswitchstate != 3)
5230                                {
5231
5232                                        plci->ptyState = IDLE;
5233                                        plci->relatedPTYPLCI = NULL;
5234                                        plci->ptyState = 0;
5235
5236                                }
5237
5238                                dbug(1, dprintf("ECT OK"));
5239                                sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5240
5241
5242
5243                        }
5244                        else
5245                        {
5246                                switch (plci->ptyState)
5247                                {
5248                                case S_3PTY_BEGIN:
5249                                        plci->ptyState = CONNECTED;
5250                                        dbug(1, dprintf("3PTY ON"));
5251                                        break;
5252
5253                                case S_3PTY_END:
5254                                        plci->ptyState = IDLE;
5255                                        plci->relatedPTYPLCI = NULL;
5256                                        plci->ptyState = 0;
5257                                        dbug(1, dprintf("3PTY OFF"));
5258                                        break;
5259                                }
5260                                PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5261                                sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5262                        }
5263                        break;
5264
5265                case CALL_DEFLECTION:
5266                        PUT_WORD(&SS_Ind[1], pty_cai[5]);
5267                        for (i = 0; i < max_appl; i++)
5268                        {
5269                                if (application[i].CDEnable)
5270                                {
5271                                        if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5272                                        application[i].CDEnable = false;
5273                                }
5274                        }
5275                        break;
5276
5277                case DEACTIVATION_DIVERSION:
5278                case ACTIVATION_DIVERSION:
5279                        if (!plci->appl) break;
5280                        PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5281                        PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5282                        sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5283                        plci_remove(plci);
5284                        break;
5285
5286                case DIVERSION_INTERROGATE_CFU:
5287                case DIVERSION_INTERROGATE_CFB:
5288                case DIVERSION_INTERROGATE_CFNR:
5289                case DIVERSION_INTERROGATE_NUM:
5290                case CCBS_REQUEST:
5291                case CCBS_DEACTIVATE:
5292                case CCBS_INTERROGATE:
5293                        if (!plci->appl) break;
5294                        switch (pty_cai[5])
5295                        {
5296                        case DIVERSION_INTERROGATE_CFU:
5297                        case DIVERSION_INTERROGATE_CFB:
5298                        case DIVERSION_INTERROGATE_CFNR:
5299                                dbug(1, dprintf("Interr_Div"));
5300                                PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5301                                pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5302                                break;
5303                        case DIVERSION_INTERROGATE_NUM:
5304                                dbug(1, dprintf("Interr_Num"));
5305                                PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5306                                pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5307                                break;
5308                        case CCBS_REQUEST:
5309                                dbug(1, dprintf("CCBS Request"));
5310                                PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5311                                pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5312                                break;
5313                        case CCBS_DEACTIVATE:
5314                                dbug(1, dprintf("CCBS Deactivate"));
5315                                PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5316                                pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5317                                break;
5318                        case CCBS_INTERROGATE:
5319                                dbug(1, dprintf("CCBS Interrogate"));
5320                                PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5321                                pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5322                                break;
5323                        }
5324                        PUT_WORD(&pty_cai[4], 0); /* Supplementary Service Reason */
5325                        PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5326                        sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5327                        plci_remove(plci);
5328                        break;
5329
5330                case ACTIVATION_MWI:
5331                case DEACTIVATION_MWI:
5332                        if (pty_cai[5] == ACTIVATION_MWI)
5333                        {
5334                                PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5335                        }
5336                        else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5337                        if (plci->cr_enquiry)
5338                        {
5339                                sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5340                                plci_remove(plci);
5341                        }
5342                        else
5343                        {
5344                                sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5345                        }
5346                        break;
5347                case MWI_INDICATION:
5348                        if (pty_cai[0] >= 0x12)
5349                        {
5350                                PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5351                                pty_cai[2] = pty_cai[0] - 2; /* len Parameter */
5352                                pty_cai[5] = pty_cai[0] - 5; /* Supplementary Service-specific parameter len */
5353                                if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5354                                {
5355                                        if (plci->internal_command == GET_MWI_STATE) /* result on Message Waiting Listen */
5356                                        {
5357                                                sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5358                                                plci_remove(plci);
5359                                                return;
5360                                        }
5361                                        else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5362                                        pty_cai[0] = 0;
5363                                }
5364                                else
5365                                {
5366                                        for (i = 0; i < max_appl; i++)
5367                                        {
5368                                                if (a->Notification_Mask[i]&SMASK_MWI)
5369                                                {
5370                                                        sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5371                                                        pty_cai[0] = 0;
5372                                                }
5373                                        }
5374                                }
5375
5376                                if (!pty_cai[0])
5377                                { /* acknowledge */
5378                                        facility[2] = 0; /* returncode */
5379                                }
5380                                else facility[2] = 0xff;
5381                        }
5382                        else
5383                        {
5384                                /* reject */
5385                                facility[2] = 0xff; /* returncode */
5386                        }
5387                        facility[0] = 2;
5388                        facility[1] = MWI_RESPONSE; /* Function */
5389                        add_p(plci, CAI, facility);
5390                        add_p(plci, ESC, multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5391                        sig_req(plci, S_SERVICE, 0);
5392                        send_req(plci);
5393                        plci->command = 0;
5394                        next_internal_command(Id, plci);
5395                        break;
5396                case CONF_ADD: /* OK */
5397                case CONF_BEGIN:
5398                case CONF_DROP:
5399                case CONF_ISOLATE:
5400                case CONF_REATTACH:
5401                case CONF_PARTYDISC:
5402                        CONF_Ind[0] = 9;
5403                        CONF_Ind[3] = 6;
5404                        switch (pty_cai[5])
5405                        {
5406                        case CONF_BEGIN:
5407                                PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5408                                if (pty_cai[0] == 6)
5409                                {
5410                                        d = pty_cai[6];
5411                                        PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5412                                }
5413                                else
5414                                {
5415                                        PUT_DWORD(&CONF_Ind[6], 0x0);
5416                                }
5417                                break;
5418                        case CONF_ISOLATE:
5419                                PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5420                                CONF_Ind[0] = 5;
5421                                CONF_Ind[3] = 2;
5422                                break;
5423                        case CONF_REATTACH:
5424                                PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5425                                CONF_Ind[0] = 5;
5426                                CONF_Ind[3] = 2;
5427                                break;
5428                        case CONF_DROP:
5429                                PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5430                                CONF_Ind[0] = 5;
5431                                CONF_Ind[3] = 2;
5432                                break;
5433                        case CONF_ADD:
5434                                PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5435                                d = pty_cai[6];
5436                                PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5437                                tplci = plci->relatedPTYPLCI;
5438                                if (tplci) tplci->ptyState = CONNECTED;
5439                                break;
5440                        case CONF_PARTYDISC:
5441                                CONF_Ind[0] = 7;
5442                                CONF_Ind[3] = 4;
5443                                PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5444                                d = pty_cai[6];
5445                                PUT_DWORD(&CONF_Ind[4], d); /* PartyID */
5446                                break;
5447                        }
5448                        plci->ptyState = CONNECTED;
5449                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5450                        break;
5451                case CCBS_INFO_RETAIN:
5452                case CCBS_ERASECALLLINKAGEID:
5453                case CCBS_STOP_ALERTING:
5454                        CONF_Ind[0] = 5;
5455                        CONF_Ind[3] = 2;
5456                        switch (pty_cai[5])
5457                        {
5458                        case CCBS_INFO_RETAIN:
5459                                PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5460                                break;
5461                        case CCBS_STOP_ALERTING:
5462                                PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5463                                break;
5464                        case CCBS_ERASECALLLINKAGEID:
5465                                PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5466                                CONF_Ind[0] = 7;
5467                                CONF_Ind[3] = 4;
5468                                CONF_Ind[6] = 0;
5469                                CONF_Ind[7] = 0;
5470                                break;
5471                        }
5472                        w = pty_cai[6];
5473                        PUT_WORD(&CONF_Ind[4], w); /* PartyID */
5474
5475                        if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5476                        {
5477                                sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5478                        }
5479                        else
5480                        {
5481                                for (i = 0; i < max_appl; i++)
5482                                        if (a->Notification_Mask[i] & SMASK_CCBS)
5483                                                sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5484                        }
5485                        break;
5486                }
5487                break;
5488        case CALL_HOLD_REJ:
5489                cau = parms[7];
5490                if (cau)
5491                {
5492                        i = _L3_CAUSE | cau[2];
5493                        if (cau[2] == 0) i = 0x3603;
5494                }
5495                else
5496                {
5497                        i = 0x3603;
5498                }
5499                PUT_WORD(&SS_Ind[1], S_HOLD);
5500                PUT_WORD(&SS_Ind[4], i);
5501                if (plci->SuppState == HOLD_REQUEST)
5502                {
5503                        plci->SuppState = IDLE;
5504                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5505                }
5506                break;
5507
5508        case CALL_HOLD_ACK:
5509                if (plci->SuppState == HOLD_REQUEST)
5510                {
5511                        plci->SuppState = CALL_HELD;
5512                        CodecIdCheck(a, plci);
5513                        start_internal_command(Id, plci, hold_save_command);
5514                }
5515                break;
5516
5517        case CALL_RETRIEVE_REJ:
5518                cau = parms[7];
5519                if (cau)
5520                {
5521                        i = _L3_CAUSE | cau[2];
5522                        if (cau[2] == 0) i = 0x3603;
5523                }
5524                else
5525                {
5526                        i = 0x3603;
5527                }
5528                PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5529                PUT_WORD(&SS_Ind[4], i);
5530                if (plci->SuppState == RETRIEVE_REQUEST)
5531                {
5532                        plci->SuppState = CALL_HELD;
5533                        CodecIdCheck(a, plci);
5534                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5535                }
5536                break;
5537
5538        case CALL_RETRIEVE_ACK:
5539                PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5540                if (plci->SuppState == RETRIEVE_REQUEST)
5541                {
5542                        plci->SuppState = IDLE;
5543                        plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5544                        plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5545                        if (plci->tel)
5546                        {
5547                                mixer_set_bchannel_id_esc(plci, plci->b_channel);
5548                                dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5549                                SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5550                                if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5551                                {
5552                                        dbug(1, dprintf("Get B-ch"));
5553                                        start_internal_command(Id, plci, retrieve_restore_command);
5554                                }
5555                                else
5556                                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5557                        }
5558                        else
5559                                start_internal_command(Id, plci, retrieve_restore_command);
5560                }
5561                break;
5562
5563        case INDICATE_IND:
5564                if (plci->State != LISTENING) {
5565                        sig_req(plci, HANGUP, 0);
5566                        send_req(plci);
5567                        break;
5568                }
5569                cip = find_cip(a, parms[4], parms[6]);
5570                cip_mask = 1L << cip;
5571                dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5572                bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5573                if (!remove_started && !a->adapter_disabled)
5574                {
5575                        group_optimization(a, plci);
5576                        for_each_set_bit(i, plci->group_optimization_mask_table, max_appl) {
5577                                if (application[i].Id
5578                                    && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5579                                    && CPN_filter_ok(parms[0], a, i)) {
5580                                        dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5581                                        __set_bit(i, plci->c_ind_mask_table);
5582                                        dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
5583                                        plci->State = INC_CON_PENDING;
5584                                        plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5585                                                CALL_DIR_IN | CALL_DIR_ANSWER;
5586                                        if (esc_chi[0]) {
5587                                                plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5588                                                mixer_set_bchannel_id_esc(plci, plci->b_channel);
5589                                        }
5590                                        /* if a listen on the ext controller is done, check if hook states */
5591                                        /* are supported or if just a on board codec must be activated     */
5592                                        if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5593                                                if (a->profile.Global_Options & HANDSET)
5594                                                        plci->tel = ADV_VOICE;
5595                                                else if (a->profile.Global_Options & ON_BOARD_CODEC)
5596                                                        plci->tel = CODEC;
5597                                                if (plci->tel) Id |= EXT_CONTROLLER;
5598                                                a->codec_listen[i] = plci;
5599                                        }
5600
5601                                        sendf(&application[i], _CONNECT_I, Id, 0,
5602                                              "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5603                                              parms[0],    /* CalledPartyNumber   */
5604                                              multi_CiPN_parms[0],    /* CallingPartyNumber  */
5605                                              parms[2],    /* CalledPartySubad    */
5606                                              parms[3],    /* CallingPartySubad   */
5607                                              parms[4],    /* BearerCapability    */
5608                                              parms[5],    /* LowLC               */
5609                                              parms[6],    /* HighLC              */
5610                                              ai_len,      /* nested struct add_i */
5611                                              add_i[0],    /* B channel info    */
5612                                              add_i[1],    /* keypad facility   */
5613                                              add_i[2],    /* user user data    */
5614                                              add_i[3],    /* nested facility   */
5615                                              multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5616                                                );
5617                                        SendSSExtInd(&application[i],
5618                                                     plci,
5619                                                     Id,
5620                                                     multi_ssext_parms);
5621                                        SendSetupInfo(&application[i],
5622                                                      plci,
5623                                                      Id,
5624                                                      parms,
5625                                                      SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5626                                }
5627                        }
5628                        dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
5629                }
5630                if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL)) {
5631                        sig_req(plci, HANGUP, 0);
5632                        send_req(plci);
5633                        plci->State = IDLE;
5634                }
5635                plci->notifiedcall = 0;
5636                a->listen_active--;
5637                listen_check(a);
5638                break;
5639
5640        case CALL_PEND_NOTIFY:
5641                plci->notifiedcall = 1;
5642                listen_check(a);
5643                break;
5644
5645        case CALL_IND:
5646        case CALL_CON:
5647                if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5648                {
5649                        if (plci->internal_command == PERM_COD_CONN_PEND)
5650                        {
5651                                if (plci->State == ADVANCED_VOICE_NOSIG)
5652                                {
5653                                        dbug(1, dprintf("***Codec OK"));
5654                                        if (a->AdvSignalPLCI)
5655                                        {
5656                                                tplci = a->AdvSignalPLCI;
5657                                                if (tplci->spoofed_msg)
5658                                                {
5659                                                        dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5660                                                        tplci->command = 0;
5661                                                        tplci->internal_command = 0;
5662                                                        x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5663                                                        switch (tplci->spoofed_msg)
5664                                                        {
5665                                                        case CALL_RES:
5666                                                                tplci->command = _CONNECT_I | RESPONSE;
5667                                                                api_load_msg(&tplci->saved_msg, saved_parms);
5668                                                                add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5669                                                                if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5670                                                                {
5671                                                                        /* early B3 connect (CIP mask bit 9) no release after a disc */
5672                                                                        add_p(tplci, LLI, "\x01\x01");
5673                                                                }
5674                                                                add_s(tplci, CONN_NR, &saved_parms[2]);
5675                                                                add_s(tplci, LLC, &saved_parms[4]);
5676                                                                add_ai(tplci, &saved_parms[5]);
5677                                                                tplci->State = INC_CON_ACCEPT;
5678                                                                sig_req(tplci, CALL_RES, 0);
5679                                                                send_req(tplci);
5680                                                                break;
5681
5682                                                        case AWAITING_SELECT_B:
5683                                                                dbug(1, dprintf("Select_B continue"));
5684                                                                start_internal_command(x_Id, tplci, select_b_command);
5685                                                                break;
5686
5687                                                        case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5688                                                                if (!tplci->Sig.Id)
5689                                                                {
5690                                                                        dbug(1, dprintf("No SigID!"));
5691                                                                        sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5692                                                                        plci_remove(tplci);
5693                                                                        break;
5694                                                                }
5695                                                                tplci->command = _MANUFACTURER_R;
5696                                                                api_load_msg(&tplci->saved_msg, saved_parms);
5697                                                                dir = saved_parms[2].info[0];
5698                                                                if (dir == 1) {
5699                                                                        sig_req(tplci, CALL_REQ, 0);
5700                                                                }
5701                                                                else if (!dir) {
5702                                                                        sig_req(tplci, LISTEN_REQ, 0);
5703                                                                }
5704                                                                send_req(tplci);
5705                                                                sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5706                                                                break;
5707
5708                                                        case (CALL_REQ | AWAITING_MANUF_CON):
5709                                                                sig_req(tplci, CALL_REQ, 0);
5710                                                                send_req(tplci);
5711                                                                break;
5712
5713                                                        case CALL_REQ:
5714                                                                if (!tplci->Sig.Id)
5715                                                                {
5716                                                                        dbug(1, dprintf("No SigID!"));
5717                                                                        sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5718                                                                        plci_remove(tplci);
5719                                                                        break;
5720                                                                }
5721                                                                tplci->command = _CONNECT_R;
5722                                                                api_load_msg(&tplci->saved_msg, saved_parms);
5723                                                                add_s(tplci, CPN, &saved_parms[1]);
5724                                                                add_s(tplci, DSA, &saved_parms[3]);
5725                                                                add_ai(tplci, &saved_parms[9]);
5726                                                                sig_req(tplci, CALL_REQ, 0);
5727                                                                send_req(tplci);
5728                                                                break;
5729
5730                                                        case CALL_RETRIEVE:
5731                                                                tplci->command = C_RETRIEVE_REQ;
5732                                                                sig_req(tplci, CALL_RETRIEVE, 0);
5733                                                                send_req(tplci);
5734                                                                break;
5735                                                        }
5736                                                        tplci->spoofed_msg = 0;
5737                                                        if (tplci->internal_command == 0)
5738                                                                next_internal_command(x_Id, tplci);
5739                                                }
5740                                        }
5741                                        next_internal_command(Id, plci);
5742                                        break;
5743                                }
5744                                dbug(1, dprintf("***Codec Hook Init Req"));
5745                                plci->internal_command = PERM_COD_HOOK;
5746                                add_p(plci, FTY, "\x01\x09");             /* Get Hook State*/
5747                                sig_req(plci, TEL_CTRL, 0);
5748                                send_req(plci);
5749                        }
5750                }
5751                else if (plci->command != _MANUFACTURER_R  /* old style permanent connect */
5752                         && plci->State != INC_ACT_PENDING)
5753                {
5754                        mixer_set_bchannel_id_esc(plci, plci->b_channel);
5755                        if (plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5756                        {
5757                                chi[2] = plci->b_channel;
5758                                SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5759                        }
5760                        sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5761                        plci->State = INC_ACT_PENDING;
5762                }
5763                break;
5764
5765        case TEL_CTRL:
5766                ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5767                if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5768                        switch (ie[1] & 0x91) {
5769                        case 0x80:   /* hook off */
5770                        case 0x81:
5771                                if (plci->internal_command == PERM_COD_HOOK)
5772                                {
5773                                        dbug(1, dprintf("init:hook_off"));
5774                                        plci->hook_state = ie[1];
5775                                        next_internal_command(Id, plci);
5776                                        break;
5777                                }
5778                                else /* ignore doubled hook indications */
5779                                {
5780                                        if (((plci->hook_state) & 0xf0) == 0x80)
5781                                        {
5782                                                dbug(1, dprintf("ignore hook"));
5783                                                break;
5784                                        }
5785                                        plci->hook_state = ie[1]&0x91;
5786                                }
5787                                /* check for incoming call pending */
5788                                /* and signal '+'.Appl must decide */
5789                                /* with connect_res if call must   */
5790                                /* accepted or not                 */
5791                                for (i = 0, tplci = NULL; i < max_appl; i++) {
5792                                        if (a->codec_listen[i]
5793                                            && (a->codec_listen[i]->State == INC_CON_PENDING
5794                                                || a->codec_listen[i]->State == INC_CON_ALERT)) {
5795                                                tplci = a->codec_listen[i];
5796                                                tplci->appl = &application[i];
5797                                        }
5798                                }
5799                                /* no incoming call, do outgoing call */
5800                                /* and signal '+' if outg. setup   */
5801                                if (!a->AdvSignalPLCI && !tplci) {
5802                                        if ((i = get_plci(a))) {
5803                                                a->AdvSignalPLCI = &a->plci[i - 1];
5804                                                tplci = a->AdvSignalPLCI;
5805                                                tplci->tel  = ADV_VOICE;
5806                                                PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5807                                                if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5808                                                        /* early B3 connect (CIP mask bit 9) no release after a disc */
5809                                                        add_p(tplci, LLI, "\x01\x01");
5810                                                }
5811                                                add_p(tplci, CAI, voice_cai);
5812                                                add_p(tplci, OAD, a->TelOAD);
5813                                                add_p(tplci, OSA, a->TelOSA);
5814                                                add_p(tplci, SHIFT | 6, NULL);
5815                                                add_p(tplci, SIN, "\x02\x01\x00");
5816                                                add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5817                                                sig_req(tplci, ASSIGN, DSIG_ID);
5818                                                a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5819                                                a->AdvSignalPLCI->command = 0;
5820                                                tplci->appl = a->AdvSignalAppl;
5821                                                tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5822                                                send_req(tplci);
5823                                        }
5824
5825                                }
5826
5827                                if (!tplci) break;
5828                                Id = ((word)tplci->Id << 8) | a->Id;
5829                                Id |= EXT_CONTROLLER;
5830                                sendf(tplci->appl,
5831                                      _FACILITY_I,
5832                                      Id,
5833                                      0,
5834                                      "ws", (word)0, "\x01+");
5835                                break;
5836
5837                        case 0x90:   /* hook on  */
5838                        case 0x91:
5839                                if (plci->internal_command == PERM_COD_HOOK)
5840                                {
5841                                        dbug(1, dprintf("init:hook_on"));
5842                                        plci->hook_state = ie[1] & 0x91;
5843                                        next_internal_command(Id, plci);
5844                                        break;
5845                                }
5846                                else /* ignore doubled hook indications */
5847                                {
5848                                        if (((plci->hook_state) & 0xf0) == 0x90) break;
5849                                        plci->hook_state = ie[1] & 0x91;
5850                                }
5851                                /* hangup the adv. voice call and signal '-' to the appl */
5852                                if (a->AdvSignalPLCI) {
5853                                        Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5854                                        if (plci->tel) Id |= EXT_CONTROLLER;
5855                                        sendf(a->AdvSignalAppl,
5856                                              _FACILITY_I,
5857                                              Id,
5858                                              0,
5859                                              "ws", (word)0, "\x01-");
5860                                        a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5861                                        a->AdvSignalPLCI->command = 0;
5862                                        sig_req(a->AdvSignalPLCI, HANGUP, 0);
5863                                        send_req(a->AdvSignalPLCI);
5864                                }
5865                                break;
5866                        }
5867                }
5868                break;
5869
5870        case RESUME:
5871                __clear_bit(plci->appl->Id - 1, plci->c_ind_mask_table);
5872                PUT_WORD(&resume_cau[4], GOOD);
5873                sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
5874                break;
5875
5876        case SUSPEND:
5877                bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5878
5879                if (plci->NL.Id && !plci->nl_remove_id) {
5880                        mixer_remove(plci);
5881                        nl_req_ncci(plci, REMOVE, 0);
5882                }
5883                if (!plci->sig_remove_id) {
5884                        plci->internal_command = 0;
5885                        sig_req(plci, REMOVE, 0);
5886                }
5887                send_req(plci);
5888                if (!plci->channels) {
5889                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
5890                        sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
5891                }
5892                break;
5893
5894        case SUSPEND_REJ:
5895                break;
5896
5897        case HANGUP:
5898                plci->hangup_flow_ctrl_timer = 0;
5899                if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
5900                cau = parms[7];
5901                if (cau) {
5902                        i = _L3_CAUSE | cau[2];
5903                        if (cau[2] == 0) i = 0;
5904                        else if (cau[2] == 8) i = _L1_ERROR;
5905                        else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
5906                        else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
5907                }
5908                else {
5909                        i = _L3_ERROR;
5910                }
5911
5912                if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
5913                {
5914                        for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
5915                                sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
5916                }
5917                else
5918                {
5919                        bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5920                }
5921                if (!plci->appl)
5922                {
5923                        if (plci->State == LISTENING)
5924                        {
5925                                plci->notifiedcall = 0;
5926                                a->listen_active--;
5927                        }
5928                        plci->State = INC_DIS_PENDING;
5929                        if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
5930                        {
5931                                plci->State = IDLE;
5932                                if (plci->NL.Id && !plci->nl_remove_id)
5933                                {
5934                                        mixer_remove(plci);
5935                                        nl_req_ncci(plci, REMOVE, 0);
5936                                }
5937                                if (!plci->sig_remove_id)
5938                                {
5939                                        plci->internal_command = 0;
5940                                        sig_req(plci, REMOVE, 0);
5941                                }
5942                                send_req(plci);
5943                        }
5944                }
5945                else
5946                {
5947                        /* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
5948                        /* result in a second HANGUP! Don't generate another        */
5949                        /* DISCONNECT                                               */
5950                        if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
5951                        {
5952                                if (plci->State == RESUMING)
5953                                {
5954                                        PUT_WORD(&resume_cau[4], i);
5955                                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
5956                                }
5957                                plci->State = INC_DIS_PENDING;
5958                                sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
5959                        }
5960                }
5961                break;
5962
5963        case SSEXT_IND:
5964                SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5965                break;
5966
5967        case VSWITCH_REQ:
5968                VSwitchReqInd(plci, Id, multi_vswitch_parms);
5969                break;
5970        case VSWITCH_IND:
5971                if (plci->relatedPTYPLCI &&
5972                    plci->vswitchstate == 3 &&
5973                    plci->relatedPTYPLCI->vswitchstate == 3 &&
5974                    parms[MAXPARMSIDS - 1][0])
5975                {
5976                        add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
5977                        sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
5978                        send_req(plci->relatedPTYPLCI);
5979                }
5980                else VSwitchReqInd(plci, Id, multi_vswitch_parms);
5981                break;
5982
5983        }
5984}
5985
5986
5987static void SendSetupInfo(APPL *appl, PLCI *plci, dword Id, byte **parms, byte Info_Sent_Flag)
5988{
5989        word i;
5990        byte *ie;
5991        word Info_Number;
5992        byte *Info_Element;
5993        word Info_Mask = 0;
5994
5995        dbug(1, dprintf("SetupInfo"));
5996
5997        for (i = 0; i < MAXPARMSIDS; i++) {
5998                ie = parms[i];
5999                Info_Number = 0;
6000                Info_Element = ie;
6001                if (ie[0]) {
6002                        switch (i) {
6003                        case 0:
6004                                dbug(1, dprintf("CPN "));
6005                                Info_Number = 0x0070;
6006                                Info_Mask = 0x80;
6007                                Info_Sent_Flag = true;
6008                                break;
6009                        case 8:  /* display      */
6010                                dbug(1, dprintf("display(%d)", i));
6011                                Info_Number = 0x0028;
6012                                Info_Mask = 0x04;
6013                                Info_Sent_Flag = true;
6014                                break;
6015                        case 16: /* Channel Id */
6016                                dbug(1, dprintf("CHI"));
6017                                Info_Number = 0x0018;
6018                                Info_Mask = 0x100;
6019                                Info_Sent_Flag = true;
6020                                mixer_set_bchannel_id(plci, Info_Element);
6021                                break;
6022                        case 19: /* Redirected Number */
6023                                dbug(1, dprintf("RDN"));
6024                                Info_Number = 0x0074;
6025                                Info_Mask = 0x400;
6026                                Info_Sent_Flag = true;
6027                                break;
6028                        case 20: /* Redirected Number extended */
6029                                dbug(1, dprintf("RDX"));
6030                                Info_Number = 0x0073;
6031                                Info_Mask = 0x400;
6032                                Info_Sent_Flag = true;
6033                                break;
6034                        case 22: /* Redirecing Number  */
6035                                dbug(1, dprintf("RIN"));
6036                                Info_Number = 0x0076;
6037                                Info_Mask = 0x400;
6038                                Info_Sent_Flag = true;
6039                                break;
6040                        default:
6041                                Info_Number = 0;
6042                                break;
6043                        }
6044                }
6045
6046                if (i == MAXPARMSIDS - 2) { /* to indicate the message type "Setup" */
6047                        Info_Number = 0x8000 | 5;
6048                        Info_Mask = 0x10;
6049                        Info_Element = "";
6050                }
6051
6052                if (Info_Sent_Flag && Info_Number) {
6053                        if (plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask) {
6054                                sendf(appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6055                        }
6056                }
6057        }
6058}
6059
6060
6061static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6062{
6063        word i;
6064        word j;
6065        word k;
6066        byte *ie;
6067        word Info_Number;
6068        byte *Info_Element;
6069        word Info_Mask = 0;
6070        static byte charges[5] = {4, 0, 0, 0, 0};
6071        static byte cause[] = {0x02, 0x80, 0x00};
6072        APPL *appl;
6073
6074        dbug(1, dprintf("InfoParse "));
6075
6076        if (
6077                !plci->appl
6078                && !plci->State
6079                && plci->Sig.Ind != NCR_FACILITY
6080                )
6081        {
6082                dbug(1, dprintf("NoParse "));
6083                return;
6084        }
6085        cause[2] = 0;
6086        for (i = 0; i < MAXPARMSIDS; i++) {
6087                ie = parms[i];
6088                Info_Number = 0;
6089                Info_Element = ie;
6090                if (ie[0]) {
6091                        switch (i) {
6092                        case 0:
6093                                dbug(1, dprintf("CPN "));
6094                                Info_Number = 0x0070;
6095                                Info_Mask   = 0x80;
6096                                break;
6097                        case 7: /* ESC_CAU */
6098                                dbug(1, dprintf("cau(0x%x)", ie[2]));
6099                                Info_Number = 0x0008;
6100                                Info_Mask = 0x00;
6101                                cause[2] = ie[2];
6102                                Info_Element = NULL;
6103                                break;
6104                        case 8:  /* display      */
6105                                dbug(1, dprintf("display(%d)", i));
6106                                Info_Number = 0x0028;
6107                                Info_Mask = 0x04;
6108                                break;
6109                        case 9:  /* Date display */
6110                                dbug(1, dprintf("date(%d)", i));
6111                                Info_Number = 0x0029;
6112                                Info_Mask = 0x02;
6113                                break;
6114                        case 10: /* charges */
6115                                for (j = 0; j < 4; j++) charges[1 + j] = 0;
6116                                for (j = 0; j < ie[0] && !(ie[1 + j] & 0x80); j++);
6117                                for (k = 1, j++; j < ie[0] && k <= 4; j++, k++) charges[k] = ie[1 + j];
6118                                Info_Number = 0x4000;
6119                                Info_Mask = 0x40;
6120                                Info_Element = charges;
6121                                break;
6122                        case 11: /* user user info */
6123                                dbug(1, dprintf("uui"));
6124                                Info_Number = 0x007E;
6125                                Info_Mask = 0x08;
6126                                break;
6127                        case 12: /* congestion receiver ready */
6128                                dbug(1, dprintf("clRDY"));
6129                                Info_Number = 0x00B0;
6130                                Info_Mask = 0x08;
6131                                Info_Element = "";
6132                                break;
6133                        case 13: /* congestion receiver not ready */
6134                                dbug(1, dprintf("clNRDY"));
6135                                Info_Number = 0x00BF;
6136                                Info_Mask = 0x08;
6137                                Info_Element = "";
6138                                break;
6139                        case 15: /* Keypad Facility */
6140                                dbug(1, dprintf("KEY"));
6141                                Info_Number = 0x002C;
6142                                Info_Mask = 0x20;
6143                                break;
6144                        case 16: /* Channel Id */
6145                                dbug(1, dprintf("CHI"));
6146                                Info_Number = 0x0018;
6147                                Info_Mask = 0x100;
6148                                mixer_set_bchannel_id(plci, Info_Element);
6149                                break;
6150                        case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6151                                dbug(1, dprintf("q9cau(0x%x)", ie[2]));
6152                                if (!cause[2] || cause[2] < 0x80) break;  /* eg. layer 1 error */
6153                                Info_Number = 0x0008;
6154                                Info_Mask = 0x01;
6155                                if (cause[2] != ie[2]) Info_Element = cause;
6156                                break;
6157                        case 19: /* Redirected Number */
6158                                dbug(1, dprintf("RDN"));
6159                                Info_Number = 0x0074;
6160                                Info_Mask = 0x400;
6161                                break;
6162                        case 22: /* Redirecing Number  */
6163                                dbug(1, dprintf("RIN"));
6164                                Info_Number = 0x0076;
6165                                Info_Mask = 0x400;
6166                                break;
6167                        case 23: /* Notification Indicator  */
6168                                dbug(1, dprintf("NI"));
6169                                Info_Number = (word)NI;
6170                                Info_Mask = 0x210;
6171                                break;
6172                        case 26: /* Call State  */
6173                                dbug(1, dprintf("CST"));
6174                                Info_Number = (word)CST;
6175                                Info_Mask = 0x01; /* do with cause i.e. for now */
6176                                break;
6177                        case MAXPARMSIDS - 2:  /* Escape Message Type, must be the last indication */
6178                                dbug(1, dprintf("ESC/MT[0x%x]", ie[3]));
6179                                Info_Number = 0x8000 | ie[3];
6180                                if (iesent) Info_Mask = 0xffff;
6181                                else  Info_Mask = 0x10;
6182                                Info_Element = "";
6183                                break;
6184                        default:
6185                                Info_Number  = 0;
6186                                Info_Mask    = 0;
6187                                Info_Element = "";
6188                                break;
6189                        }
6190                }
6191
6192                if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6193                {
6194                        for (j = 0; j < max_appl; j++)
6195                        {
6196                                appl = &application[j];
6197                                if (Info_Number
6198                                    && appl->Id
6199                                    && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6200                                {
6201                                        dbug(1, dprintf("NCR_Ind"));
6202                                        iesent = true;
6203                                        sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6204                                }
6205                        }
6206                }
6207                else if (!plci->appl)
6208                { /* overlap receiving broadcast */
6209                        if (Info_Number == CPN
6210                            || Info_Number == KEY
6211                            || Info_Number == NI
6212                            || Info_Number == DSP
6213                            || Info_Number == UUI)
6214                        {
6215                                for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
6216                                        dbug(1, dprintf("Ovl_Ind"));
6217                                        iesent = true;
6218                                        sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6219                                }
6220                        }
6221                }               /* all other signalling states */
6222                else if (Info_Number
6223                         && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6224                {
6225                        dbug(1, dprintf("Std_Ind"));
6226                        iesent = true;
6227                        sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6228                }
6229        }
6230}
6231
6232
6233static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6234                        dword info_mask, byte setupParse)
6235{
6236        word i;
6237        word j;
6238        byte *ie;
6239        word Info_Number;
6240        byte *Info_Element;
6241        APPL *appl;
6242        word Info_Mask = 0;
6243        byte iesent = 0;
6244
6245        if (
6246                !plci->appl
6247                && !plci->State
6248                && plci->Sig.Ind != NCR_FACILITY
6249                && !setupParse
6250                )
6251        {
6252                dbug(1, dprintf("NoM-IEParse "));
6253                return 0;
6254        }
6255        dbug(1, dprintf("M-IEParse "));
6256
6257        for (i = 0; i < MAX_MULTI_IE; i++)
6258        {
6259                ie = parms[i];
6260                Info_Number = 0;
6261                Info_Element = ie;
6262                if (ie[0])
6263                {
6264                        dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci->Sig.Ind, ie_type));
6265                        Info_Number = (word)ie_type;
6266                        Info_Mask = (word)info_mask;
6267                }
6268
6269                if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6270                {
6271                        for (j = 0; j < max_appl; j++)
6272                        {
6273                                appl = &application[j];
6274                                if (Info_Number
6275                                    && appl->Id
6276                                    && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6277                                {
6278                                        iesent = true;
6279                                        dbug(1, dprintf("Mlt_NCR_Ind"));
6280                                        sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6281                                }
6282                        }
6283                }
6284                else if (!plci->appl && Info_Number)
6285                {                                        /* overlap receiving broadcast */
6286                        for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
6287                                iesent = true;
6288                                dbug(1, dprintf("Mlt_Ovl_Ind"));
6289                                sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6290                        }
6291                }                                        /* all other signalling states */
6292                else if (Info_Number
6293                         && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6294                {
6295                        iesent = true;
6296                        dbug(1, dprintf("Mlt_Std_Ind"));
6297                        sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6298                }
6299        }
6300        return iesent;
6301}
6302
6303static void SendSSExtInd(APPL *appl, PLCI *plci, dword Id, byte **parms)
6304{
6305        word i;
6306        /* Format of multi_ssext_parms[i][]:
6307           0 byte length
6308           1 byte SSEXTIE
6309           2 byte SSEXT_REQ/SSEXT_IND
6310           3 byte length
6311           4 word SSExtCommand
6312           6... Params
6313        */
6314        if (
6315                plci
6316                && plci->State
6317                && plci->Sig.Ind != NCR_FACILITY
6318                )
6319                for (i = 0; i < MAX_MULTI_IE; i++)
6320                {
6321                        if (parms[i][0] < 6) continue;
6322                        if (parms[i][2] == SSEXT_REQ) continue;
6323
6324                        if (appl)
6325                        {
6326                                parms[i][0] = 0; /* kill it */
6327                                sendf(appl, _MANUFACTURER_I,
6328                                      Id,
6329                                      0,
6330                                      "dwS",
6331                                      _DI_MANU_ID,
6332                                      _DI_SSEXT_CTRL,
6333                                      &parms[i][3]);
6334                        }
6335                        else if (plci->appl)
6336                        {
6337                                parms[i][0] = 0; /* kill it */
6338                                sendf(plci->appl, _MANUFACTURER_I,
6339                                      Id,
6340                                      0,
6341                                      "dwS",
6342                                      _DI_MANU_ID,
6343                                      _DI_SSEXT_CTRL,
6344                                      &parms[i][3]);
6345                        }
6346                }
6347};
6348
6349static void nl_ind(PLCI *plci)
6350{
6351        byte ch;
6352        word ncci;
6353        dword Id;
6354        DIVA_CAPI_ADAPTER *a;
6355        word NCCIcode;
6356        APPL *APPLptr;
6357        word count;
6358        word Num;
6359        word i, ncpi_state;
6360        byte len, ncci_state;
6361        word msg;
6362        word info = 0;
6363        word fax_feature_bits;
6364        byte fax_send_edata_ack;
6365        static byte v120_header_buffer[2 + 3];
6366        static word fax_info[] = {
6367                0,                     /* T30_SUCCESS                        */
6368                _FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
6369                _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
6370                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
6371                _FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
6372                _FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
6373                _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
6374                _FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
6375                _FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
6376                _FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
6377                _FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
6378                _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
6379                _FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
6380                _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
6381                _FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
6382                _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
6383                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
6384                _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
6385                _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
6386                _FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
6387                _FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
6388                _FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
6389                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
6390                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
6391                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
6392                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
6393                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
6394                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
6395                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
6396                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
6397                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
6398                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
6399                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
6400                0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
6401                0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
6402                0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
6403                _FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
6404                _FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
6405                _FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
6406                _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
6407                _FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
6408                _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6409                _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
6410                _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
6411                _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
6412                _FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
6413                _FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
6414        };
6415
6416        byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6417
6418
6419        static word rtp_info[] = {
6420                GOOD,                  /* RTP_SUCCESS                       */
6421                0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
6422        };
6423
6424        static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6425                {
6426                        0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6427                        0x00000000, 0x00000000, 0x00000000, 0x00000000
6428                };
6429
6430        ch = plci->NL.IndCh;
6431        a = plci->adapter;
6432        ncci = a->ch_ncci[ch];
6433        Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6434        if (plci->tel) Id |= EXT_CONTROLLER;
6435        APPLptr = plci->appl;
6436        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",
6437                        plci->NL.Id, Id, plci->Id, plci->tel, plci->State, ch, plci->channels, plci->NL.Ind & 0x0f));
6438
6439        /* in the case if no connect_active_Ind was sent to the appl we wait for */
6440
6441        if (plci->nl_remove_id)
6442        {
6443                plci->NL.RNR = 2; /* discard */
6444                dbug(1, dprintf("NL discard while remove pending"));
6445                return;
6446        }
6447        if ((plci->NL.Ind & 0x0f) == N_CONNECT)
6448        {
6449                if (plci->State == INC_DIS_PENDING
6450                    || plci->State == OUTG_DIS_PENDING
6451                    || plci->State == IDLE)
6452                {
6453                        plci->NL.RNR = 2; /* discard */
6454                        dbug(1, dprintf("discard n_connect"));
6455                        return;
6456                }
6457                if (plci->State < INC_ACT_PENDING)
6458                {
6459                        plci->NL.RNR = 1; /* flow control */
6460                        channel_x_off(plci, ch, N_XON_CONNECT_IND);
6461                        return;
6462                }
6463        }
6464
6465        if (!APPLptr)                         /* no application or invalid data */
6466        {                                    /* while reloading the DSP        */
6467                dbug(1, dprintf("discard1"));
6468                plci->NL.RNR = 2;
6469                return;
6470        }
6471
6472        if (((plci->NL.Ind & 0x0f) == N_UDATA)
6473            && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6474                || (plci->B2_prot == 7)
6475                || (plci->B3_prot == 7)))
6476        {
6477                plci->ncpi_buffer[0] = 0;
6478
6479                ncpi_state = plci->ncpi_state;
6480                if (plci->NL.complete == 1)
6481                {
6482                        byte *data = &plci->NL.RBuffer->P[0];
6483
6484                        if ((plci->NL.RBuffer->length >= 12)
6485                            && ((*data == DSP_UDATA_INDICATION_DCD_ON)
6486                                || (*data == DSP_UDATA_INDICATION_CTS_ON)))
6487                        {
6488                                word conn_opt, ncpi_opt = 0x00;
6489/*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6490
6491                                if (*data == DSP_UDATA_INDICATION_DCD_ON)
6492                                        plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6493                                if (*data == DSP_UDATA_INDICATION_CTS_ON)
6494                                        plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6495
6496                                data++;    /* indication code */
6497                                data += 2; /* timestamp */
6498                                if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6499                                        ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6500                                data++;    /* connected norm */
6501                                conn_opt = GET_WORD(data);
6502                                data += 2; /* connected options */
6503
6504                                PUT_WORD(&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6505
6506                                if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6507                                {
6508                                        ncpi_opt |= MDM_NCPI_ECM_V42;
6509                                }
6510                                else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6511                                {
6512                                        ncpi_opt |= MDM_NCPI_ECM_MNP;
6513                                }
6514                                else
6515                                {
6516                                        ncpi_opt |= MDM_NCPI_TRANSPARENT;
6517                                }
6518                                if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6519                                {
6520                                        ncpi_opt |= MDM_NCPI_COMPRESSED;
6521                                }
6522                                PUT_WORD(&(plci->ncpi_buffer[3]), ncpi_opt);
6523                                plci->ncpi_buffer[0] = 4;
6524
6525                                plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6526                        }
6527                }
6528                if (plci->B3_prot == 7)
6529                {
6530                        if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6531                            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6532                            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6533                        {
6534                                a->ncci_state[ncci] = INC_ACT_PENDING;
6535                                sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6536                                plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6537                        }
6538                }
6539
6540                if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
6541                      & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6542                    || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6543                    || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6544
6545                {
6546                        plci->NL.RNR = 2;
6547                        return;
6548                }
6549        }
6550
6551        if (plci->NL.complete == 2)
6552        {
6553                if (((plci->NL.Ind & 0x0f) == N_UDATA)
6554                    && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6555                {
6556                        switch (plci->RData[0].P[0])
6557                        {
6558
6559                        case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6560                                if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6561                                        sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01X");
6562                                break;
6563                        case DTMF_UDATA_INDICATION_ANSWER_TONE:
6564                                if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6565                                        sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01Y");
6566                                break;
6567                        case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6568                                dtmf_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6569                                break;
6570                        case DTMF_UDATA_INDICATION_DIGITS_SENT:
6571                                dtmf_confirmation(Id, plci);
6572                                break;
6573
6574
6575                        case UDATA_INDICATION_MIXER_TAP_DATA:
6576                                capidtmf_recv_process_block(&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6577                                i = capidtmf_indication(&(plci->capidtmf_state), dtmf_code_buffer + 1);
6578                                if (i != 0)
6579                                {
6580                                        dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6581                                        dtmf_indication(Id, plci, dtmf_code_buffer, (word)(i + 1));
6582                                }
6583                                break;
6584
6585
6586                        case UDATA_INDICATION_MIXER_COEFS_SET:
6587                                mixer_indication_coefs_set(Id, plci);
6588                                break;
6589                        case UDATA_INDICATION_XCONNECT_FROM:
6590                                mixer_indication_xconnect_from(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6591                                break;
6592                        case UDATA_INDICATION_XCONNECT_TO:
6593                                mixer_indication_xconnect_to(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6594                                break;
6595
6596
6597                        case LEC_UDATA_INDICATION_DISABLE_DETECT:
6598                                ec_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6599                                break;
6600
6601
6602
6603                        default:
6604                                break;
6605                        }
6606                }
6607                else
6608                {
6609                        if ((plci->RData[0].PLength != 0)
6610                            && ((plci->B2_prot == B2_V120_ASYNC)
6611                                || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6612                                || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6613                        {
6614
6615                                sendf(plci->appl, _DATA_B3_I, Id, 0,
6616                                      "dwww",
6617                                      plci->RData[1].P,
6618                                      (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6619                                      plci->RNum,
6620                                      plci->RFlags);
6621
6622                        }
6623                        else
6624                        {
6625
6626                                sendf(plci->appl, _DATA_B3_I, Id, 0,
6627                                      "dwww",
6628                                      plci->RData[0].P,
6629                                      plci->RData[0].PLength,
6630                                      plci->RNum,
6631                                      plci->RFlags);
6632
6633                        }
6634                }
6635                return;
6636        }
6637
6638        fax_feature_bits = 0;
6639        if ((plci->NL.Ind & 0x0f) == N_CONNECT ||
6640            (plci->NL.Ind & 0x0f) == N_CONNECT_ACK ||
6641            (plci->NL.Ind & 0x0f) == N_DISC ||
6642            (plci->NL.Ind & 0x0f) == N_EDATA ||
6643            (plci->NL.Ind & 0x0f) == N_DISC_ACK)
6644        {
6645                info = 0;
6646                plci->ncpi_buffer[0] = 0;
6647                switch (plci->B3_prot) {
6648                case  0: /*XPARENT*/
6649                case  1: /*T.90 NL*/
6650                        break;    /* no network control protocol info - jfr */
6651                case  2: /*ISO8202*/
6652                case  3: /*X25 DCE*/
6653                        for (i = 0; i < plci->NL.RLength; i++) plci->ncpi_buffer[4 + i] = plci->NL.RBuffer->P[i];
6654                        plci->ncpi_buffer[0] = (byte)(i + 3);
6655                        plci->ncpi_buffer[1] = (byte)(plci->NL.Ind & N_D_BIT ? 1 : 0);
6656                        plci->ncpi_buffer[2] = 0;
6657                        plci->ncpi_buffer[3] = 0;
6658                        break;
6659                case  4: /*T.30 - FAX*/
6660                case  5: /*T.30 - FAX*/
6661                        if (plci->NL.RLength >= sizeof(T30_INFO))
6662                        {
6663                                dbug(1, dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6664                                len = 9;
6665                                PUT_WORD(&(plci->ncpi_buffer[1]), ((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6666                                fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6667                                i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6668                                if (plci->B3_prot == 5)
6669                                {
6670                                        if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6671                                                i |= 0x8000; /* This is not an ECM connection */
6672                                        if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6673                                                i |= 0x4000; /* This is a connection with MMR compression */
6674                                        if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6675                                                i |= 0x2000; /* This is a connection with MR compression */
6676                                        if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6677                                                i |= 0x0004; /* More documents */
6678                                        if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6679                                                i |= 0x0002; /* Fax-polling indication */
6680                                }
6681                                dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits, i));
6682                                PUT_WORD(&(plci->ncpi_buffer[3]), i);
6683                                PUT_WORD(&(plci->ncpi_buffer[5]), ((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6684                                plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6685                                plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6686                                plci->ncpi_buffer[len] = 0;
6687                                if (((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6688                                {
6689                                        plci->ncpi_buffer[len] = 20;
6690                                        for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6691                                                plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6692                                }
6693                                if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6694                                {
6695                                        if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6696                                                info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6697                                        else
6698                                                info = _FAX_PROTOCOL_ERROR;
6699                                }
6700
6701                                if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6702                                    & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6703                                {
6704                                        i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6705                                        while (i < plci->NL.RBuffer->length)
6706                                                plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6707                                }
6708
6709                                plci->ncpi_buffer[0] = len;
6710                                fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6711                                PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6712
6713                                plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6714                                if (((plci->NL.Ind & 0x0f) == N_CONNECT_ACK)
6715                                    || (((plci->NL.Ind & 0x0f) == N_CONNECT)
6716                                        && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6717                                    || (((plci->NL.Ind & 0x0f) == N_EDATA)
6718                                        && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6719                                            || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6720                                            || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6721                                {
6722                                        plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6723                                }
6724                                if (((plci->NL.Ind & 0x0f) == N_DISC)
6725                                    || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)
6726                                    || (((plci->NL.Ind & 0x0f) == N_EDATA)
6727                                        && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6728                                {
6729                                        plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6730                                }
6731                        }
6732                        break;
6733
6734                case B3_RTP:
6735                        if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6736                        {
6737                                if (plci->NL.RLength != 0)
6738                                {
6739                                        info = rtp_info[plci->NL.RBuffer->P[0]];
6740                                        plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6741                                        for (i = 1; i < plci->NL.RLength; i++)
6742                                                plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6743                                }
6744                        }
6745                        break;
6746
6747                }
6748                plci->NL.RNR = 2;
6749        }
6750        switch (plci->NL.Ind & 0x0f) {
6751        case N_EDATA:
6752                if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6753                {
6754                        dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6755                                        ((T30_INFO *)plci->NL.RBuffer->P)->code));
6756                        fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6757
6758                        if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6759                            && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6760                            && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6761                            && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6762                            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6763                            && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6764                        {
6765                                ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6766                                sendf(plci->appl, _MANUFACTURER_I, Id, 0, "dwbS", _DI_MANU_ID, _DI_NEGOTIATE_B3,
6767                                      (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6768                                plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6769                                if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6770                                        fax_send_edata_ack = false;
6771                        }
6772
6773                        if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6774                        {
6775                                switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6776                                {
6777                                case EDATA_T30_DIS:
6778                                        if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6779                                            && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6780                                            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6781                                            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6782                                        {
6783                                                a->ncci_state[ncci] = INC_ACT_PENDING;
6784                                                if (plci->B3_prot == 4)
6785                                                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6786                                                else
6787                                                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6788                                                plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6789                                        }
6790                                        break;
6791
6792                                case EDATA_T30_TRAIN_OK:
6793                                        if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6794                                            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6795                                            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6796                                        {
6797                                                if (plci->B3_prot == 4)
6798                                                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6799                                                else
6800                                                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6801                                                plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6802                                        }
6803                                        break;
6804
6805                                case EDATA_T30_EOP_CAPI:
6806                                        if (a->ncci_state[ncci] == CONNECTED)
6807                                        {
6808                                                sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", GOOD, plci->ncpi_buffer);
6809                                                a->ncci_state[ncci] = INC_DIS_PENDING;
6810                                                plci->ncpi_state = 0;
6811                                                fax_send_edata_ack = false;
6812                                        }
6813                                        break;
6814                                }
6815                        }
6816                        else
6817                        {
6818                                switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6819                                {
6820                                case EDATA_T30_TRAIN_OK:
6821                                        if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6822                                            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6823                                            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6824                                        {
6825                                                if (plci->B3_prot == 4)
6826                                                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6827                                                else
6828                                                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6829                                                plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6830                                        }
6831                                        break;
6832                                }
6833                        }
6834                        if (fax_send_edata_ack)
6835                        {
6836                                ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6837                                plci->fax_edata_ack_length = 1;
6838                                start_internal_command(Id, plci, fax_edata_ack_command);
6839                        }
6840                }
6841                else
6842                {
6843                        dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6844                }
6845                break;
6846        case N_CONNECT:
6847                if (!a->ch_ncci[ch])
6848                {
6849                        ncci = get_ncci(plci, ch, 0);
6850                        Id = (Id & 0xffff) | (((dword) ncci) << 16);
6851                }
6852                dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6853                                ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6854
6855                msg = _CONNECT_B3_I;
6856                if (a->ncci_state[ncci] == IDLE)
6857                        plci->channels++;
6858                else if (plci->B3_prot == 1)
6859                        msg = _CONNECT_B3_T90_ACTIVE_I;
6860
6861                a->ncci_state[ncci] = INC_CON_PENDING;
6862                if (plci->B3_prot == 4)
6863                        sendf(plci->appl, msg, Id, 0, "s", "");
6864                else
6865                        sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6866                break;
6867        case N_CONNECT_ACK:
6868                dbug(1, dprintf("N_connect_Ack"));
6869                if (plci->internal_command_queue[0]
6870                    && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6871                        || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6872                        || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6873                {
6874                        (*(plci->internal_command_queue[0]))(Id, plci, 0);
6875                        if (!plci->internal_command)
6876                                next_internal_command(Id, plci);
6877                        break;
6878                }
6879                msg = _CONNECT_B3_ACTIVE_I;
6880                if (plci->B3_prot == 1)
6881                {
6882                        if (a->ncci_state[ncci] != OUTG_CON_PENDING)
6883                                msg = _CONNECT_B3_T90_ACTIVE_I;
6884                        a->ncci_state[ncci] = INC_ACT_PENDING;
6885                        sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6886                }
6887                else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
6888                {
6889                        if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6890                            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6891                            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6892                        {
6893                                a->ncci_state[ncci] = INC_ACT_PENDING;
6894                                if (plci->B3_prot == 4)
6895                                        sendf(plci->appl, msg, Id, 0, "s", "");
6896                                else
6897                                        sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6898                                plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6899                        }
6900                }
6901                else
6902                {
6903                        a->ncci_state[ncci] = INC_ACT_PENDING;
6904                        sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6905                }
6906                if (plci->adjust_b_restore)
6907                {
6908                        plci->adjust_b_restore = false;
6909                        start_internal_command(Id, plci, adjust_b_restore);
6910                }
6911                break;
6912        case N_DISC:
6913        case N_DISC_ACK:
6914                if (plci->internal_command_queue[0]
6915                    && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
6916                        || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
6917                        || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
6918                {
6919                        (*(plci->internal_command_queue[0]))(Id, plci, 0);
6920                        if (!plci->internal_command)
6921                                next_internal_command(Id, plci);
6922                }
6923                ncci_state = a->ncci_state[ncci];
6924                ncci_remove(plci, ncci, false);
6925
6926                /* with N_DISC or N_DISC_ACK the IDI frees the respective   */
6927                /* channel, so we cannot store the state in ncci_state! The */
6928                /* information which channel we received a N_DISC is thus   */
6929                /* stored in the inc_dis_ncci_table buffer.                 */
6930                for (i = 0; plci->inc_dis_ncci_table[i]; i++);
6931                plci->inc_dis_ncci_table[i] = (byte) ncci;
6932
6933                /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
6934                if (!plci->channels
6935                    && (plci->B1_resource == 16)
6936                    && (plci->State <= CONNECTED))
6937                {
6938                        len = 9;
6939                        i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
6940                        PUT_WORD(&plci->ncpi_buffer[1], i);
6941                        PUT_WORD(&plci->ncpi_buffer[3], 0);
6942                        i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
6943                        PUT_WORD(&plci->ncpi_buffer[5], i);
6944                        PUT_WORD(&plci->ncpi_buffer[7], 0);
6945                        plci->ncpi_buffer[len] = 0;
6946                        plci->ncpi_buffer[0] = len;
6947                        if (plci->B3_prot == 4)
6948                                sendf(plci->appl, _CONNECT_B3_I, Id, 0, "s", "");
6949                        else
6950                        {
6951
6952                                if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6953                                    & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6954                                {
6955                                        plci->ncpi_buffer[++len] = 0;
6956                                        plci->ncpi_buffer[++len] = 0;
6957                                        plci->ncpi_buffer[++len] = 0;
6958                                        plci->ncpi_buffer[0] = len;
6959                                }
6960
6961                                sendf(plci->appl, _CONNECT_B3_I, Id, 0, "S", plci->ncpi_buffer);
6962                        }
6963                        sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
6964                        plci->ncpi_state = 0;
6965                        sig_req(plci, HANGUP, 0);
6966                        send_req(plci);
6967                        plci->State = OUTG_DIS_PENDING;
6968                        /* disc here */
6969                }
6970                else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6971                         && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6972                         && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
6973                {
6974                        if (ncci_state == IDLE)
6975                        {
6976                                if (plci->channels)
6977                                        plci->channels--;
6978                                if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
6979                                        if (plci->State == SUSPENDING) {
6980                                                sendf(plci->appl,
6981                                                      _FACILITY_I,
6982                                                      Id & 0xffffL,
6983                                                      0,
6984                                                      "ws", (word)3, "\x03\x04\x00\x00");
6985                                                sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
6986                                        }
6987                                        plci_remove(plci);
6988                                        plci->State = IDLE;
6989                                }
6990                        }
6991                }
6992                else if (plci->channels)
6993                {
6994                        sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
6995                        plci->ncpi_state = 0;
6996                        if ((ncci_state == OUTG_REJ_PENDING)
6997                            && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
6998                        {
6999                                sig_req(plci, HANGUP, 0);
7000                                send_req(plci);
7001                                plci->State = OUTG_DIS_PENDING;
7002                        }
7003                }
7004                break;
7005        case N_RESET:
7006                a->ncci_state[ncci] = INC_RES_PENDING;
7007                sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7008                break;
7009        case N_RESET_ACK:
7010                a->ncci_state[ncci] = CONNECTED;
7011                sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7012                break;
7013
7014        case N_UDATA:
7015                if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7016                {
7017                        plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7018                        plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7019                        plci->NL.R = plci->RData;
7020                        plci->NL.RNum = 1;
7021                        return;
7022                }
7023        case N_BDATA:
7024        case N_DATA:
7025                if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7026                    || (a->ncci_state[ncci] == IDLE)
7027                    || (a->ncci_state[ncci] == INC_DIS_PENDING))
7028                {
7029                        plci->NL.RNR = 2;
7030                        break;
7031                }
7032                if ((a->ncci_state[ncci] != CONNECTED)
7033                    && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7034                    && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7035                {
7036                        dbug(1, dprintf("flow control"));
7037                        plci->NL.RNR = 1; /* flow control  */
7038                        channel_x_off(plci, ch, 0);
7039                        break;
7040                }
7041
7042                NCCIcode = ncci | (((word)a->Id) << 8);
7043
7044                /* count all buffers within the Application pool    */
7045                /* belonging to the same NCCI. If this is below the */
7046                /* number of buffers available per NCCI we accept   */
7047                /* this packet, otherwise we reject it              */
7048                count = 0;
7049                Num = 0xffff;
7050                for (i = 0; i < APPLptr->MaxBuffer; i++) {
7051                        if (NCCIcode == APPLptr->DataNCCI[i]) count++;
7052                        if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
7053                }
7054
7055                if (count >= APPLptr->MaxNCCIData || Num == 0xffff)
7056                {
7057                        dbug(3, dprintf("Flow-Control"));
7058                        plci->NL.RNR = 1;
7059                        if (++(APPLptr->NCCIDataFlowCtrlTimer) >=
7060                            (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7061                        {
7062                                plci->NL.RNR = 2;
7063                                dbug(3, dprintf("DiscardData"));
7064                        } else {
7065                                channel_x_off(plci, ch, 0);
7066                        }
7067                        break;
7068                }
7069                else
7070                {
7071                        APPLptr->NCCIDataFlowCtrlTimer = 0;
7072                }
7073
7074                plci->RData[0].P = ReceiveBufferGet(APPLptr, Num);
7075                if (!plci->RData[0].P) {
7076                        plci->NL.RNR = 1;
7077                        channel_x_off(plci, ch, 0);
7078                        break;
7079                }
7080
7081                APPLptr->DataNCCI[Num] = NCCIcode;
7082                APPLptr->DataFlags[Num] = (plci->Id << 8) | (plci->NL.Ind >> 4);
7083                dbug(3, dprintf("Buffer(%d), Max = %d", Num, APPLptr->MaxBuffer));
7084
7085                plci->RNum = Num;
7086                plci->RFlags = plci->NL.Ind >> 4;
7087                plci->RData[0].PLength = APPLptr->MaxDataLength;
7088                plci->NL.R = plci->RData;
7089                if ((plci->NL.RLength != 0)
7090                    && ((plci->B2_prot == B2_V120_ASYNC)
7091                        || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7092                        || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7093                {
7094                        plci->RData[1].P = plci->RData[0].P;
7095                        plci->RData[1].PLength = plci->RData[0].PLength;
7096                        plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7097                        if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7098                                plci->RData[0].PLength = 1;
7099                        else
7100                                plci->RData[0].PLength = 2;
7101                        if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7102                                plci->RFlags |= 0x0010;
7103                        if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7104                                plci->RFlags |= 0x8000;
7105                        plci->NL.RNum = 2;
7106                }
7107                else
7108                {
7109                        if ((plci->NL.Ind & 0x0f) == N_UDATA)
7110                                plci->RFlags |= 0x0010;
7111
7112                        else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7113                                plci->RFlags |= 0x0001;
7114
7115                        plci->NL.RNum = 1;
7116                }
7117                break;
7118        case N_DATA_ACK:
7119                data_ack(plci, ch);
7120                break;
7121        default:
7122                plci->NL.RNR = 2;
7123                break;
7124        }
7125}
7126
7127/*------------------------------------------------------------------*/
7128/* find a free PLCI */
7129/*------------------------------------------------------------------*/
7130
7131static word get_plci(DIVA_CAPI_ADAPTER *a)
7132{
7133        word i, j;
7134        PLCI *plci;
7135
7136        for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
7137        if (i == a->max_plci) {
7138                dbug(1, dprintf("get_plci: out of PLCIs"));
7139                return 0;
7140        }
7141        plci = &a->plci[i];
7142        plci->Id = (byte)(i + 1);
7143
7144        plci->Sig.Id = 0;
7145        plci->NL.Id = 0;
7146        plci->sig_req = 0;
7147        plci->nl_req = 0;
7148
7149        plci->appl = NULL;
7150        plci->relatedPTYPLCI = NULL;
7151        plci->State = IDLE;
7152        plci->SuppState = IDLE;
7153        plci->channels = 0;
7154        plci->tel = 0;
7155        plci->B1_resource = 0;
7156        plci->B2_prot = 0;
7157        plci->B3_prot = 0;
7158
7159        plci->command = 0;
7160        plci->m_command = 0;
7161        init_internal_command_queue(plci);
7162        plci->number = 0;
7163        plci->req_in_start = 0;
7164        plci->req_in = 0;
7165        plci->req_out = 0;
7166        plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7167        plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7168        plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7169
7170        plci->data_sent = false;
7171        plci->send_disc = 0;
7172        plci->sig_global_req = 0;
7173        plci->sig_remove_id = 0;
7174        plci->nl_global_req = 0;
7175        plci->nl_remove_id = 0;
7176        plci->adv_nl = 0;
7177        plci->manufacturer = false;
7178        plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7179        plci->spoofed_msg = 0;
7180        plci->ptyState = 0;
7181        plci->cr_enquiry = false;
7182        plci->hangup_flow_ctrl_timer = 0;
7183
7184        plci->ncci_ring_list = 0;
7185        for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
7186        bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
7187        bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
7188        plci->fax_connect_info_length = 0;
7189        plci->nsf_control_bits = 0;
7190        plci->ncpi_state = 0x00;
7191        plci->ncpi_buffer[0] = 0;
7192
7193        plci->requested_options_conn = 0;
7194        plci->requested_options = 0;
7195        plci->notifiedcall = 0;
7196        plci->vswitchstate = 0;
7197        plci->vsprot = 0;
7198        plci->vsprotdialect = 0;
7199        init_b1_config(plci);
7200        dbug(1, dprintf("get_plci(%x)", plci->Id));
7201        return i + 1;
7202}
7203
7204/*------------------------------------------------------------------*/
7205/* put a parameter in the parameter buffer                          */
7206/*------------------------------------------------------------------*/
7207
7208static void add_p(PLCI *plci, byte code, byte *p)
7209{
7210        word p_length;
7211
7212        p_length = 0;
7213        if (p) p_length = p[0];
7214        add_ie(plci, code, p, p_length);
7215}
7216
7217/*------------------------------------------------------------------*/
7218/* put a structure in the parameter buffer                          */
7219/*------------------------------------------------------------------*/
7220static void add_s(PLCI *plci, byte code, API_PARSE *p)
7221{
7222        if (p) add_ie(plci, code, p->info, (word)p->length);
7223}
7224
7225/*------------------------------------------------------------------*/
7226/* put multiple structures in the parameter buffer                  */
7227/*------------------------------------------------------------------*/
7228static void add_ss(PLCI *plci, byte code, API_PARSE *p)
7229{
7230        byte i;
7231
7232        if (p) {
7233                dbug(1, dprintf("add_ss(%x,len=%d)", code, p->length));
7234                for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7235                        dbug(1, dprintf("add_ss_ie(%x,len=%d)", p->info[i - 1], p->info[i]));
7236                        add_ie(plci, p->info[i - 1], (byte *)&(p->info[i]), (word)p->info[i]);
7237                }
7238        }
7239}
7240
7241/*------------------------------------------------------------------*/
7242/* return the channel number sent by the application in a esc_chi   */
7243/*------------------------------------------------------------------*/
7244static byte getChannel(API_PARSE *p)
7245{
7246        byte i;
7247
7248        if (p) {
7249                for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7250                        if (p->info[i] == 2) {
7251                                if (p->info[i - 1] == ESC && p->info[i + 1] == CHI) return (p->info[i + 2]);
7252                        }
7253                }
7254        }
7255        return 0;
7256}
7257
7258
7259/*------------------------------------------------------------------*/
7260/* put an information element in the parameter buffer               */
7261/*------------------------------------------------------------------*/
7262
7263static void add_ie(PLCI *plci, byte code, byte *p, word p_length)
7264{
7265        word i;
7266
7267        if (!(code & 0x80) && !p_length) return;
7268
7269        if (plci->req_in == plci->req_in_start) {
7270                plci->req_in += 2;
7271        }
7272        else {
7273                plci->req_in--;
7274        }
7275        plci->RBuffer[plci->req_in++] = code;
7276
7277        if (p) {
7278                plci->RBuffer[plci->req_in++] = (byte)p_length;
7279                for (i = 0; i < p_length; i++) plci->RBuffer[plci->req_in++] = p[1 + i];
7280        }
7281
7282        plci->RBuffer[plci->req_in++] = 0;
7283}
7284
7285/*------------------------------------------------------------------*/
7286/* put a unstructured data into the buffer                          */
7287/*------------------------------------------------------------------*/
7288
7289static void add_d(PLCI *plci, word length, byte *p)
7290{
7291        word i;
7292
7293        if (plci->req_in == plci->req_in_start) {
7294                plci->req_in += 2;
7295        }
7296        else {
7297                plci->req_in--;
7298        }
7299        for (i = 0; i < length; i++) plci->RBuffer[plci->req_in++] = p[i];
7300}
7301
7302/*------------------------------------------------------------------*/
7303/* put parameters from the Additional Info parameter in the         */
7304/* parameter buffer                                                 */
7305/*------------------------------------------------------------------*/
7306
7307static void add_ai(PLCI *plci, API_PARSE *ai)
7308{
7309        word i;
7310        API_PARSE ai_parms[5];
7311
7312        for (i = 0; i < 5; i++) ai_parms[i].length = 0;
7313
7314        if (!ai->length)
7315                return;
7316        if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7317                return;
7318
7319        add_s(plci, KEY, &ai_parms[1]);
7320        add_s(plci, UUI, &ai_parms[2]);
7321        add_ss(plci, FTY, &ai_parms[3]);
7322}
7323
7324/*------------------------------------------------------------------*/
7325/* put parameter for b1 protocol in the parameter buffer            */
7326/*------------------------------------------------------------------*/
7327
7328static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7329                   word b1_facilities)
7330{
7331        API_PARSE bp_parms[8];
7332        API_PARSE mdm_cfg[9];
7333        API_PARSE global_config[2];
7334        byte cai[256];
7335        byte resource[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7336        byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7337        word i;
7338
7339        API_PARSE mdm_cfg_v18[4];
7340        word j, n, w;
7341        dword d;
7342
7343
7344        for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7345        for (i = 0; i < 2; i++) global_config[i].length = 0;
7346
7347        dbug(1, dprintf("add_b1"));
7348        api_save_msg(bp, "s", &plci->B_protocol);
7349
7350        if (b_channel_info == 2) {
7351                plci->B1_resource = 0;
7352                adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7353                add_p(plci, CAI, "\x01\x00");
7354                dbug(1, dprintf("Cai=1,0 (no resource)"));
7355                return 0;
7356        }
7357
7358        if (plci->tel == CODEC_PERMANENT) return 0;
7359        else if (plci->tel == CODEC) {
7360                plci->B1_resource = 1;
7361                adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7362                add_p(plci, CAI, "\x01\x01");
7363                dbug(1, dprintf("Cai=1,1 (Codec)"));
7364                return 0;
7365        }
7366        else if (plci->tel == ADV_VOICE) {
7367                plci->B1_resource = add_b1_facilities(plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7368                adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7369                voice_cai[1] = plci->B1_resource;
7370                PUT_WORD(&voice_cai[5], plci->appl->MaxDataLength);
7371                add_p(plci, CAI, voice_cai);
7372                dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai[1]));
7373                return 0;
7374        }
7375        plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7376        if (plci->call_dir & CALL_DIR_OUT)
7377                plci->call_dir |= CALL_DIR_ORIGINATE;
7378        else if (plci->call_dir & CALL_DIR_IN)
7379                plci->call_dir |= CALL_DIR_ANSWER;
7380
7381        if (!bp->length) {
7382                plci->B1_resource = 0x5;
7383                adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7384                add_p(plci, CAI, "\x01\x05");
7385                return 0;
7386        }
7387
7388        dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7389        if (bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7390        if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7391        {
7392                bp_parms[6].length = 0;
7393                if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7394                {
7395                        dbug(1, dprintf("b-form.!"));
7396                        return _WRONG_MESSAGE_FORMAT;
7397                }
7398        }
7399        else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7400        {
7401                dbug(1, dprintf("b-form.!"));
7402                return _WRONG_MESSAGE_FORMAT;
7403        }
7404
7405        if (bp_parms[6].length)
7406        {
7407                if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7408                {
7409                        return _WRONG_MESSAGE_FORMAT;
7410                }
7411                switch (GET_WORD(global_config[0].info))
7412                {
7413                case 1:
7414                        plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7415                        break;
7416                case 2:
7417                        plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7418                        break;
7419                }
7420        }
7421        dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7422
7423
7424        if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7425            && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7426        {
7427                plci->B1_resource = add_b1_facilities(plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7428                adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7429                cai[1] = plci->B1_resource;
7430                cai[2] = 0;
7431                cai[3] = 0;
7432                cai[4] = 0;
7433                PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7434                for (i = 0; i < bp_parms[3].length; i++)
7435                        cai[7 + i] = bp_parms[3].info[1 + i];
7436                cai[0] = 6 + bp_parms[3].length;
7437                add_p(plci, CAI, cai);
7438                return 0;
7439        }
7440
7441
7442        if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7443            && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7444        {
7445                plci->B1_resource = add_b1_facilities(plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7446                adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7447                cai[1] = plci->B1_resource;
7448                cai[2] = 0;
7449                cai[3] = 0;
7450                cai[4] = 0;
7451                PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7452                cai[0] = 6;
7453                add_p(plci, CAI, cai);
7454                return 0;
7455        }
7456
7457
7458        if ((GET_WORD(bp_parms[0].info) >= 32)
7459            || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7460                && ((GET_WORD(bp_parms[0].info) != 3)
7461                    || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7462                    || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7463        {
7464                return _B1_NOT_SUPPORTED;
7465        }
7466        plci->B1_resource = add_b1_facilities(plci, resource[GET_WORD(bp_parms[0].info)],
7467                                              (word)(b1_facilities & ~B1_FACILITY_VOICE));
7468        adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7469        cai[0] = 6;
7470        cai[1] = plci->B1_resource;
7471        for (i = 2; i < sizeof(cai); i++) cai[i] = 0;
7472
7473        if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7474            || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7475            || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7476        { /* B1 - modem */
7477                for (i = 0; i < 7; i++) mdm_cfg[i].length = 0;
7478
7479                if (bp_parms[3].length)
7480                {
7481                        if (api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwww", mdm_cfg))
7482                        {
7483                                return (_WRONG_MESSAGE_FORMAT);
7484                        }
7485
7486                        cai[2] = 0; /* Bit rate for adaptation */
7487
7488                        dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7489
7490                        PUT_WORD(&cai[13], 0);                          /* Min Tx speed */
7491                        PUT_WORD(&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7492                        PUT_WORD(&cai[17], 0);                          /* Min Rx speed */
7493                        PUT_WORD(&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7494
7495                        cai[3] = 0; /* Async framing parameters */
7496                        switch (GET_WORD(mdm_cfg[2].info))
7497                        {       /* Parity     */
7498                        case 1: /* odd parity */
7499                                cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7500                                dbug(1, dprintf("MDM: odd parity"));
7501                                break;
7502
7503                        case 2: /* even parity */
7504                                cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7505                                dbug(1, dprintf("MDM: even parity"));
7506                                break;
7507
7508                        default:
7509                                dbug(1, dprintf("MDM: no parity"));
7510                                break;
7511                        }
7512
7513                        switch (GET_WORD(mdm_cfg[3].info))
7514                        {       /* stop bits   */
7515                        case 1: /* 2 stop bits */
7516                                cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7517                                dbug(1, dprintf("MDM: 2 stop bits"));
7518                                break;
7519
7520                        default:
7521                                dbug(1, dprintf("MDM: 1 stop bit"));
7522                                break;
7523                        }
7524
7525                        switch (GET_WORD(mdm_cfg[1].info))
7526                        {     /* char length */
7527                        case 5:
7528                                cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7529                                dbug(1, dprintf("MDM: 5 bits"));
7530                                break;
7531
7532                        case 6:
7533                                cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7534                                dbug(1, dprintf("MDM: 6 bits"));
7535                                break;
7536
7537                        case 7:
7538                                cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7539                                dbug(1, dprintf("MDM: 7 bits"));
7540                                break;
7541
7542                        default:
7543                                dbug(1, dprintf("MDM: 8 bits"));
7544                                break;
7545                        }
7546
7547                        cai[7] = 0; /* Line taking options */
7548                        cai[8] = 0; /* Modulation negotiation options */
7549                        cai[9] = 0; /* Modulation options */
7550
7551                        if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7552                        {
7553                                cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7554                                dbug(1, dprintf("MDM: Reverse direction"));
7555                        }
7556
7557                        if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7558                        {
7559                                cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7560                                dbug(1, dprintf("MDM: Disable retrain"));
7561                        }
7562
7563                        if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7564                        {
7565                                cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7566                                dbug(1, dprintf("MDM: Disable ring tone"));
7567                        }
7568
7569                        if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7570                        {
7571                                cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7572                                dbug(1, dprintf("MDM: 1800 guard tone"));
7573                        }
7574                        else if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_550)
7575                        {
7576                                cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7577                                dbug(1, dprintf("MDM: 550 guard tone"));
7578                        }
7579
7580                        if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7581                        {
7582                                cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7583                                dbug(1, dprintf("MDM: V100"));
7584                        }
7585                        else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7586                        {
7587                                cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7588                                dbug(1, dprintf("MDM: IN CLASS"));
7589                        }
7590                        else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7591                        {
7592                                cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7593                                dbug(1, dprintf("MDM: DISABLED"));
7594                        }
7595                        cai[0] = 20;
7596
7597                        if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7598                            && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7599                        {
7600                                plci->requested_options |= 1L << PRIVATE_V18;
7601                        }
7602                        if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7603                                plci->requested_options |= 1L << PRIVATE_VOWN;
7604
7605                        if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
7606                            & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7607                        {
7608                                if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwws", mdm_cfg))
7609                                {
7610                                        i = 27;
7611                                        if (mdm_cfg[6].length >= 4)
7612                                        {
7613                                                d = GET_DWORD(&mdm_cfg[6].info[1]);
7614                                                cai[7] |= (byte) d;          /* line taking options */
7615                                                cai[9] |= (byte)(d >> 8);    /* modulation options */
7616                                                cai[++i] = (byte)(d >> 16);  /* vown modulation options */
7617                                                cai[++i] = (byte)(d >> 24);
7618                                                if (mdm_cfg[6].length >= 8)
7619                                                {
7620                                                        d = GET_DWORD(&mdm_cfg[6].info[5]);
7621                                                        cai[10] |= (byte) d;        /* disabled modulations mask */
7622                                                        cai[11] |= (byte)(d >> 8);
7623                                                        if (mdm_cfg[6].length >= 12)
7624                                                        {
7625                                                                d = GET_DWORD(&mdm_cfg[6].info[9]);
7626                                                                cai[12] = (byte) d;          /* enabled modulations mask */
7627                                                                cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */
7628                                                                cai[++i] = (byte)(d >> 16);
7629                                                                cai[++i] = (byte)(d >> 24);
7630                                                                cai[++i] = 0;
7631                                                                if (mdm_cfg[6].length >= 14)
7632                                                                {
7633                                                                        w = GET_WORD(&mdm_cfg[6].info[13]);
7634                                                                        if (w != 0)
7635                                                                                PUT_WORD(&cai[13], w);  /* min tx speed */
7636                                                                        if (mdm_cfg[6].length >= 16)
7637                                                                        {
7638                                                                                w = GET_WORD(&mdm_cfg[6].info[15]);
7639                                                                                if (w != 0)
7640                                                                                        PUT_WORD(&cai[15], w);  /* max tx speed */
7641                                                                                if (mdm_cfg[6].length >= 18)
7642                                                                                {
7643                                                                                        w = GET_WORD(&mdm_cfg[6].info[17]);
7644                                                                                        if (w != 0)
7645                                                                                                PUT_WORD(&cai[17], w);  /* min rx speed */
7646                                                                                        if (mdm_cfg[6].length >= 20)
7647                                                                                        {
7648                                                                                                w = GET_WORD(&mdm_cfg[6].info[19]);
7649                                                                                                if (w != 0)
7650                                                                                                        PUT_WORD(&cai[19], w);  /* max rx speed */
7651                                                                                                if (mdm_cfg[6].length >= 22)
7652                                                                                                {
7653                                                                                                        w = GET_WORD(&mdm_cfg[6].info[21]);
7654                                                                                                        cai[23] = (byte)(-((short) w));  /* transmit level */
7655                                                                                                        if (mdm_cfg[6].length >= 24)
7656                                                                                                        {
7657                                                                                                                w = GET_WORD(&mdm_cfg[6].info[23]);
7658                                                                                                                cai[22] |= (byte) w;        /* info options mask */
7659                                                                                                                cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */
7660                                                                                                        }
7661                                                                                                }
7662                                                                                        }
7663                                                                                }
7664                                                                        }
7665                                                                }
7666                                                        }
7667                                                }
7668                                        }
7669                                        cai[27] = i - 27;
7670                                        i++;
7671                                        if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwwss", mdm_cfg))
7672                                        {
7673                                                if (!api_parse(&mdm_cfg[7].info[1], (word)mdm_cfg[7].length, "sss", mdm_cfg_v18))
7674                                                {
7675                                                        for (n = 0; n < 3; n++)
7676                                                        {
7677                                                                cai[i] = (byte)(mdm_cfg_v18[n].length);
7678                                                                for (j = 1; j < ((word)(cai[i] + 1)); j++)
7679                                                                        cai[i + j] = mdm_cfg_v18[n].info[j];
7680                                                                i += cai[i] + 1;
7681                                                        }
7682                                                }
7683                                        }
7684                                        cai[0] = (byte)(i - 1);
7685                                }
7686                        }
7687
7688                }
7689        }
7690        if (GET_WORD(bp_parms[0].info) == 2 ||                         /* V.110 async */
7691            GET_WORD(bp_parms[0].info) == 3)                           /* V.110 sync */
7692        {
7693                if (bp_parms[3].length) {
7694                        dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms[3].info[1])));
7695                        switch (GET_WORD(&bp_parms[3].info[1])) {                 /* Rate */
7696                        case 0:
7697                        case 56000:
7698                                if (GET_WORD(bp_parms[0].info) == 3) {                  /* V.110 sync 56k */
7699                                        dbug(1, dprintf("56k sync HSCX"));
7700                                        cai[1] = 8;
7701                                        cai[2] = 0;
7702                                        cai[3] = 0;
7703                                }
7704                                else if (GET_WORD(bp_parms[0].info) == 2) {
7705                                        dbug(1, dprintf("56k async DSP"));
7706                                        cai[2] = 9;
7707                                }
7708                                break;
7709                        case 50:     cai[2] = 1;  break;
7710                        case 75:     cai[2] = 1;  break;
7711                        case 110:    cai[2] = 1;  break;
7712                        case 150:    cai[2] = 1;  break;
7713                        case 200:    cai[2] = 1;  break;
7714                        case 300:    cai[2] = 1;  break;
7715                        case 600:    cai[2] = 1;  break;
7716                        case 1200:   cai[2] = 2;  break;
7717                        case 2400:   cai[2] = 3;  break;
7718                        case 4800:   cai[2] = 4;  break;
7719                        case 7200:   cai[2] = 10; break;
7720                        case 9600:   cai[2] = 5;  break;
7721                        case 12000:  cai[2] = 13; break;
7722                        case 24000:  cai[2] = 0;  break;
7723                        case 14400:  cai[2] = 11; break;
7724                        case 19200:  cai[2] = 6;  break;
7725                        case 28800:  cai[2] = 12; break;
7726                        case 38400:  cai[2] = 7;  break;
7727                        case 48000:  cai[2] = 8;  break;
7728                        case 76:     cai[2] = 15; break;  /* 75/1200     */
7729                        case 1201:   cai[2] = 14; break;  /* 1200/75     */
7730                        case 56001:  cai[2] = 9;  break;  /* V.110 56000 */
7731
7732                        default:
7733                                return _B1_PARM_NOT_SUPPORTED;
7734                        }
7735                        cai[3] = 0;
7736                        if (cai[1] == 13)                                        /* v.110 async */
7737                        {
7738                                if (bp_parms[3].length >= 8)
7739                                {
7740                                        switch (GET_WORD(&bp_parms[3].info[3]))
7741                                        {       /* char length */
7742                                        case 5:
7743                                                cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7744                                                break;
7745                                        case 6:
7746                                                cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7747                                                break;
7748                                        case 7:
7749                                                cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7750                                                break;
7751                                        }
7752                                        switch (GET_WORD(&bp_parms[3].info[5]))
7753                                        {       /* Parity     */
7754                                        case 1: /* odd parity */
7755                                                cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7756                                                break;
7757                                        case 2: /* even parity */
7758                                                cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7759                                                break;
7760                                        }
7761                                        switch (GET_WORD(&bp_parms[3].info[7]))
7762                                        {       /* stop bits   */
7763                                        case 1: /* 2 stop bits */
7764                                                cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7765                                                break;
7766                                        }
7767                                }
7768                        }
7769                }
7770                else if (cai[1] == 8 || GET_WORD(bp_parms[0].info) == 3) {
7771                        dbug(1, dprintf("V.110 default 56k sync"));
7772                        cai[1] = 8;
7773                        cai[2] = 0;
7774                        cai[3] = 0;
7775                }
7776                else {
7777                        dbug(1, dprintf("V.110 default 9600 async"));
7778                        cai[2] = 5;
7779                }
7780        }
7781        PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7782        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]));
7783/* HexDump ("CAI", sizeof(cai), &cai[0]); */
7784
7785        add_p(plci, CAI, cai);
7786        return 0;
7787}
7788
7789/*------------------------------------------------------------------*/
7790/* put parameter for b2 and B3  protocol in the parameter buffer    */
7791/*------------------------------------------------------------------*/
7792
7793static word add_b23(PLCI *plci, API_PARSE *bp)
7794{
7795        word i, fax_control_bits;
7796        byte pos, len;
7797        byte SAPI = 0x40;  /* default SAPI 16 for x.31 */
7798        API_PARSE bp_parms[8];
7799        API_PARSE *b1_config;
7800        API_PARSE *b2_config;
7801        API_PARSE b2_config_parms[8];
7802        API_PARSE *b3_config;
7803        API_PARSE b3_config_parms[6];
7804        API_PARSE global_config[2];
7805
7806        static byte llc[3] = {2,0,0};
7807        static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7808        static byte nlc[256];
7809        static byte lli[12] = {1,1};
7810
7811        const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7812        const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7813
7814        const byte llc3[] = {4,3,2,2,6,6,0};
7815        const byte header[] = {0,2,3,3,0,0,0};
7816
7817        for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7818        for (i = 0; i < 6; i++) b2_config_parms[i].length = 0;
7819        for (i = 0; i < 5; i++) b3_config_parms[i].length = 0;
7820
7821        lli[0] = 1;
7822        lli[1] = 1;
7823        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7824                lli[1] |= 2;
7825        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7826                lli[1] |= 4;
7827
7828        if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7829                lli[1] |= 0x10;
7830                if (plci->rx_dma_descriptor <= 0) {
7831                        plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
7832                        if (plci->rx_dma_descriptor >= 0)
7833                                plci->rx_dma_descriptor++;
7834                }
7835                if (plci->rx_dma_descriptor > 0) {
7836                        lli[0] = 6;
7837                        lli[1] |= 0x40;
7838                        lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7839                        lli[3] = (byte)plci->rx_dma_magic;
7840                        lli[4] = (byte)(plci->rx_dma_magic >>  8);
7841                        lli[5] = (byte)(plci->rx_dma_magic >> 16);
7842                        lli[6] = (byte)(plci->rx_dma_magic >> 24);
7843                }
7844        }
7845
7846        if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7847                lli[1] |= 0x20;
7848        }
7849
7850        dbug(1, dprintf("add_b23"));
7851        api_save_msg(bp, "s", &plci->B_protocol);
7852
7853        if (!bp->length && plci->tel)
7854        {
7855                plci->adv_nl = true;
7856                dbug(1, dprintf("Default adv.Nl"));
7857                add_p(plci, LLI, lli);
7858                plci->B2_prot = 1 /*XPARENT*/;
7859                plci->B3_prot = 0 /*XPARENT*/;
7860                llc[1] = 2;
7861                llc[2] = 4;
7862                add_p(plci, LLC, llc);
7863                dlc[0] = 2;
7864                PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7865                add_p(plci, DLC, dlc);
7866                return 0;
7867        }
7868
7869        if (!bp->length) /*default*/
7870        {
7871                dbug(1, dprintf("ret default"));
7872                add_p(plci, LLI, lli);
7873                plci->B2_prot = 0 /*X.75   */;
7874                plci->B3_prot = 0 /*XPARENT*/;
7875                llc[1] = 1;
7876                llc[2] = 4;
7877                add_p(plci, LLC, llc);
7878                dlc[0] = 2;
7879                PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7880                add_p(plci, DLC, dlc);
7881                return 0;
7882        }
7883        dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7884        if ((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT;
7885
7886        if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7887        {
7888                bp_parms[6].length = 0;
7889                if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7890                {
7891                        dbug(1, dprintf("b-form.!"));
7892                        return _WRONG_MESSAGE_FORMAT;
7893                }
7894        }
7895        else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7896        {
7897                dbug(1, dprintf("b-form.!"));
7898                return _WRONG_MESSAGE_FORMAT;
7899        }
7900
7901        if (plci->tel == ADV_VOICE) /* transparent B on advanced voice */
7902        {
7903                if (GET_WORD(bp_parms[1].info) != 1
7904                    || GET_WORD(bp_parms[2].info) != 0) return _B2_NOT_SUPPORTED;
7905                plci->adv_nl = true;
7906        }
7907        else if (plci->tel) return _B2_NOT_SUPPORTED;
7908
7909
7910        if ((GET_WORD(bp_parms[1].info) == B2_RTP)
7911            && (GET_WORD(bp_parms[2].info) == B3_RTP)
7912            && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7913        {
7914                add_p(plci, LLI, lli);
7915                plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
7916                plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
7917                llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
7918                llc[2] = 4;
7919                add_p(plci, LLC, llc);
7920                dlc[0] = 2;
7921                PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7922                dlc[3] = 3; /* Addr A */
7923                dlc[4] = 1; /* Addr B */
7924                dlc[5] = 7; /* modulo mode */
7925                dlc[6] = 7; /* window size */
7926                dlc[7] = 0; /* XID len Lo  */
7927                dlc[8] = 0; /* XID len Hi  */
7928                for (i = 0; i < bp_parms[4].length; i++)
7929                        dlc[9 + i] = bp_parms[4].info[1 + i];
7930                dlc[0] = (byte)(8 + bp_parms[4].length);
7931                add_p(plci, DLC, dlc);
7932                for (i = 0; i < bp_parms[5].length; i++)
7933                        nlc[1 + i] = bp_parms[5].info[1 + i];
7934                nlc[0] = (byte)(bp_parms[5].length);
7935                add_p(plci, NLC, nlc);
7936                return 0;
7937        }
7938
7939
7940
7941        if ((GET_WORD(bp_parms[1].info) >= 32)
7942            || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
7943                && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
7944                    || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
7945
7946        {
7947                return _B2_NOT_SUPPORTED;
7948        }
7949        if ((GET_WORD(bp_parms[2].info) >= 32)
7950            || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
7951        {
7952                return _B3_NOT_SUPPORTED;
7953        }
7954        if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
7955            && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7956                || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7957                || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
7958        {
7959                return (add_modem_b23(plci, bp_parms));
7960        }
7961
7962        add_p(plci, LLI, lli);
7963
7964        plci->B2_prot = (byte)GET_WORD(bp_parms[1].info);
7965        plci->B3_prot = (byte)GET_WORD(bp_parms[2].info);
7966        if (plci->B2_prot == 12) SAPI = 0; /* default SAPI D-channel */
7967
7968        if (bp_parms[6].length)
7969        {
7970                if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7971                {
7972                        return _WRONG_MESSAGE_FORMAT;
7973                }
7974                switch (GET_WORD(global_config[0].info))
7975                {
7976                case 1:
7977                        plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7978                        break;
7979                case 2:
7980                        plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7981                        break;
7982                }
7983        }
7984        dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7985
7986
7987        if (plci->B2_prot == B2_PIAFS)
7988                llc[1] = PIAFS_CRC;
7989        else
7990/* IMPLEMENT_PIAFS */
7991        {
7992                llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
7993                        llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
7994        }
7995        llc[2] = llc3[GET_WORD(bp_parms[2].info)];
7996
7997        add_p(plci, LLC, llc);
7998
7999        dlc[0] = 2;
8000        PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8001                 header[GET_WORD(bp_parms[2].info)]);
8002
8003        b1_config = &bp_parms[3];
8004        nlc[0] = 0;
8005        if (plci->B3_prot == 4
8006            || plci->B3_prot == 5)
8007        {
8008                for (i = 0; i < sizeof(T30_INFO); i++) nlc[i] = 0;
8009                nlc[0] = sizeof(T30_INFO);
8010                if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8011                        ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8012                ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8013                if (b1_config->length >= 2)
8014                {
8015                        ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1]) / 2400);
8016                }
8017        }
8018        b2_config = &bp_parms[4];
8019
8020
8021        if (llc[1] == PIAFS_CRC)
8022        {
8023                if (plci->B3_prot != B3_TRANSPARENT)
8024                {
8025                        return _B_STACK_NOT_SUPPORTED;
8026                }
8027                if (b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8028                        return _WRONG_MESSAGE_FORMAT;
8029                }
8030                PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8031                dlc[3] = 0; /* Addr A */
8032                dlc[4] = 0; /* Addr B */
8033                dlc[5] = 0; /* modulo mode */
8034                dlc[6] = 0; /* window size */
8035                if (b2_config->length >= 7) {
8036                        dlc[7] = 7;
8037                        dlc[8] = 0;
8038                        dlc[9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8039                        dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8040                        dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8041                        dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8042                        dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8043                        dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8044                        dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8045                        dlc[0] = 15;
8046                        if (b2_config->length >= 8) { /* PIAFS control abilities */
8047                                dlc[7] = 10;
8048                                dlc[16] = 2; /* Length of PIAFS extension */
8049                                dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8050                                dlc[18] = b2_config_parms[4].info[0]; /* value */
8051                                dlc[0] = 18;
8052                        }
8053                }
8054                else /* default values, 64K, variable, no compression */
8055                {
8056                        dlc[7] = 7;
8057                        dlc[8] = 0;
8058                        dlc[9] = 0x03; /* PIAFS protocol Speed configuration */
8059                        dlc[10] = 0x03; /* V.42bis P0 */
8060                        dlc[11] = 0;    /* V.42bis P0 */
8061                        dlc[12] = 0;    /* V.42bis P1 */
8062                        dlc[13] = 0;    /* V.42bis P1 */
8063                        dlc[14] = 0;    /* V.42bis P2 */
8064                        dlc[15] = 0;    /* V.42bis P2 */
8065                        dlc[0] = 15;
8066                }
8067                add_p(plci, DLC, dlc);
8068        }
8069        else
8070
8071                if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8072                {
8073                        if (plci->B3_prot != B3_TRANSPARENT)
8074                                return _B_STACK_NOT_SUPPORTED;
8075
8076                        dlc[0] = 6;
8077                        PUT_WORD(&dlc[1], GET_WORD(&dlc[1]) + 2);
8078                        dlc[3] = 0x08;
8079                        dlc[4] = 0x01;
8080                        dlc[5] = 127;
8081                        dlc[6] = 7;
8082                        if (b2_config->length != 0)
8083                        {
8084                                if ((llc[1] == V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8085                                        return _WRONG_MESSAGE_FORMAT;
8086                                }
8087                                dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8088                                dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8089                                if (b2_config->info[3] != 128)
8090                                {
8091                                        dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8092                                        return _B2_PARM_NOT_SUPPORTED;
8093                                }
8094                                dlc[5] = (byte)(b2_config->info[3] - 1);
8095                                dlc[6] = b2_config->info[4];
8096                                if (llc[1] == V120_V42BIS) {
8097                                        if (b2_config->length >= 10) {
8098                                                dlc[7] = 6;
8099                                                dlc[8] = 0;
8100                                                dlc[9] = b2_config_parms[4].info[0];
8101                                                dlc[10] = b2_config_parms[4].info[1];
8102                                                dlc[11] = b2_config_parms[5].info[0];
8103                                                dlc[12] = b2_config_parms[5].info[1];
8104                                                dlc[13] = b2_config_parms[6].info[0];
8105                                                dlc[14] = b2_config_parms[6].info[1];
8106                                                dlc[0] = 14;
8107                                                dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8108                                                dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8109                                                dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8110                                        }
8111                                        else {
8112                                                dlc[6] = 14;
8113                                        }
8114                                }
8115                        }
8116                }
8117                else
8118                {
8119                        if (b2_config->length)
8120                        {
8121                                dbug(1, dprintf("B2-Config"));
8122                                if (llc[1] == X75_V42BIS) {
8123                                        if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8124                                        {
8125                                                return _WRONG_MESSAGE_FORMAT;
8126                                        }
8127                                }
8128                                else {
8129                                        if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8130                                        {
8131                                                return _WRONG_MESSAGE_FORMAT;
8132                                        }
8133                                }
8134                                /* if B2 Protocol is LAPD, b2_config structure is different */
8135                                if (llc[1] == 6)
8136                                {
8137                                        dlc[0] = 4;
8138                                        if (b2_config->length >= 1) dlc[2] = b2_config->info[1];      /* TEI */
8139                                        else dlc[2] = 0x01;
8140                                        if ((b2_config->length >= 2) && (plci->B2_prot == 12))
8141                                        {
8142                                                SAPI = b2_config->info[2];    /* SAPI */
8143                                        }
8144                                        dlc[1] = SAPI;
8145                                        if ((b2_config->length >= 3) && (b2_config->info[3] == 128))
8146                                        {
8147                                                dlc[3] = 127;      /* Mode */
8148                                        }
8149                                        else
8150                                        {
8151                                                dlc[3] = 7;        /* Mode */
8152                                        }
8153
8154                                        if (b2_config->length >= 4) dlc[4] = b2_config->info[4];      /* Window */
8155                                        else dlc[4] = 1;
8156                                        dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8157                                        if (b2_config->length > 5) return _B2_PARM_NOT_SUPPORTED;
8158                                }
8159                                else
8160                                {
8161                                        dlc[0] = (byte)(b2_config_parms[4].length + 6);
8162                                        dlc[3] = b2_config->info[1];
8163                                        dlc[4] = b2_config->info[2];
8164                                        if (b2_config->info[3] != 8 && b2_config->info[3] != 128) {
8165                                                dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8166                                                return _B2_PARM_NOT_SUPPORTED;
8167                                        }
8168
8169                                        dlc[5] = (byte)(b2_config->info[3] - 1);
8170                                        dlc[6] = b2_config->info[4];
8171                                        if (dlc[6] > dlc[5]) {
8172                                                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]));
8173                                                return _B2_PARM_NOT_SUPPORTED;
8174                                        }
8175
8176                                        if (llc[1] == X75_V42BIS) {
8177                                                if (b2_config->length >= 10) {
8178                                                        dlc[7] = 6;
8179                                                        dlc[8] = 0;
8180                                                        dlc[9] = b2_config_parms[4].info[0];
8181                                                        dlc[10] = b2_config_parms[4].info[1];
8182                                                        dlc[11] = b2_config_parms[5].info[0];
8183                                                        dlc[12] = b2_config_parms[5].info[1];
8184                                                        dlc[13] = b2_config_parms[6].info[0];
8185                                                        dlc[14] = b2_config_parms[6].info[1];
8186                                                        dlc[0] = 14;
8187                                                        dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8188                                                        dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8189                                                        dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8190                                                }
8191                                                else {
8192                                                        dlc[6] = 14;
8193                                                }
8194
8195                                        }
8196                                        else {
8197                                                PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8198                                                for (i = 0; i < b2_config_parms[4].length; i++)
8199                                                        dlc[11 + i] = b2_config_parms[4].info[1 + i];
8200                                        }
8201                                }
8202                        }
8203                }
8204        add_p(plci, DLC, dlc);
8205
8206        b3_config = &bp_parms[5];
8207        if (b3_config->length)
8208        {
8209                if (plci->B3_prot == 4
8210                    || plci->B3_prot == 5)
8211                {
8212                        if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8213                        {
8214                                return _WRONG_MESSAGE_FORMAT;
8215                        }
8216                        i = GET_WORD((byte *)(b3_config_parms[0].info));
8217                        ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8218                                                                    ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8219                        ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8220                        fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8221                        if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8222                                fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8223                        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8224                        {
8225
8226                                if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8227                                    & (1L << PRIVATE_FAX_PAPER_FORMATS))
8228                                {
8229                                        ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8230                                                T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8231                                                T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8232                                }
8233
8234                                ((T30_INFO *)&nlc[1])->recording_properties =
8235                                        T30_RECORDING_WIDTH_ISO_A3 |
8236                                        (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8237                                        (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8238                        }
8239                        if (plci->B3_prot == 5)
8240                        {
8241                                if (i & 0x0002) /* Accept incoming fax-polling requests */
8242                                        fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8243                                if (i & 0x2000) /* Do not use MR compression */
8244                                        fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8245                                if (i & 0x4000) /* Do not use MMR compression */
8246                                        fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8247                                if (i & 0x8000) /* Do not use ECM */
8248                                        fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8249                                if (plci->fax_connect_info_length != 0)
8250                                {
8251                                        ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8252                                        ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8253                                        ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8254                                        fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8255                                                (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8256                                }
8257                        }
8258                        /* copy station id to NLC */
8259                        for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
8260                        {
8261                                if (i < b3_config_parms[2].length)
8262                                {
8263                                        ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1 + i];
8264                                }
8265                                else
8266                                {
8267                                        ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8268                                }
8269                        }
8270                        ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8271                        /* copy head line to NLC */
8272                        if (b3_config_parms[3].length)
8273                        {
8274
8275                                pos = (byte)(fax_head_line_time(&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8276                                if (pos != 0)
8277                                {
8278                                        if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8279                                                pos = 0;
8280                                        else
8281                                        {
8282                                                nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8283                                                nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8284                                                len = (byte)b3_config_parms[2].length;
8285                                                if (len > 20)
8286                                                        len = 20;
8287                                                if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8288                                                {
8289                                                        for (i = 0; i < len; i++)
8290                                                                nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1 + i];
8291                                                        nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8292                                                        nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8293                                                }
8294                                        }
8295                                }
8296
8297                                len = (byte)b3_config_parms[3].length;
8298                                if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8299                                        len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8300                                ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8301                                nlc[0] += (byte)(pos + len);
8302                                for (i = 0; i < len; i++)
8303                                        nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] =  ((byte *)b3_config_parms[3].info)[1 + i];
8304                        } else
8305                                ((T30_INFO *)&nlc[1])->head_line_len = 0;
8306
8307                        plci->nsf_control_bits = 0;
8308                        if (plci->B3_prot == 5)
8309                        {
8310                                if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8311                                    && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8312                                {
8313                                        plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8314                                }
8315                                if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8316                                    && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8317                                {
8318                                        plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8319                                }
8320                                if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8321                                    & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8322                                {
8323                                        if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8324                                            & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8325                                        {
8326                                                fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8327                                                if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8328                                                        fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8329                                        }
8330                                        len = nlc[0];
8331                                        pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8332                                        if (pos < plci->fax_connect_info_length)
8333                                        {
8334                                                for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8335                                                        nlc[++len] = plci->fax_connect_info_buffer[pos++];
8336                                        }
8337                                        else
8338                                                nlc[++len] = 0;
8339                                        if (pos < plci->fax_connect_info_length)
8340                                        {
8341                                                for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8342                                                        nlc[++len] = plci->fax_connect_info_buffer[pos++];
8343                                        }
8344                                        else
8345                                                nlc[++len] = 0;
8346                                        if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8347                                            & (1L << PRIVATE_FAX_NONSTANDARD))
8348                                        {
8349                                                if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8350                                                {
8351                                                        if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos + 1] >= 2))
8352                                                                plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos + 2]);
8353                                                        for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8354                                                                nlc[++len] = plci->fax_connect_info_buffer[pos++];
8355                                                }
8356                                                else
8357                                                {
8358                                                        if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8359                                                        {
8360                                                                dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8361                                                                nlc[++len] = 0;
8362                                                        }
8363                                                        else
8364                                                        {
8365                                                                if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8366                                                                        plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8367                                                                nlc[++len] = (byte)(b3_config_parms[4].length);
8368                                                                for (i = 0; i < b3_config_parms[4].length; i++)
8369                                                                        nlc[++len] = b3_config_parms[4].info[1 + i];
8370                                                        }
8371                                                }
8372                                        }
8373                                        nlc[0] = len;
8374                                        if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8375                                            && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8376                                        {
8377                                                ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8378                                        }
8379                                }
8380                        }
8381
8382                        PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8383                        len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8384                        for (i = 0; i < len; i++)
8385                                plci->fax_connect_info_buffer[i] = nlc[1 + i];
8386                        ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8387                        i += ((T30_INFO *)&nlc[1])->head_line_len;
8388                        while (i < nlc[0])
8389                                plci->fax_connect_info_buffer[len++] = nlc[++i];
8390                        plci->fax_connect_info_length = len;
8391                }
8392                else
8393                {
8394                        nlc[0] = 14;
8395                        if (b3_config->length != 16)
8396                                return _B3_PARM_NOT_SUPPORTED;
8397                        for (i = 0; i < 12; i++) nlc[1 + i] = b3_config->info[1 + i];
8398                        if (GET_WORD(&b3_config->info[13]) != 8 && GET_WORD(&b3_config->info[13]) != 128)
8399                                return _B3_PARM_NOT_SUPPORTED;
8400                        nlc[13] = b3_config->info[13];
8401                        if (GET_WORD(&b3_config->info[15]) >= nlc[13])
8402                                return _B3_PARM_NOT_SUPPORTED;
8403                        nlc[14] = b3_config->info[15];
8404                }
8405        }
8406        else
8407        {
8408                if (plci->B3_prot == 4
8409                    || plci->B3_prot == 5 /*T.30 - FAX*/) return _B3_PARM_NOT_SUPPORTED;
8410        }
8411        add_p(plci, NLC, nlc);
8412        return 0;
8413}
8414
8415/*----------------------------------------------------------------*/
8416/*      make the same as add_b23, but only for the modem related  */
8417/*      L2 and L3 B-Chan protocol.                                */
8418/*                                                                */
8419/*      Enabled L2 and L3 Configurations:                         */
8420/*        If L1 == Modem all negotiation                          */
8421/*          only L2 == Modem with full negotiation is allowed     */
8422/*        If L1 == Modem async or sync                            */
8423/*          only L2 == Transparent is allowed                     */
8424/*        L3 == Modem or L3 == Transparent are allowed            */
8425/*      B2 Configuration for modem:                               */
8426/*          word : enable/disable compression, bitoptions         */
8427/*      B3 Configuration for modem:                               */
8428/*          empty                                                 */
8429/*----------------------------------------------------------------*/
8430static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms)
8431{
8432        static byte lli[12] = {1,1};
8433        static byte llc[3] = {2,0,0};
8434        static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8435        API_PARSE mdm_config[2];
8436        word i;
8437        word b2_config = 0;
8438
8439        for (i = 0; i < 2; i++) mdm_config[i].length = 0;
8440        for (i = 0; i < sizeof(dlc); i++) dlc[i] = 0;
8441
8442        if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8443             && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8444            || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8445                && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8446        {
8447                return (_B_STACK_NOT_SUPPORTED);
8448        }
8449        if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8450            && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8451        {
8452                return (_B_STACK_NOT_SUPPORTED);
8453        }
8454
8455        plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8456        plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8457
8458        if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8459        {
8460                if (api_parse(&bp_parms[4].info[1],
8461                              (word)bp_parms[4].length, "w",
8462                              mdm_config))
8463                {
8464                        return (_WRONG_MESSAGE_FORMAT);
8465                }
8466                b2_config = GET_WORD(mdm_config[0].info);
8467        }
8468
8469        /* OK, L2 is modem */
8470
8471        lli[0] = 1;
8472        lli[1] = 1;
8473        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8474                lli[1] |= 2;
8475        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8476                lli[1] |= 4;
8477
8478        if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8479                lli[1] |= 0x10;
8480                if (plci->rx_dma_descriptor <= 0) {
8481                        plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
8482                        if (plci->rx_dma_descriptor >= 0)
8483                                plci->rx_dma_descriptor++;
8484                }
8485                if (plci->rx_dma_descriptor > 0) {
8486                        lli[1] |= 0x40;
8487                        lli[0] = 6;
8488                        lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8489                        lli[3] = (byte)plci->rx_dma_magic;
8490                        lli[4] = (byte)(plci->rx_dma_magic >>  8);
8491                        lli[5] = (byte)(plci->rx_dma_magic >> 16);
8492                        lli[6] = (byte)(plci->rx_dma_magic >> 24);
8493                }
8494        }
8495
8496        if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8497                lli[1] |= 0x20;
8498        }
8499
8500        llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8501                /*V42*/ 10 : /*V42_IN*/ 9;
8502        llc[2] = 4;                      /* pass L3 always transparent */
8503        add_p(plci, LLI, lli);
8504        add_p(plci, LLC, llc);
8505        i =  1;
8506        PUT_WORD(&dlc[i], plci->appl->MaxDataLength);
8507        i += 2;
8508        if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8509        {
8510                if (bp_parms[4].length)
8511                {
8512                        dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8513                        dlc[i++] = 3; /* Addr A */
8514                        dlc[i++] = 1; /* Addr B */
8515                        dlc[i++] = 7; /* modulo mode */
8516                        dlc[i++] = 7; /* window size */
8517                        dlc[i++] = 0; /* XID len Lo  */
8518                        dlc[i++] = 0; /* XID len Hi  */
8519
8520                        if (b2_config & MDM_B2_DISABLE_V42bis)
8521                        {
8522                                dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8523                        }
8524                        if (b2_config & MDM_B2_DISABLE_MNP)
8525                        {
8526                                dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8527                        }
8528                        if (b2_config & MDM_B2_DISABLE_TRANS)
8529                        {
8530                                dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8531                        }
8532                        if (b2_config & MDM_B2_DISABLE_V42)
8533                        {
8534                                dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8535                        }
8536                        if (b2_config & MDM_B2_DISABLE_COMP)
8537                        {
8538                                dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8539                        }
8540                        i++;
8541                }
8542        }
8543        else
8544        {
8545                dlc[i++] = 3; /* Addr A */
8546                dlc[i++] = 1; /* Addr B */
8547                dlc[i++] = 7; /* modulo mode */
8548                dlc[i++] = 7; /* window size */
8549                dlc[i++] = 0; /* XID len Lo  */
8550                dlc[i++] = 0; /* XID len Hi  */
8551                dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8552                        DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8553                        DLC_MODEMPROT_DISABLE_V42_DETECT |
8554                        DLC_MODEMPROT_DISABLE_COMPRESSION;
8555        }
8556        dlc[0] = (byte)(i - 1);
8557/* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8558        add_p(plci, DLC, dlc);
8559        return (0);
8560}
8561
8562
8563/*------------------------------------------------------------------*/
8564/* send a request for the signaling entity                          */
8565/*------------------------------------------------------------------*/
8566
8567static void sig_req(PLCI *plci, byte req, byte Id)
8568{
8569        if (!plci) return;
8570        if (plci->adapter->adapter_disabled) return;
8571        dbug(1, dprintf("sig_req(%x)", req));
8572        if (req == REMOVE)
8573                plci->sig_remove_id = plci->Sig.Id;
8574        if (plci->req_in == plci->req_in_start) {
8575                plci->req_in += 2;
8576                plci->RBuffer[plci->req_in++] = 0;
8577        }
8578        PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8579        plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
8580        plci->RBuffer[plci->req_in++] = req;  /* request */
8581        plci->RBuffer[plci->req_in++] = 0;    /* channel */
8582        plci->req_in_start = plci->req_in;
8583}
8584
8585/*------------------------------------------------------------------*/
8586/* send a request for the network layer entity                      */
8587/*------------------------------------------------------------------*/
8588
8589static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8590{
8591        if (!plci) return;
8592        if (plci->adapter->adapter_disabled) return;
8593        dbug(1, dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8594        if (req == REMOVE)
8595        {
8596                plci->nl_remove_id = plci->NL.Id;
8597                ncci_remove(plci, 0, (byte)(ncci != 0));
8598                ncci = 0;
8599        }
8600        if (plci->req_in == plci->req_in_start) {
8601                plci->req_in += 2;
8602                plci->RBuffer[plci->req_in++] = 0;
8603        }
8604        PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8605        plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */
8606        plci->RBuffer[plci->req_in++] = req;  /* request */
8607        plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
8608        plci->req_in_start = plci->req_in;
8609}
8610
8611static void send_req(PLCI *plci)
8612{
8613        ENTITY *e;
8614        word l;
8615/*  word i; */
8616
8617        if (!plci) return;
8618        if (plci->adapter->adapter_disabled) return;
8619        channel_xmit_xon(plci);
8620
8621        /* if nothing to do, return */
8622        if (plci->req_in == plci->req_out) return;
8623        dbug(1, dprintf("send_req(in=%d,out=%d)", plci->req_in, plci->req_out));
8624
8625        if (plci->nl_req || plci->sig_req) return;
8626
8627        l = GET_WORD(&plci->RBuffer[plci->req_out]);
8628        plci->req_out += 2;
8629        plci->XData[0].P = &plci->RBuffer[plci->req_out];
8630        plci->req_out += l;
8631        if (plci->RBuffer[plci->req_out] == 1)
8632        {
8633                e = &plci->NL;
8634                plci->req_out++;
8635                e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8636                e->ReqCh = plci->RBuffer[plci->req_out++];
8637                if (!(e->Id & 0x1f))
8638                {
8639                        e->Id = NL_ID;
8640                        plci->RBuffer[plci->req_out - 4] = CAI;
8641                        plci->RBuffer[plci->req_out - 3] = 1;
8642                        plci->RBuffer[plci->req_out - 2] = (plci->Sig.Id == 0xff) ? 0 : plci->Sig.Id;
8643                        plci->RBuffer[plci->req_out - 1] = 0;
8644                        l += 3;
8645                        plci->nl_global_req = plci->nl_req;
8646                }
8647                dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8648        }
8649        else
8650        {
8651                e = &plci->Sig;
8652                if (plci->RBuffer[plci->req_out])
8653                        e->Id = plci->RBuffer[plci->req_out];
8654                plci->req_out++;
8655                e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8656                e->ReqCh = plci->RBuffer[plci->req_out++];
8657                if (!(e->Id & 0x1f))
8658                        plci->sig_global_req = plci->sig_req;
8659                dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8660        }
8661        plci->XData[0].PLength = l;
8662        e->X = plci->XData;
8663        plci->adapter->request(e);
8664        dbug(1, dprintf("send_ok"));
8665}
8666
8667static void send_data(PLCI *plci)
8668{
8669        DIVA_CAPI_ADAPTER *a;
8670        DATA_B3_DESC *data;
8671        NCCI   *ncci_ptr;
8672        word ncci;
8673
8674        if (!plci->nl_req && plci->ncci_ring_list)
8675        {
8676                a = plci->adapter;
8677                ncci = plci->ncci_ring_list;
8678                do
8679                {
8680                        ncci = a->ncci_next[ncci];
8681                        ncci_ptr = &(a->ncci[ncci]);
8682                        if (!(a->ncci_ch[ncci]
8683                              && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8684                        {
8685                                if (ncci_ptr->data_pending)
8686                                {
8687                                        if ((a->ncci_state[ncci] == CONNECTED)
8688                                            || (a->ncci_state[ncci] == INC_ACT_PENDING)
8689                                            || (plci->send_disc == ncci))
8690                                        {
8691                                                data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8692                                                if ((plci->B2_prot == B2_V120_ASYNC)
8693                                                    || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8694                                                    || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8695                                                {
8696                                                        plci->NData[1].P = TransmitBufferGet(plci->appl, data->P);
8697                                                        plci->NData[1].PLength = data->Length;
8698                                                        if (data->Flags & 0x10)
8699                                                                plci->NData[0].P = v120_break_header;
8700                                                        else
8701                                                                plci->NData[0].P = v120_default_header;
8702                                                        plci->NData[0].PLength = 1;
8703                                                        plci->NL.XNum = 2;
8704                                                        plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8705                                                }
8706                                                else
8707                                                {
8708                                                        plci->NData[0].P = TransmitBufferGet(plci->appl, data->P);
8709                                                        plci->NData[0].PLength = data->Length;
8710                                                        if (data->Flags & 0x10)
8711                                                                plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8712
8713                                                        else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8714                                                                plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8715
8716                                                        else
8717                                                                plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8718                                                }
8719                                                plci->NL.X = plci->NData;
8720                                                plci->NL.ReqCh = a->ncci_ch[ncci];
8721                                                dbug(1, dprintf("%x:DREQ(%x:%x)", a->Id, plci->NL.Id, plci->NL.Req));
8722                                                plci->data_sent = true;
8723                                                plci->data_sent_ptr = data->P;
8724                                                a->request(&plci->NL);
8725                                        }
8726                                        else {
8727                                                cleanup_ncci_data(plci, ncci);
8728                                        }
8729                                }
8730                                else if (plci->send_disc == ncci)
8731                                {
8732                                        /* dprintf("N_DISC"); */
8733                                        plci->NData[0].PLength = 0;
8734                                        plci->NL.ReqCh = a->ncci_ch[ncci];
8735                                        plci->NL.Req = plci->nl_req = N_DISC;
8736                                        a->request(&plci->NL);
8737                                        plci->command = _DISCONNECT_B3_R;
8738                                        plci->send_disc = 0;
8739                                }
8740                        }
8741                } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8742                plci->ncci_ring_list = ncci;
8743        }
8744}
8745
8746static void listen_check(DIVA_CAPI_ADAPTER *a)
8747{
8748        word i, j;
8749        PLCI *plci;
8750        byte activnotifiedcalls = 0;
8751
8752        dbug(1, dprintf("listen_check(%d,%d)", a->listen_active, a->max_listen));
8753        if (!remove_started && !a->adapter_disabled)
8754        {
8755                for (i = 0; i < a->max_plci; i++)
8756                {
8757                        plci = &(a->plci[i]);
8758                        if (plci->notifiedcall) activnotifiedcalls++;
8759                }
8760                dbug(1, dprintf("listen_check(%d)", activnotifiedcalls));
8761
8762                for (i = a->listen_active; i < ((word)(a->max_listen + activnotifiedcalls)); i++) {
8763                        if ((j = get_plci(a))) {
8764                                a->listen_active++;
8765                                plci = &a->plci[j - 1];
8766                                plci->State = LISTENING;
8767
8768                                add_p(plci, OAD, "\x01\xfd");
8769
8770                                add_p(plci, KEY, "\x04\x43\x41\x32\x30");
8771
8772                                add_p(plci, CAI, "\x01\xc0");
8773                                add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
8774                                add_p(plci, LLI, "\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */
8775                                add_p(plci, SHIFT | 6, NULL);
8776                                add_p(plci, SIN, "\x02\x00\x00");
8777                                plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
8778                                sig_req(plci, ASSIGN, DSIG_ID);
8779                                send_req(plci);
8780                        }
8781                }
8782        }
8783}
8784
8785/*------------------------------------------------------------------*/
8786/* functions for all parameters sent in INDs                        */
8787/*------------------------------------------------------------------*/
8788
8789static void IndParse(PLCI *plci, const word *parms_id, byte **parms, byte multiIEsize)
8790{
8791        word ploc;            /* points to current location within packet */
8792        byte w;
8793        byte wlen;
8794        byte codeset, lock;
8795        byte *in;
8796        word i;
8797        word code;
8798        word mIEindex = 0;
8799        ploc = 0;
8800        codeset = 0;
8801        lock = 0;
8802
8803        in = plci->Sig.RBuffer->P;
8804        for (i = 0; i < parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
8805        {                            /* element but parms array is larger      */
8806                parms[i] = (byte *)"";
8807        }
8808        for (i = 0; i < multiIEsize; i++)
8809        {
8810                parms[i] = (byte *)"";
8811        }
8812
8813        while (ploc < plci->Sig.RBuffer->length - 1) {
8814
8815                /* read information element id and length                   */
8816                w = in[ploc];
8817
8818                if (w & 0x80) {
8819/*    w &=0xf0; removed, cannot detect congestion levels */
8820/*    upper 4 bit masked with w==SHIFT now               */
8821                        wlen = 0;
8822                }
8823                else {
8824                        wlen = (byte)(in[ploc + 1] + 1);
8825                }
8826                /* check if length valid (not exceeding end of packet)      */
8827                if ((ploc + wlen) > 270) return;
8828                if (lock & 0x80) lock &= 0x7f;
8829                else codeset = lock;
8830
8831                if ((w & 0xf0) == SHIFT) {
8832                        codeset = in[ploc];
8833                        if (!(codeset & 0x08)) lock = (byte)(codeset & 7);
8834                        codeset &= 7;
8835                        lock |= 0x80;
8836                }
8837                else {
8838                        if (w == ESC && wlen >= 3) code = in[ploc + 2] | 0x800;
8839                        else code = w;
8840                        code |= (codeset << 8);
8841
8842                        for (i = 1; i < parms_id[0] + 1 && parms_id[i] != code; i++);
8843
8844                        if (i < parms_id[0] + 1) {
8845                                if (!multiIEsize) { /* with multiIEs use next field index,          */
8846                                        mIEindex = i - 1;    /* with normal IEs use same index like parms_id */
8847                                }
8848
8849                                parms[mIEindex] = &in[ploc + 1];
8850                                dbug(1, dprintf("mIE[%d]=0x%x", *parms[mIEindex], in[ploc]));
8851                                if (parms_id[i] == OAD
8852                                    || parms_id[i] == CONN_NR
8853                                    || parms_id[i] == CAD) {
8854                                        if (in[ploc + 2] & 0x80) {
8855                                                in[ploc + 0] = (byte)(in[ploc + 1] + 1);
8856                                                in[ploc + 1] = (byte)(in[ploc + 2] & 0x7f);
8857                                                in[ploc + 2] = 0x80;
8858                                                parms[mIEindex] = &in[ploc];
8859                                        }
8860                                }
8861                                mIEindex++;       /* effects multiIEs only */
8862                        }
8863                }
8864
8865                ploc += (wlen + 1);
8866        }
8867        return;
8868}
8869
8870/*------------------------------------------------------------------*/
8871/* try to match a cip from received BC and HLC                      */
8872/*------------------------------------------------------------------*/
8873
8874static byte ie_compare(byte *ie1, byte *ie2)
8875{
8876        word i;
8877        if (!ie1 || !ie2) return false;
8878        if (!ie1[0]) return false;
8879        for (i = 0; i < (word)(ie1[0] + 1); i++) if (ie1[i] != ie2[i]) return false;
8880        return true;
8881}
8882
8883static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
8884{
8885        word i;
8886        word j;
8887
8888        for (i = 9; i && !ie_compare(bc, cip_bc[i][a->u_law]); i--);
8889
8890        for (j = 16; j < 29 &&
8891                     (!ie_compare(bc, cip_bc[j][a->u_law]) || !ie_compare(hlc, cip_hlc[j])); j++);
8892        if (j == 29) return i;
8893        return j;
8894}
8895
8896
8897static byte AddInfo(byte **add_i,
8898                    byte **fty_i,
8899                    byte *esc_chi,
8900                    byte *facility)
8901{
8902        byte i;
8903        byte j;
8904        byte k;
8905        byte flen;
8906        byte len = 0;
8907        /* facility is a nested structure */
8908        /* FTY can be more than once      */
8909
8910        if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
8911        {
8912                add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
8913        }
8914
8915        else
8916        {
8917                add_i[0] = (byte *)"";
8918        }
8919        if (!fty_i[0][0])
8920        {
8921                add_i[3] = (byte *)"";
8922        }
8923        else
8924        {    /* facility array found  */
8925                for (i = 0, j = 1; i < MAX_MULTI_IE && fty_i[i][0]; i++)
8926                {
8927                        dbug(1, dprintf("AddIFac[%d]", fty_i[i][0]));
8928                        len += fty_i[i][0];
8929                        len += 2;
8930                        flen = fty_i[i][0];
8931                        facility[j++] = 0x1c; /* copy fac IE */
8932                        for (k = 0; k <= flen; k++, j++)
8933                        {
8934                                facility[j] = fty_i[i][k];
8935/*      dbug(1, dprintf("%x ",facility[j])); */
8936                        }
8937                }
8938                facility[0] = len;
8939                add_i[3] = facility;
8940        }
8941/*  dbug(1, dprintf("FacArrLen=%d ",len)); */
8942        len = add_i[0][0] + add_i[1][0] + add_i[2][0] + add_i[3][0];
8943        len += 4;                          /* calculate length of all */
8944        return (len);
8945}
8946
8947/*------------------------------------------------------------------*/
8948/* voice and codec features                                         */
8949/*------------------------------------------------------------------*/
8950
8951static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
8952{
8953        byte voice_chi[] = "\x02\x18\x01";
8954        byte channel;
8955
8956        channel = chi[chi[0]] & 0x3;
8957        dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel));
8958        voice_chi[2] = (channel) ? channel : 1;
8959        add_p(plci, FTY, "\x02\x01\x07");             /* B On, default on 1 */
8960        add_p(plci, ESC, voice_chi);                  /* Channel */
8961        sig_req(plci, TEL_CTRL, 0);
8962        send_req(plci);
8963        if (a->AdvSignalPLCI)
8964        {
8965                adv_voice_write_coefs(a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
8966        }
8967}
8968
8969static void VoiceChannelOff(PLCI *plci)
8970{
8971        dbug(1, dprintf("ExtDevOFF"));
8972        add_p(plci, FTY, "\x02\x01\x08");             /* B Off */
8973        sig_req(plci, TEL_CTRL, 0);
8974        send_req(plci);
8975        if (plci->adapter->AdvSignalPLCI)
8976        {
8977                adv_voice_clear_config(plci->adapter->AdvSignalPLCI);
8978        }
8979}
8980
8981
8982static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
8983                            byte hook_listen)
8984{
8985        word j;
8986        PLCI *splci;
8987
8988        /* check if hardware supports handset with hook states (adv.codec) */
8989        /* or if just a on board codec is supported                        */
8990        /* the advanced codec plci is just for internal use                */
8991
8992        /* diva Pro with on-board codec:                                   */
8993        if (a->profile.Global_Options & HANDSET)
8994        {
8995                /* new call, but hook states are already signalled */
8996                if (a->AdvCodecFLAG)
8997                {
8998                        if (a->AdvSignalAppl != appl || a->AdvSignalPLCI)
8999                        {
9000                                dbug(1, dprintf("AdvSigPlci=0x%x", a->AdvSignalPLCI));
9001                                return 0x2001; /* codec in use by another application */
9002                        }
9003                        if (plci != NULL)
9004                        {
9005                                a->AdvSignalPLCI = plci;
9006                                plci->tel = ADV_VOICE;
9007                        }
9008                        return 0;                      /* adv codec still used */
9009                }
9010                if ((j = get_plci(a)))
9011                {
9012                        splci = &a->plci[j - 1];
9013                        splci->tel = CODEC_PERMANENT;
9014                        /* hook_listen indicates if a facility_req with handset/hook support */
9015                        /* was sent. Otherwise if just a call on an external device was made */
9016                        /* the codec will be used but the hook info will be discarded (just  */
9017                        /* the external controller is in use                                 */
9018                        if (hook_listen) splci->State = ADVANCED_VOICE_SIG;
9019                        else
9020                        {
9021                                splci->State = ADVANCED_VOICE_NOSIG;
9022                                if (plci)
9023                                {
9024                                        plci->spoofed_msg = SPOOFING_REQUIRED;
9025                                }
9026                                /* indicate D-ch connect if  */
9027                        }                                        /* codec is connected OK     */
9028                        if (plci != NULL)
9029                        {
9030                                a->AdvSignalPLCI = plci;
9031                                plci->tel = ADV_VOICE;
9032                        }
9033                        a->AdvSignalAppl = appl;
9034                        a->AdvCodecFLAG = true;
9035                        a->AdvCodecPLCI = splci;
9036                        add_p(splci, CAI, "\x01\x15");
9037                        add_p(splci, LLI, "\x01\x00");
9038                        add_p(splci, ESC, "\x02\x18\x00");
9039                        add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9040                        splci->internal_command = PERM_COD_ASSIGN;
9041                        dbug(1, dprintf("Codec Assign"));
9042                        sig_req(splci, ASSIGN, DSIG_ID);
9043                        send_req(splci);
9044                }
9045                else
9046                {
9047                        return 0x2001; /* wrong state, no more plcis */
9048                }
9049        }
9050        else if (a->profile.Global_Options & ON_BOARD_CODEC)
9051        {
9052                if (hook_listen) return 0x300B;               /* Facility not supported */
9053                /* no hook with SCOM      */
9054                if (plci != NULL) plci->tel = CODEC;
9055                dbug(1, dprintf("S/SCOM codec"));
9056                /* first time we use the scom-s codec we must shut down the internal   */
9057                /* handset application of the card. This can be done by an assign with */
9058                /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9059                if (!a->scom_appl_disable) {
9060                        if ((j = get_plci(a))) {
9061                                splci = &a->plci[j - 1];
9062                                add_p(splci, CAI, "\x01\x80");
9063                                add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9064                                sig_req(splci, ASSIGN, 0xC0);  /* 0xc0 is the TEL_ID */
9065                                send_req(splci);
9066                                a->scom_appl_disable = true;
9067                        }
9068                        else{
9069                                return 0x2001; /* wrong state, no more plcis */
9070                        }
9071                }
9072        }
9073        else return 0x300B;               /* Facility not supported */
9074
9075        return 0;
9076}
9077
9078
9079static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9080{
9081
9082        dbug(1, dprintf("CodecIdCheck"));
9083
9084        if (a->AdvSignalPLCI == plci)
9085        {
9086                dbug(1, dprintf("PLCI owns codec"));
9087                VoiceChannelOff(a->AdvCodecPLCI);
9088                if (a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9089                {
9090                        dbug(1, dprintf("remove temp codec PLCI"));
9091                        plci_remove(a->AdvCodecPLCI);
9092                        a->AdvCodecFLAG  = 0;
9093                        a->AdvCodecPLCI  = NULL;
9094                        a->AdvSignalAppl = NULL;
9095                }
9096                a->AdvSignalPLCI = NULL;
9097        }
9098}
9099
9100/* -------------------------------------------------------------------
9101   Ask for physical address of card on PCI bus
9102   ------------------------------------------------------------------- */
9103static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *a,
9104                                       IDI_SYNC_REQ *preq) {
9105        a->sdram_bar = 0;
9106        if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9107                ENTITY *e = (ENTITY *)preq;
9108
9109                e->user[0] = a->Id - 1;
9110                preq->xdi_sdram_bar.info.bar    = 0;
9111                preq->xdi_sdram_bar.Req         = 0;
9112                preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9113
9114                (*(a->request))(e);
9115
9116                a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9117                dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9118        }
9119}
9120
9121/* -------------------------------------------------------------------
9122   Ask XDI about extended features
9123   ------------------------------------------------------------------- */
9124static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a) {
9125        IDI_SYNC_REQ *preq;
9126        char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
9127
9128        char features[4];
9129        preq = (IDI_SYNC_REQ *)&buffer[0];
9130
9131        if (!diva_xdi_extended_features) {
9132                ENTITY *e = (ENTITY *)preq;
9133                diva_xdi_extended_features |= 0x80000000;
9134
9135                e->user[0] = a->Id - 1;
9136                preq->xdi_extended_features.Req = 0;
9137                preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9138                preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9139                preq->xdi_extended_features.info.features = &features[0];
9140
9141                (*(a->request))(e);
9142
9143                if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9144                        /*
9145                          Check features located in the byte '0'
9146                        */
9147                        if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9148                                diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9149                        }
9150                        if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9151                                diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9152                                dbug(1, dprintf("XDI provides RxDMA"));
9153                        }
9154                        if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9155                                diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9156                        }
9157                        if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9158                                diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9159                                dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9160                        }
9161
9162                }
9163        }
9164
9165        diva_ask_for_xdi_sdram_bar(a, preq);
9166}
9167
9168/*------------------------------------------------------------------*/
9169/* automatic law                                                    */
9170/*------------------------------------------------------------------*/
9171/* called from OS specific part after init time to get the Law              */
9172/* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9173void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9174{
9175        word j;
9176        PLCI *splci;
9177
9178        if (a->automatic_law) {
9179                return;
9180        }
9181        if ((j = get_plci(a))) {
9182                diva_get_extended_adapter_features(a);
9183                splci = &a->plci[j - 1];
9184                a->automatic_lawPLCI = splci;
9185                a->automatic_law = 1;
9186                add_p(splci, CAI, "\x01\x80");
9187                add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9188                splci->internal_command = USELAW_REQ;
9189                splci->command = 0;
9190                splci->number = 0;
9191                sig_req(splci, ASSIGN, DSIG_ID);
9192                send_req(splci);
9193        }
9194}
9195
9196/* called from OS specific part if an application sends an Capi20Release */
9197word CapiRelease(word Id)
9198{
9199        word i, j, appls_found;
9200        PLCI *plci;
9201        APPL   *this;
9202        DIVA_CAPI_ADAPTER *a;
9203
9204        if (!Id)
9205        {
9206                dbug(0, dprintf("A: CapiRelease(Id==0)"));
9207                return (_WRONG_APPL_ID);
9208        }
9209
9210        this = &application[Id - 1];               /* get application pointer */
9211
9212        for (i = 0, appls_found = 0; i < max_appl; i++)
9213        {
9214                if (application[i].Id)       /* an application has been found        */
9215                {
9216                        appls_found++;
9217                }
9218        }
9219
9220        for (i = 0; i < max_adapter; i++)             /* scan all adapters...    */
9221        {
9222                a = &adapter[i];
9223                if (a->request)
9224                {
9225                        a->Info_Mask[Id - 1] = 0;
9226                        a->CIP_Mask[Id - 1] = 0;
9227                        a->Notification_Mask[Id - 1] = 0;
9228                        a->codec_listen[Id - 1] = NULL;
9229                        a->requested_options_table[Id - 1] = 0;
9230                        for (j = 0; j < a->max_plci; j++)           /* and all PLCIs connected */
9231                        {                                      /* with this application   */
9232                                plci = &a->plci[j];
9233                                if (plci->Id)                         /* if plci owns no application */
9234                                {                                    /* it may be not jet connected */
9235                                        if (plci->State == INC_CON_PENDING
9236                                            || plci->State == INC_CON_ALERT)
9237                                        {
9238                                                if (test_bit(Id - 1, plci->c_ind_mask_table))
9239                                                {
9240                                                        __clear_bit(Id - 1, plci->c_ind_mask_table);
9241                                                        if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9242                                                        {
9243                                                                sig_req(plci, HANGUP, 0);
9244                                                                send_req(plci);
9245                                                                plci->State = OUTG_DIS_PENDING;
9246                                                        }
9247                                                }
9248                                        }
9249                                        if (test_bit(Id - 1, plci->c_ind_mask_table))
9250                                        {
9251                                                __clear_bit(Id - 1, plci->c_ind_mask_table);
9252                                                if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9253                                                {
9254                                                        if (!plci->appl)
9255                                                        {
9256                                                                plci_remove(plci);
9257                                                                plci->State = IDLE;
9258                                                        }
9259                                                }
9260                                        }
9261                                        if (plci->appl == this)
9262                                        {
9263                                                plci->appl = NULL;
9264                                                plci_remove(plci);
9265                                                plci->State = IDLE;
9266                                        }
9267                                }
9268                        }
9269                        listen_check(a);
9270
9271                        if (a->flag_dynamic_l1_down)
9272                        {
9273                                if (appls_found == 1)            /* last application does a capi release */
9274                                {
9275                                        if ((j = get_plci(a)))
9276                                        {
9277                                                plci = &a->plci[j - 1];
9278                                                plci->command = 0;
9279                                                add_p(plci, OAD, "\x01\xfd");
9280                                                add_p(plci, CAI, "\x01\x80");
9281                                                add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9282                                                add_p(plci, SHIFT | 6, NULL);
9283                                                add_p(plci, SIN, "\x02\x00\x00");
9284                                                plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9285                                                sig_req(plci, ASSIGN, DSIG_ID);
9286                                                add_p(plci, FTY, "\x02\xff\x06"); /* l1 down */
9287                                                sig_req(plci, SIG_CTRL, 0);
9288                                                send_req(plci);
9289                                        }
9290                                }
9291                        }
9292                        if (a->AdvSignalAppl == this)
9293                        {
9294                                this->NullCREnable = false;
9295                                if (a->AdvCodecPLCI)
9296                                {
9297                                        plci_remove(a->AdvCodecPLCI);
9298                                        a->AdvCodecPLCI->tel = 0;
9299                                        a->AdvCodecPLCI->adv_nl = 0;
9300                                }
9301                                a->AdvSignalAppl = NULL;
9302                                a->AdvSignalPLCI = NULL;
9303                                a->AdvCodecFLAG = 0;
9304                                a->AdvCodecPLCI = NULL;
9305                        }
9306                }
9307        }
9308
9309        this->Id = 0;
9310
9311        return GOOD;
9312}
9313
9314static word plci_remove_check(PLCI *plci)
9315{
9316        if (!plci) return true;
9317        if (!plci->NL.Id && bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9318        {
9319                if (plci->Sig.Id == 0xff)
9320                        plci->Sig.Id = 0;
9321                if (!plci->Sig.Id)
9322                {
9323                        dbug(1, dprintf("plci_remove_complete(%x)", plci->Id));
9324                        dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci->tel, plci->Sig.Id));
9325                        if (plci->Id)
9326                        {
9327                                CodecIdCheck(plci->adapter, plci);
9328                                clear_b1_config(plci);
9329                                ncci_remove(plci, 0, false);
9330                                plci_free_msg_in_queue(plci);
9331                                channel_flow_control_remove(plci);
9332                                plci->Id = 0;
9333                                plci->State = IDLE;
9334                                plci->channels = 0;
9335                                plci->appl = NULL;
9336                                plci->notifiedcall = 0;
9337                        }
9338                        listen_check(plci->adapter);
9339                        return true;
9340                }
9341        }
9342        return false;
9343}
9344
9345
9346/*------------------------------------------------------------------*/
9347
9348static byte plci_nl_busy(PLCI *plci)
9349{
9350        /* only applicable for non-multiplexed protocols */
9351        return (plci->nl_req
9352                || (plci->ncci_ring_list
9353                    && plci->adapter->ncci_ch[plci->ncci_ring_list]
9354                    && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9355}
9356
9357
9358/*------------------------------------------------------------------*/
9359/* DTMF facilities                                                  */
9360/*------------------------------------------------------------------*/
9361
9362
9363static struct
9364{
9365        byte send_mask;
9366        byte listen_mask;
9367        byte character;
9368        byte code;
9369} dtmf_digit_map[] =
9370{
9371        { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9372        { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9373        { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9374        { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9375        { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9376        { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9377        { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9378        { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9379        { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9380        { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9381        { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9382        { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9383        { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9384        { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9385        { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9386        { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9387        { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9388        { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9389        { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9390        { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9391
9392        { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9393        { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9394        { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9395        { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9396        { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9397        { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9398        { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9399        { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9400        { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9401        { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9402        { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9403        { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9404        { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9405        { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9406        { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9407        { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9408        { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9409        { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9410        { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9411        { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9412        { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9413        { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9414        { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9415        { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9416        { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9417        { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9418        { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9419        { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9420        { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9421        { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9422        { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9423        { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9424        { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9425        { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9426        { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9427        { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9428        { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9429        { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9430        { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9431        { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9432        { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9433        { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9434        { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9435        { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9436        { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9437        { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9438        { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9439        { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9440        { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9441        { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9442        { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9443        { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9444
9445};
9446
9447#define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9448
9449
9450static void dtmf_enable_receiver(PLCI *plci, byte enable_mask)
9451{
9452        word min_digit_duration, min_gap_duration;
9453
9454        dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9455                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9456                        (char *)(FILE_), __LINE__, enable_mask));
9457
9458        if (enable_mask != 0)
9459        {
9460                min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9461                min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9462                plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9463                PUT_WORD(&plci->internal_req_buffer[1], min_digit_duration);
9464                PUT_WORD(&plci->internal_req_buffer[3], min_gap_duration);
9465                plci->NData[0].PLength = 5;
9466
9467                PUT_WORD(&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9468                plci->NData[0].PLength += 2;
9469                capidtmf_recv_enable(&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9470
9471        }
9472        else
9473        {
9474                plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9475                plci->NData[0].PLength = 1;
9476
9477                capidtmf_recv_disable(&(plci->capidtmf_state));
9478
9479        }
9480        plci->NData[0].P = plci->internal_req_buffer;
9481        plci->NL.X = plci->NData;
9482        plci->NL.ReqCh = 0;
9483        plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9484        plci->adapter->request(&plci->NL);
9485}
9486
9487
9488static void dtmf_send_digits(PLCI *plci, byte *digit_buffer, word digit_count)
9489{
9490        word w, i;
9491
9492        dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9493                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9494                        (char *)(FILE_), __LINE__, digit_count));
9495
9496        plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9497        w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9498        PUT_WORD(&plci->internal_req_buffer[1], w);
9499        w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9500        PUT_WORD(&plci->internal_req_buffer[3], w);
9501        for (i = 0; i < digit_count; i++)
9502        {
9503                w = 0;
9504                while ((w < DTMF_DIGIT_MAP_ENTRIES)
9505                       && (digit_buffer[i] != dtmf_digit_map[w].character))
9506                {
9507                        w++;
9508                }
9509                plci->internal_req_buffer[5 + i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9510                        dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9511        }
9512        plci->NData[0].PLength = 5 + digit_count;
9513        plci->NData[0].P = plci->internal_req_buffer;
9514        plci->NL.X = plci->NData;
9515        plci->NL.ReqCh = 0;
9516        plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9517        plci->adapter->request(&plci->NL);
9518}
9519
9520
9521static void dtmf_rec_clear_config(PLCI *plci)
9522{
9523
9524        dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9525                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9526                        (char *)(FILE_), __LINE__));
9527
9528        plci->dtmf_rec_active = 0;
9529        plci->dtmf_rec_pulse_ms = 0;
9530        plci->dtmf_rec_pause_ms = 0;
9531
9532        capidtmf_init(&(plci->capidtmf_state), plci->adapter->u_law);
9533
9534}
9535
9536
9537static void dtmf_send_clear_config(PLCI *plci)
9538{
9539
9540        dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9541                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9542                        (char *)(FILE_), __LINE__));
9543
9544        plci->dtmf_send_requests = 0;
9545        plci->dtmf_send_pulse_ms = 0;
9546        plci->dtmf_send_pause_ms = 0;
9547}
9548
9549
9550static void dtmf_prepare_switch(dword Id, PLCI *plci)
9551{
9552
9553        dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9554                        UnMapId(Id), (char *)(FILE_), __LINE__));
9555
9556        while (plci->dtmf_send_requests != 0)
9557                dtmf_confirmation(Id, plci);
9558}
9559
9560
9561static word dtmf_save_config(dword Id, PLCI *plci, byte Rc)
9562{
9563
9564        dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9565                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9566
9567        return (GOOD);
9568}
9569
9570
9571static word dtmf_restore_config(dword Id, PLCI *plci, byte Rc)
9572{
9573        word Info;
9574
9575        dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9576                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9577
9578        Info = GOOD;
9579        if (plci->B1_facilities & B1_FACILITY_DTMFR)
9580        {
9581                switch (plci->adjust_b_state)
9582                {
9583                case ADJUST_B_RESTORE_DTMF_1:
9584                        plci->internal_command = plci->adjust_b_command;
9585                        if (plci_nl_busy(plci))
9586                        {
9587                                plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9588                                break;
9589                        }
9590                        dtmf_enable_receiver(plci, plci->dtmf_rec_active);
9591                        plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9592                        break;
9593                case ADJUST_B_RESTORE_DTMF_2:
9594                        if ((Rc != OK) && (Rc != OK_FC))
9595                        {
9596                                dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9597                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9598                                Info = _WRONG_STATE;
9599                                break;
9600                        }
9601                        break;
9602                }
9603        }
9604        return (Info);
9605}
9606
9607
9608static void dtmf_command(dword Id, PLCI *plci, byte Rc)
9609{
9610        word internal_command, Info;
9611        byte mask;
9612        byte result[4];
9613
9614        dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9615                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9616                        plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9617                        plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9618
9619        Info = GOOD;
9620        result[0] = 2;
9621        PUT_WORD(&result[1], DTMF_SUCCESS);
9622        internal_command = plci->internal_command;
9623        plci->internal_command = 0;
9624        mask = 0x01;
9625        switch (plci->dtmf_cmd)
9626        {
9627
9628        case DTMF_LISTEN_TONE_START:
9629                mask <<= 1;
9630        case DTMF_LISTEN_MF_START:
9631                mask <<= 1;
9632
9633        case DTMF_LISTEN_START:
9634                switch (internal_command)
9635                {
9636                default:
9637                        adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9638                                                                  B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9639                case DTMF_COMMAND_1:
9640                        if (adjust_b_process(Id, plci, Rc) != GOOD)
9641                        {
9642                                dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9643                                                UnMapId(Id), (char *)(FILE_), __LINE__));
9644                                Info = _FACILITY_NOT_SUPPORTED;
9645                                break;
9646                        }
9647                        if (plci->internal_command)
9648                                return;
9649                case DTMF_COMMAND_2:
9650                        if (plci_nl_busy(plci))
9651                        {
9652                                plci->internal_command = DTMF_COMMAND_2;
9653                                return;
9654                        }
9655                        plci->internal_command = DTMF_COMMAND_3;
9656                        dtmf_enable_receiver(plci, (byte)(plci->dtmf_rec_active | mask));
9657                        return;
9658                case DTMF_COMMAND_3:
9659                        if ((Rc != OK) && (Rc != OK_FC))
9660                        {
9661                                dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9662                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9663                                Info = _FACILITY_NOT_SUPPORTED;
9664                                break;
9665                        }
9666
9667                        plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9668
9669                        plci->dtmf_rec_active |= mask;
9670                        break;
9671                }
9672                break;
9673
9674
9675        case DTMF_LISTEN_TONE_STOP:
9676                mask <<= 1;
9677        case DTMF_LISTEN_MF_STOP:
9678                mask <<= 1;
9679
9680        case DTMF_LISTEN_STOP:
9681                switch (internal_command)
9682                {
9683                default:
9684                        plci->dtmf_rec_active &= ~mask;
9685                        if (plci->dtmf_rec_active)
9686                                break;
9687/*
9688  case DTMF_COMMAND_1:
9689  if (plci->dtmf_rec_active)
9690  {
9691  if (plci_nl_busy (plci))
9692  {
9693  plci->internal_command = DTMF_COMMAND_1;
9694  return;
9695  }
9696  plci->dtmf_rec_active &= ~mask;
9697  plci->internal_command = DTMF_COMMAND_2;
9698  dtmf_enable_receiver (plci, false);
9699  return;
9700  }
9701  Rc = OK;
9702  case DTMF_COMMAND_2:
9703  if ((Rc != OK) && (Rc != OK_FC))
9704  {
9705  dbug (1, dprintf("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9706  UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9707  Info = _FACILITY_NOT_SUPPORTED;
9708  break;
9709  }
9710*/
9711                        adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
9712                                                                  ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9713                case DTMF_COMMAND_3:
9714                        if (adjust_b_process(Id, plci, Rc) != GOOD)
9715                        {
9716                                dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9717                                                UnMapId(Id), (char *)(FILE_), __LINE__));
9718                                Info = _FACILITY_NOT_SUPPORTED;
9719                                break;
9720                        }
9721                        if (plci->internal_command)
9722                                return;
9723                        break;
9724                }
9725                break;
9726
9727
9728        case DTMF_SEND_TONE:
9729                mask <<= 1;
9730        case DTMF_SEND_MF:
9731                mask <<= 1;
9732
9733        case DTMF_DIGITS_SEND:
9734                switch (internal_command)
9735                {
9736                default:
9737                        adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9738                                                                  ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9739                                           DTMF_COMMAND_1);
9740                case DTMF_COMMAND_1:
9741                        if (adjust_b_process(Id, plci, Rc) != GOOD)
9742                        {
9743                                dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9744                                                UnMapId(Id), (char *)(FILE_), __LINE__));
9745                                Info = _FACILITY_NOT_SUPPORTED;
9746                                break;
9747                        }
9748                        if (plci->internal_command)
9749                                return;
9750                case DTMF_COMMAND_2:
9751                        if (plci_nl_busy(plci))
9752                        {
9753                                plci->internal_command = DTMF_COMMAND_2;
9754                                return;
9755                        }
9756                        plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9757                        plci->internal_command = DTMF_COMMAND_3;
9758                        dtmf_send_digits(plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9759                        return;
9760                case DTMF_COMMAND_3:
9761                        if ((Rc != OK) && (Rc != OK_FC))
9762                        {
9763                                dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9764                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9765                                if (plci->dtmf_send_requests != 0)
9766                                        (plci->dtmf_send_requests)--;
9767                                Info = _FACILITY_NOT_SUPPORTED;
9768                                break;
9769                        }
9770                        return;
9771                }
9772                break;
9773        }
9774        sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9775              "wws", Info, SELECTOR_DTMF, result);
9776}
9777
9778
9779static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
9780{
9781        word Info;
9782        word i, j;
9783        byte mask;
9784        API_PARSE dtmf_parms[5];
9785        byte result[40];
9786
9787        dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9788                        UnMapId(Id), (char *)(FILE_), __LINE__));
9789
9790        Info = GOOD;
9791        result[0] = 2;
9792        PUT_WORD(&result[1], DTMF_SUCCESS);
9793        if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9794        {
9795                dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9796                                UnMapId(Id), (char *)(FILE_), __LINE__));
9797                Info = _FACILITY_NOT_SUPPORTED;
9798        }
9799        else if (api_parse(&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9800        {
9801                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9802                                UnMapId(Id), (char *)(FILE_), __LINE__));
9803                Info = _WRONG_MESSAGE_FORMAT;
9804        }
9805
9806        else if ((GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9807                 || (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9808        {
9809                if (!((a->requested_options_table[appl->Id - 1])
9810                      & (1L << PRIVATE_DTMF_TONE)))
9811                {
9812                        dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9813                                        UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9814                        PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9815                }
9816                else
9817                {
9818                        for (i = 0; i < 32; i++)
9819                                result[4 + i] = 0;
9820                        if (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9821                        {
9822                                for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9823                                {
9824                                        if (dtmf_digit_map[i].listen_mask != 0)
9825                                                result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9826                                }
9827                        }
9828                        else
9829                        {
9830                                for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9831                                {
9832                                        if (dtmf_digit_map[i].send_mask != 0)
9833                                                result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9834                                }
9835                        }
9836                        result[0] = 3 + 32;
9837                        result[3] = 32;
9838                }
9839        }
9840
9841        else if (plci == NULL)
9842        {
9843                dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9844                                UnMapId(Id), (char *)(FILE_), __LINE__));
9845                Info = _WRONG_IDENTIFIER;
9846        }
9847        else
9848        {
9849                if (!plci->State
9850                    || !plci->NL.Id || plci->nl_remove_id)
9851                {
9852                        dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9853                                        UnMapId(Id), (char *)(FILE_), __LINE__));
9854                        Info = _WRONG_STATE;
9855                }
9856                else
9857                {
9858                        plci->command = 0;
9859                        plci->dtmf_cmd = GET_WORD(dtmf_parms[0].info);
9860                        mask = 0x01;
9861                        switch (plci->dtmf_cmd)
9862                        {
9863
9864                        case DTMF_LISTEN_TONE_START:
9865                        case DTMF_LISTEN_TONE_STOP:
9866                                mask <<= 1;
9867                        case DTMF_LISTEN_MF_START:
9868                        case DTMF_LISTEN_MF_STOP:
9869                                mask <<= 1;
9870                                if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
9871                                      & (1L << PRIVATE_DTMF_TONE)))
9872                                {
9873                                        dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9874                                                        UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9875                                        PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9876                                        break;
9877                                }
9878
9879                        case DTMF_LISTEN_START:
9880                        case DTMF_LISTEN_STOP:
9881                                if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
9882                                    && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
9883                                {
9884                                        dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9885                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
9886                                        Info = _FACILITY_NOT_SUPPORTED;
9887                                        break;
9888                                }
9889                                if (mask & DTMF_LISTEN_ACTIVE_FLAG)
9890                                {
9891                                        if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
9892                                        {
9893                                                plci->dtmf_rec_pulse_ms = 0;
9894                                                plci->dtmf_rec_pause_ms = 0;
9895                                        }
9896                                        else
9897                                        {
9898                                                plci->dtmf_rec_pulse_ms = GET_WORD(dtmf_parms[1].info);
9899                                                plci->dtmf_rec_pause_ms = GET_WORD(dtmf_parms[2].info);
9900                                        }
9901                                }
9902                                start_internal_command(Id, plci, dtmf_command);
9903                                return (false);
9904
9905
9906                        case DTMF_SEND_TONE:
9907                                mask <<= 1;
9908                        case DTMF_SEND_MF:
9909                                mask <<= 1;
9910                                if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
9911                                      & (1L << PRIVATE_DTMF_TONE)))
9912                                {
9913                                        dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9914                                                        UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9915                                        PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9916                                        break;
9917                                }
9918
9919                        case DTMF_DIGITS_SEND:
9920                                if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
9921                                {
9922                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9923                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
9924                                        Info = _WRONG_MESSAGE_FORMAT;
9925                                        break;
9926                                }
9927                                if (mask & DTMF_LISTEN_ACTIVE_FLAG)
9928                                {
9929                                        plci->dtmf_send_pulse_ms = GET_WORD(dtmf_parms[1].info);
9930                                        plci->dtmf_send_pause_ms = GET_WORD(dtmf_parms[2].info);
9931                                }
9932                                i = 0;
9933                                j = 0;
9934                                while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
9935                                {
9936                                        j = 0;
9937                                        while ((j < DTMF_DIGIT_MAP_ENTRIES)
9938                                               && ((dtmf_parms[3].info[i + 1] != dtmf_digit_map[j].character)
9939                                                   || ((dtmf_digit_map[j].send_mask & mask) == 0)))
9940                                        {
9941                                                j++;
9942                                        }
9943                                        i++;
9944                                }
9945                                if (j == DTMF_DIGIT_MAP_ENTRIES)
9946                                {
9947                                        dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
9948                                                        UnMapId(Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
9949                                        PUT_WORD(&result[1], DTMF_INCORRECT_DIGIT);
9950                                        break;
9951                                }
9952                                if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
9953                                {
9954                                        dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
9955                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
9956                                        Info = _WRONG_STATE;
9957                                        break;
9958                                }
9959                                api_save_msg(dtmf_parms, "wwws", &plci->saved_msg);
9960                                start_internal_command(Id, plci, dtmf_command);
9961                                return (false);
9962
9963                        default:
9964                                dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9965                                                UnMapId(Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
9966                                PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9967                        }
9968                }
9969        }
9970        sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
9971              "wws", Info, SELECTOR_DTMF, result);
9972        return (false);
9973}
9974
9975
9976static void dtmf_confirmation(dword Id, PLCI *plci)
9977{
9978        word i;
9979        byte result[4];
9980
9981        dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
9982                        UnMapId(Id), (char *)(FILE_), __LINE__));
9983
9984        result[0] = 2;
9985        PUT_WORD(&result[1], DTMF_SUCCESS);
9986        if (plci->dtmf_send_requests != 0)
9987        {
9988                sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
9989                      "wws", GOOD, SELECTOR_DTMF, result);
9990                (plci->dtmf_send_requests)--;
9991                for (i = 0; i < plci->dtmf_send_requests; i++)
9992                        plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i + 1];
9993        }
9994}
9995
9996
9997static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length)
9998{
9999        word i, j, n;
10000
10001        dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10002                        UnMapId(Id), (char *)(FILE_), __LINE__));
10003
10004        n = 0;
10005        for (i = 1; i < length; i++)
10006        {
10007                j = 0;
10008                while ((j < DTMF_DIGIT_MAP_ENTRIES)
10009                       && ((msg[i] != dtmf_digit_map[j].code)
10010                           || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10011                {
10012                        j++;
10013                }
10014                if (j < DTMF_DIGIT_MAP_ENTRIES)
10015                {
10016
10017                        if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10018                            && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10019                            && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10020                        {
10021                                if (n + 1 == i)
10022                                {
10023                                        for (i = length; i > n + 1; i--)
10024                                                msg[i] = msg[i - 1];
10025                                        length++;
10026                                        i++;
10027                                }
10028                                msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10029                        }
10030                        plci->tone_last_indication_code = dtmf_digit_map[j].character;
10031
10032                        msg[++n] = dtmf_digit_map[j].character;
10033                }
10034        }
10035        if (n != 0)
10036        {
10037                msg[0] = (byte) n;
10038                sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10039        }
10040}
10041
10042
10043/*------------------------------------------------------------------*/
10044/* DTMF parameters                                                  */
10045/*------------------------------------------------------------------*/
10046
10047static void dtmf_parameter_write(PLCI *plci)
10048{
10049        word i;
10050        byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10051
10052        dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10053                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10054                        (char *)(FILE_), __LINE__));
10055
10056        parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10057        parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10058        for (i = 0; i < plci->dtmf_parameter_length; i++)
10059                parameter_buffer[2 + i] = plci->dtmf_parameter_buffer[i];
10060        add_p(plci, FTY, parameter_buffer);
10061        sig_req(plci, TEL_CTRL, 0);
10062        send_req(plci);
10063}
10064
10065
10066static void dtmf_parameter_clear_config(PLCI *plci)
10067{
10068
10069        dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10070                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10071                        (char *)(FILE_), __LINE__));
10072
10073        plci->dtmf_parameter_length = 0;
10074}
10075
10076
10077static void dtmf_parameter_prepare_switch(dword Id, PLCI *plci)
10078{
10079
10080        dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10081                        UnMapId(Id), (char *)(FILE_), __LINE__));
10082
10083}
10084
10085
10086static word dtmf_parameter_save_config(dword Id, PLCI *plci, byte Rc)
10087{
10088
10089        dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10090                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10091
10092        return (GOOD);
10093}
10094
10095
10096static word dtmf_parameter_restore_config(dword Id, PLCI *plci, byte Rc)
10097{
10098        word Info;
10099
10100        dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10101                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10102
10103        Info = GOOD;
10104        if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10105            && (plci->dtmf_parameter_length != 0))
10106        {
10107                switch (plci->adjust_b_state)
10108                {
10109                case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10110                        plci->internal_command = plci->adjust_b_command;
10111                        if (plci->sig_req)
10112                        {
10113                                plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10114                                break;
10115                        }
10116                        dtmf_parameter_write(plci);
10117                        plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10118                        break;
10119                case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10120                        if ((Rc != OK) && (Rc != OK_FC))
10121                        {
10122                                dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10123                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10124                                Info = _WRONG_STATE;
10125                                break;
10126                        }
10127                        break;
10128                }
10129        }
10130        return (Info);
10131}
10132
10133
10134/*------------------------------------------------------------------*/
10135/* Line interconnect facilities                                     */
10136/*------------------------------------------------------------------*/
10137
10138
10139LI_CONFIG   *li_config_table;
10140word li_total_channels;
10141
10142
10143/*------------------------------------------------------------------*/
10144/* translate a CHI information element to a channel number          */
10145/* returns 0xff - any channel                                       */
10146/*         0xfe - chi wrong coding                                  */
10147/*         0xfd - D-channel                                         */
10148/*         0x00 - no channel                                        */
10149/*         else channel number / PRI: timeslot                      */
10150/* if channels is provided we accept more than one channel.         */
10151/*------------------------------------------------------------------*/
10152
10153static byte chi_to_channel(byte *chi, dword *pchannelmap)
10154{
10155        int p;
10156        int i;
10157        dword map;
10158        byte excl;
10159        byte ofs;
10160        byte ch;
10161
10162        if (pchannelmap) *pchannelmap = 0;
10163        if (!chi[0]) return 0xff;
10164        excl = 0;
10165
10166        if (chi[1] & 0x20) {
10167                if (chi[0] == 1 && chi[1] == 0xac) return 0xfd; /* exclusive d-channel */
10168                for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10169                if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10170                if ((chi[1] | 0xc8) != 0xe9) return 0xfe;
10171                if (chi[1] & 0x08) excl = 0x40;
10172
10173                /* int. id present */
10174                if (chi[1] & 0x40) {
10175                        p = i + 1;
10176                        for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10177                        if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10178                }
10179
10180                /* coding standard, Number/Map, Channel Type */
10181                p = i + 1;
10182                for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10183                if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10184                if ((chi[p] | 0xd0) != 0xd3) return 0xfe;
10185
10186                /* Number/Map */
10187                if (chi[p] & 0x10) {
10188
10189                        /* map */
10190                        if ((chi[0] - p) == 4) ofs = 0;
10191                        else if ((chi[0] - p) == 3) ofs = 1;
10192                        else return 0xfe;
10193                        ch = 0;
10194                        map = 0;
10195                        for (i = 0; i < 4 && p < chi[0]; i++) {
10196                                p++;
10197                                ch += 8;
10198                                map <<= 8;
10199                                if (chi[p]) {
10200                                        for (ch = 0; !(chi[p] & (1 << ch)); ch++);
10201                                        map |= chi[p];
10202                                }
10203                        }
10204                        ch += ofs;
10205                        map <<= ofs;
10206                }
10207                else {
10208
10209                        /* number */
10210                        p = i + 1;
10211                        ch = chi[p] & 0x3f;
10212                        if (pchannelmap) {
10213                                if ((byte)(chi[0] - p) > 30) return 0xfe;
10214                                map = 0;
10215                                for (i = p; i <= chi[0]; i++) {
10216                                        if ((chi[i] & 0x7f) > 31) return 0xfe;
10217                                        map |= (1L << (chi[i] & 0x7f));
10218                                }
10219                        }
10220                        else {
10221                                if (p != chi[0]) return 0xfe;
10222                                if (ch > 31) return 0xfe;
10223                                map = (1L << ch);
10224                        }
10225                        if (chi[p] & 0x40) return 0xfe;
10226                }
10227                if (pchannelmap) *pchannelmap = map;
10228                else if (map != ((dword)(1L << ch))) return 0xfe;
10229                return (byte)(excl | ch);
10230        }
10231        else {  /* not PRI */
10232                for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10233                if (i != chi[0] || !(chi[i] & 0x80)) return 0xfe;
10234                if (chi[1] & 0x08) excl = 0x40;
10235
10236                switch (chi[1] | 0x98) {
10237                case 0x98: return 0;
10238                case 0x99:
10239                        if (pchannelmap) *pchannelmap = 2;
10240                        return excl | 1;
10241                case 0x9a:
10242                        if (pchannelmap) *pchannelmap = 4;
10243                        return excl | 2;
10244                case 0x9b: return 0xff;
10245                case 0x9c: return 0xfd; /* d-ch */
10246                default: return 0xfe;
10247                }
10248        }
10249}
10250
10251
10252static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id)
10253{
10254        DIVA_CAPI_ADAPTER *a;
10255        PLCI *splci;
10256        byte old_id;
10257
10258        a = plci->adapter;
10259        old_id = plci->li_bchannel_id;
10260        if (a->li_pri)
10261        {
10262                if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10263                        li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10264                plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10265                if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10266                        li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10267        }
10268        else
10269        {
10270                if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10271                {
10272                        if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10273                                li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10274                        plci->li_bchannel_id = bchannel_id & 0x03;
10275                        if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10276                        {
10277                                splci = a->AdvSignalPLCI;
10278                                if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10279                                {
10280                                        if ((splci->li_bchannel_id != 0)
10281                                            && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10282                                        {
10283                                                li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10284                                        }
10285                                        splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10286                                        li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10287                                        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10288                                                        (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10289                                                        (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10290                                }
10291                        }
10292                        if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10293                                li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10294                }
10295        }
10296        if ((old_id == 0) && (plci->li_bchannel_id != 0)
10297            && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10298        {
10299                mixer_clear_config(plci);
10300        }
10301        dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10302                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10303                        (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10304}
10305
10306
10307static void mixer_set_bchannel_id(PLCI *plci, byte *chi)
10308{
10309        DIVA_CAPI_ADAPTER *a;
10310        PLCI *splci;
10311        byte ch, old_id;
10312
10313        a = plci->adapter;
10314        old_id = plci->li_bchannel_id;
10315        ch = chi_to_channel(chi, NULL);
10316        if (!(ch & 0x80))
10317        {
10318                if (a->li_pri)
10319                {
10320                        if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10321                                li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10322                        plci->li_bchannel_id = (ch & 0x1f) + 1;
10323                        if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10324                                li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10325                }
10326                else
10327                {
10328                        if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10329                        {
10330                                if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10331                                        li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10332                                plci->li_bchannel_id = ch & 0x1f;
10333                                if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10334                                {
10335                                        splci = a->AdvSignalPLCI;
10336                                        if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10337                                        {
10338                                                if ((splci->li_bchannel_id != 0)
10339                                                    && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10340                                                {
10341                                                        li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10342                                                }
10343                                                splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10344                                                li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10345                                                dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10346                                                                (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10347                                                                (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10348                                        }
10349                                }
10350                                if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10351                                        li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10352                        }
10353                }
10354        }
10355        if ((old_id == 0) && (plci->li_bchannel_id != 0)
10356            && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10357        {
10358                mixer_clear_config(plci);
10359        }
10360        dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10361                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10362                        (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10363}
10364
10365
10366#define MIXER_MAX_DUMP_CHANNELS 34
10367
10368static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER *a)
10369{
10370        word n, i, j;
10371        char *p;
10372        char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10373
10374        dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10375                        (dword)(UnMapController(a->Id)), (char *)(FILE_), __LINE__));
10376
10377        for (i = 0; i < li_total_channels; i++)
10378        {
10379                li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10380                if (li_config_table[i].chflags != 0)
10381                        li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10382                else
10383                {
10384                        for (j = 0; j < li_total_channels; j++)
10385                        {
10386                                if (((li_config_table[i].flag_table[j]) != 0)
10387                                    || ((li_config_table[j].flag_table[i]) != 0))
10388                                {
10389                                        li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10390                                }
10391                                if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10392                                    || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10393                                {
10394                                        li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10395                                }
10396                        }
10397                }
10398        }
10399        for (i = 0; i < li_total_channels; i++)
10400        {
10401                for (j = 0; j < li_total_channels; j++)
10402                {
10403                        li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10404                        if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10405                                li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10406                }
10407        }
10408        for (n = 0; n < li_total_channels; n++)
10409        {
10410                if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10411                {
10412                        for (i = 0; i < li_total_channels; i++)
10413                        {
10414                                if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10415                                {
10416                                        for (j = 0; j < li_total_channels; j++)
10417                                        {
10418                                                li_config_table[i].coef_table[j] |=
10419                                                        li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10420                                        }
10421                                }
10422                        }
10423                }
10424        }
10425        for (i = 0; i < li_total_channels; i++)
10426        {
10427                if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10428                {
10429                        li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10430                        for (j = 0; j < li_total_channels; j++)
10431                        {
10432                                if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10433                                        li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10434                        }
10435                        if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10436                                li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10437                }
10438        }
10439        for (i = 0; i < li_total_channels; i++)
10440        {
10441                if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10442                {
10443                        for (j = 0; j < li_total_channels; j++)
10444                        {
10445                                if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10446                                        li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10447                                if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10448                                        li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10449                                if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10450                                        li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10451                                if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10452                                        li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10453                        }
10454                        if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10455                        {
10456                                for (j = 0; j < li_total_channels; j++)
10457                                {
10458                                        if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10459                                        {
10460                                                li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10461                                                if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10462                                                        li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10463                                        }
10464                                }
10465                        }
10466                        if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10467                        {
10468                                for (j = 0; j < li_total_channels; j++)
10469                                {
10470                                        if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10471                                                li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10472                                }
10473                        }
10474                        if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10475                        {
10476                                for (j = 0; j < li_total_channels; j++)
10477                                {
10478                                        if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10479                                        {
10480                                                for (n = 0; n < li_total_channels; n++)
10481                                                {
10482                                                        if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10483                                                        {
10484                                                                li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10485                                                                if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10486                                                                {
10487                                                                        li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10488                                                                        if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10489                                                                                li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10490                                                                }
10491                                                                else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10492                                                                        li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10493                                                        }
10494                                                }
10495                                        }
10496                                }
10497                        }
10498                }
10499        }
10500        for (i = 0; i < li_total_channels; i++)
10501        {
10502                if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10503                {
10504                        if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10505                                li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10506                        if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10507                                li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10508                        if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10509                                li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10510                        for (j = 0; j < li_total_channels; j++)
10511                        {
10512                                if ((li_config_table[i].flag_table[j] &
10513                                     (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10514                                    || (li_config_table[j].flag_table[i] &
10515                                        (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10516                                {
10517                                        li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10518                                }
10519                                if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10520                                        li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10521                                if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10522                                        li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10523                        }
10524                        if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10525                        {
10526                                li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10527                                li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10528                        }
10529                }
10530        }
10531        for (i = 0; i < li_total_channels; i++)
10532        {
10533                if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10534                {
10535                        j = 0;
10536                        while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10537                                j++;
10538                        if (j < li_total_channels)
10539                        {
10540                                for (j = 0; j < li_total_channels; j++)
10541                                {
10542                                        li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10543                                        if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10544                                                li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10545                                }
10546                        }
10547                }
10548        }
10549        n = li_total_channels;
10550        if (n > MIXER_MAX_DUMP_CHANNELS)
10551                n = MIXER_MAX_DUMP_CHANNELS;
10552
10553        p = hex_line;
10554        for (j = 0; j < n; j++)
10555        {
10556                if ((j & 0x7) == 0)
10557                        *(p++) = ' ';
10558                p = hex_byte_pack(p, li_config_table[j].curchnl);
10559        }
10560        *p = '\0';
10561        dbug(1, dprintf("[%06lx] CURRENT %s",
10562                        (dword)(UnMapController(a->Id)), (char *)hex_line));
10563        p = hex_line;
10564        for (j = 0; j < n; j++)
10565        {
10566                if ((j & 0x7) == 0)
10567                        *(p++) = ' ';
10568                p = hex_byte_pack(p, li_config_table[j].channel);
10569        }
10570        *p = '\0';
10571        dbug(1, dprintf("[%06lx] CHANNEL %s",
10572                        (dword)(UnMapController(a->Id)), (char *)hex_line));
10573        p = hex_line;
10574        for (j = 0; j < n; j++)
10575        {
10576                if ((j & 0x7) == 0)
10577                        *(p++) = ' ';
10578                p = hex_byte_pack(p, li_config_table[j].chflags);
10579        }
10580        *p = '\0';
10581        dbug(1, dprintf("[%06lx] CHFLAG  %s",
10582                        (dword)(UnMapController(a->Id)), (char *)hex_line));
10583        for (i = 0; i < n; i++)
10584        {
10585                p = hex_line;
10586                for (j = 0; j < n; j++)
10587                {
10588                        if ((j & 0x7) == 0)
10589                                *(p++) = ' ';
10590                        p = hex_byte_pack(p, li_config_table[i].flag_table[j]);
10591                }
10592                *p = '\0';
10593                dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10594                                (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10595        }
10596        for (i = 0; i < n; i++)
10597        {
10598                p = hex_line;
10599                for (j = 0; j < n; j++)
10600                {
10601                        if ((j & 0x7) == 0)
10602                                *(p++) = ' ';
10603                        p = hex_byte_pack(p, li_config_table[i].coef_table[j]);
10604                }
10605                *p = '\0';
10606                dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10607                                (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10608        }
10609}
10610
10611
10612static struct
10613{
10614        byte mask;
10615        byte line_flags;
10616} mixer_write_prog_pri[] =
10617{
10618        { LI_COEF_CH_CH, 0 },
10619        { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10620        { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10621        { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10622};
10623
10624static struct
10625{
10626        byte from_ch;
10627        byte to_ch;
10628        byte mask;
10629        byte xconnect_override;
10630} mixer_write_prog_bri[] =
10631{
10632        { 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10633        { 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10634        { 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10635        { 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10636        { 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10637        { 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10638        { 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10639        { 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10640        { 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10641        { 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10642        { 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10643        { 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10644        { 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10645        { 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10646        { 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10647        { 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10648        { 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10649        { 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10650        { 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10651        { 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10652        { 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10653        { 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10654        { 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10655        { 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10656        { 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10657        { 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10658        { 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10659        { 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10660        { 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10661        { 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10662        { 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10663        { 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10664        { 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10665        { 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10666        { 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10667        { 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10668};
10669
10670static byte mixer_swapped_index_bri[] =
10671{
10672        18,  /* B      to B      */
10673        19,  /* Alt B  to B      */
10674        20,  /* PC     to B      */
10675        21,  /* Alt PC to B      */
10676        22,  /* IC     to B      */
10677        23,  /* Alt IC to B      */
10678        24,  /* B      to PC     */
10679        25,  /* Alt B  to PC     */
10680        26,  /* PC     to PC     */
10681        27,  /* Alt PC to PC     */
10682        28,  /* IC     to PC     */
10683        29,  /* Alt IC to PC     */
10684        30,  /* B      to IC     */
10685        31,  /* Alt B  to IC     */
10686        32,  /* PC     to IC     */
10687        33,  /* Alt PC to IC     */
10688        34,  /* IC     to IC     */
10689        35,  /* Alt IC to IC     */
10690        0,   /* Alt B  to Alt B  */
10691        1,   /* B      to Alt B  */
10692        2,   /* Alt PC to Alt B  */
10693        3,   /* PC     to Alt B  */
10694        4,   /* Alt IC to Alt B  */
10695        5,   /* IC     to Alt B  */
10696        6,   /* Alt B  to Alt PC */
10697        7,   /* B      to Alt PC */
10698        8,   /* Alt PC to Alt PC */
10699        9,   /* PC     to Alt PC */
10700        10,  /* Alt IC to Alt PC */
10701        11,  /* IC     to Alt PC */
10702        12,  /* Alt B  to Alt IC */
10703        13,  /* B      to Alt IC */
10704        14,  /* Alt PC to Alt IC */
10705        15,  /* PC     to Alt IC */
10706        16,  /* Alt IC to Alt IC */
10707        17   /* IC     to Alt IC */
10708};
10709
10710static struct
10711{
10712        byte mask;
10713        byte from_pc;
10714        byte to_pc;
10715} xconnect_write_prog[] =
10716{
10717        { LI_COEF_CH_CH, false, false },
10718        { LI_COEF_CH_PC, false, true },
10719        { LI_COEF_PC_CH, true, false },
10720        { LI_COEF_PC_PC, true, true }
10721};
10722
10723
10724static void xconnect_query_addresses(PLCI *plci)
10725{
10726        DIVA_CAPI_ADAPTER *a;
10727        word w, ch;
10728        byte *p;
10729
10730        dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10731                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10732                        (char *)(FILE_), __LINE__));
10733
10734        a = plci->adapter;
10735        if (a->li_pri && ((plci->li_bchannel_id == 0)
10736                          || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10737        {
10738                dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10739                                (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10740                                (char *)(FILE_), __LINE__));
10741                return;
10742        }
10743        p = plci->internal_req_buffer;
10744        ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10745        *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10746        w = ch;
10747        *(p++) = (byte) w;
10748        *(p++) = (byte)(w >> 8);
10749        w = ch | XCONNECT_CHANNEL_PORT_PC;
10750        *(p++) = (byte) w;
10751        *(p++) = (byte)(w >> 8);
10752        plci->NData[0].P = plci->internal_req_buffer;
10753        plci->NData[0].PLength = p - plci->internal_req_buffer;
10754        plci->NL.X = plci->NData;
10755        plci->NL.ReqCh = 0;
10756        plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10757        plci->adapter->request(&plci->NL);
10758}
10759
10760
10761static void xconnect_write_coefs(PLCI *plci, word internal_command)
10762{
10763
10764        dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10765                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10766                        (char *)(FILE_), __LINE__, internal_command));
10767
10768        plci->li_write_command = internal_command;
10769        plci->li_write_channel = 0;
10770}
10771
10772
10773static byte xconnect_write_coefs_process(dword Id, PLCI *plci, byte Rc)
10774{
10775        DIVA_CAPI_ADAPTER *a;
10776        word w, n, i, j, r, s, to_ch;
10777        dword d;
10778        byte *p;
10779        struct xconnect_transfer_address_s   *transfer_address;
10780        byte ch_map[MIXER_CHANNELS_BRI];
10781
10782        dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10783                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10784
10785        a = plci->adapter;
10786        if ((plci->li_bchannel_id == 0)
10787            || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10788        {
10789                dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10790                                UnMapId(Id), (char *)(FILE_), __LINE__));
10791                return (true);
10792        }
10793        i = a->li_base + (plci->li_bchannel_id - 1);
10794        j = plci->li_write_channel;
10795        p = plci->internal_req_buffer;
10796        if (j != 0)
10797        {
10798                if ((Rc != OK) && (Rc != OK_FC))
10799                {
10800                        dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10801                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10802                        return (false);
10803                }
10804        }
10805        if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10806        {
10807                r = 0;
10808                s = 0;
10809                if (j < li_total_channels)
10810                {
10811                        if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10812                        {
10813                                s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10814                                     (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10815                                        ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10816                                         (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10817                        }
10818                        r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10819                        while ((j < li_total_channels)
10820                               && ((r == 0)
10821                                   || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10822                                   || (!li_config_table[j].adapter->li_pri
10823                                       && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10824                                   || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10825                                        || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10826                                       && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10827                                           || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10828                                   || ((li_config_table[j].adapter->li_base != a->li_base)
10829                                       && !(r & s &
10830                                            ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10831                                             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10832                                            ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10833                                             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10834                        {
10835                                j++;
10836                                if (j < li_total_channels)
10837                                        r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10838                        }
10839                }
10840                if (j < li_total_channels)
10841                {
10842                        plci->internal_command = plci->li_write_command;
10843                        if (plci_nl_busy(plci))
10844                                return (true);
10845                        to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10846                        *(p++) = UDATA_REQUEST_XCONNECT_TO;
10847                        do
10848                        {
10849                                if (li_config_table[j].adapter->li_base != a->li_base)
10850                                {
10851                                        r &= s &
10852                                                ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10853                                                 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10854                                                ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10855                                                 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10856                                }
10857                                n = 0;
10858                                do
10859                                {
10860                                        if (r & xconnect_write_prog[n].mask)
10861                                        {
10862                                                if (xconnect_write_prog[n].from_pc)
10863                                                        transfer_address = &(li_config_table[j].send_pc);
10864                                                else
10865                                                        transfer_address = &(li_config_table[j].send_b);
10866                                                d = transfer_address->card_address.low;
10867                                                *(p++) = (byte) d;
10868                                                *(p++) = (byte)(d >> 8);
10869                                                *(p++) = (byte)(d >> 16);
10870                                                *(p++) = (byte)(d >> 24);
10871                                                d = transfer_address->card_address.high;
10872                                                *(p++) = (byte) d;
10873                                                *(p++) = (byte)(d >> 8);
10874                                                *(p++) = (byte)(d >> 16);
10875                                                *(p++) = (byte)(d >> 24);
10876                                                d = transfer_address->offset;
10877                                                *(p++) = (byte) d;
10878                                                *(p++) = (byte)(d >> 8);
10879                                                *(p++) = (byte)(d >> 16);
10880                                                *(p++) = (byte)(d >> 24);
10881                                                w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
10882                                                *(p++) = (byte) w;
10883                                                *(p++) = (byte)(w >> 8);
10884                                                w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
10885                                                        (li_config_table[i].adapter->u_law ?
10886                                                         (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
10887                                                         (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
10888                                                *(p++) = (byte) w;
10889                                                *(p++) = (byte) 0;
10890                                                li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
10891                                        }
10892                                        n++;
10893                                } while ((n < ARRAY_SIZE(xconnect_write_prog))
10894                                         && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
10895                                if (n == ARRAY_SIZE(xconnect_write_prog))
10896                                {
10897                                        do
10898                                        {
10899                                                j++;
10900                                                if (j < li_total_channels)
10901                                                        r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10902                                        } while ((j < li_total_channels)
10903                                                 && ((r == 0)
10904                                                     || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10905                                                     || (!li_config_table[j].adapter->li_pri
10906                                                         && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10907                                                     || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10908                                                          || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10909                                                         && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10910                                                             || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10911                                                     || ((li_config_table[j].adapter->li_base != a->li_base)
10912                                                         && !(r & s &
10913                                                              ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10914                                                               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10915                                                              ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10916                                                               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
10917                                }
10918                        } while ((j < li_total_channels)
10919                                 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
10920                }
10921                else if (j == li_total_channels)
10922                {
10923                        plci->internal_command = plci->li_write_command;
10924                        if (plci_nl_busy(plci))
10925                                return (true);
10926                        if (a->li_pri)
10927                        {
10928                                *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
10929                                w = 0;
10930                                if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
10931                                        w |= MIXER_FEATURE_ENABLE_TX_DATA;
10932                                if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
10933                                        w |= MIXER_FEATURE_ENABLE_RX_DATA;
10934                                *(p++) = (byte) w;
10935                                *(p++) = (byte)(w >> 8);
10936                        }
10937                        else
10938                        {
10939                                *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
10940                                w = 0;
10941                                if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
10942                                    && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
10943                                {
10944                                        w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
10945                                }
10946                                if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
10947                                        w |= MIXER_FEATURE_ENABLE_TX_DATA;
10948                                if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
10949                                        w |= MIXER_FEATURE_ENABLE_RX_DATA;
10950                                *(p++) = (byte) w;
10951                                *(p++) = (byte)(w >> 8);
10952                                for (j = 0; j < sizeof(ch_map); j += 2)
10953                                {
10954                                        if (plci->li_bchannel_id == 2)
10955                                        {
10956                                                ch_map[j] = (byte)(j + 1);
10957                                                ch_map[j + 1] = (byte) j;
10958                                        }
10959                                        else
10960                                        {
10961                                                ch_map[j] = (byte) j;
10962                                                ch_map[j + 1] = (byte)(j + 1);
10963                                        }
10964                                }
10965                                for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
10966                                {
10967                                        i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
10968                                        j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
10969                                        if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
10970                                        {
10971                                                *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
10972                                                        mixer_write_prog_bri[n].xconnect_override :
10973                                                        ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
10974                                                if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
10975                                                {
10976                                                        w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10977                                                        li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
10978                                                }
10979                                        }
10980                                        else
10981                                        {
10982                                                *p = 0x00;
10983                                                if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10984                                                {
10985                                                        w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
10986                                                        if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
10987                                                                *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
10988                                                }
10989                                        }
10990                                        p++;
10991                                }
10992                        }
10993                        j = li_total_channels + 1;
10994                }
10995        }
10996        else
10997        {
10998                if (j <= li_total_channels)
10999                {
11000                        plci->internal_command = plci->li_write_command;
11001                        if (plci_nl_busy(plci))
11002                                return (true);
11003                        if (j < a->li_base)
11004                                j = a->li_base;
11005                        if (a->li_pri)
11006                        {
11007                                *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11008                                w = 0;
11009                                if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11010                                        w |= MIXER_FEATURE_ENABLE_TX_DATA;
11011                                if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11012                                        w |= MIXER_FEATURE_ENABLE_RX_DATA;
11013                                *(p++) = (byte) w;
11014                                *(p++) = (byte)(w >> 8);
11015                                for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11016                                {
11017                                        *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11018                                        for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11019                                        {
11020                                                w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11021                                                if (w & mixer_write_prog_pri[n].mask)
11022                                                {
11023                                                        *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11024                                                        li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11025                                                }
11026                                                else
11027                                                        *(p++) = 0x00;
11028                                        }
11029                                        *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11030                                        for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11031                                        {
11032                                                w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11033                                                if (w & mixer_write_prog_pri[n].mask)
11034                                                {
11035                                                        *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11036                                                        li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11037                                                }
11038                                                else
11039                                                        *(p++) = 0x00;
11040                                        }
11041                                }
11042                        }
11043                        else
11044                        {
11045                                *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11046                                w = 0;
11047                                if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11048                                    && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11049                                {
11050                                        w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11051                                }
11052                                if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11053                                        w |= MIXER_FEATURE_ENABLE_TX_DATA;
11054                                if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11055                                        w |= MIXER_FEATURE_ENABLE_RX_DATA;
11056                                *(p++) = (byte) w;
11057                                *(p++) = (byte)(w >> 8);
11058                                for (j = 0; j < sizeof(ch_map); j += 2)
11059                                {
11060                                        if (plci->li_bchannel_id == 2)
11061                                        {
11062                                                ch_map[j] = (byte)(j + 1);
11063                                                ch_map[j + 1] = (byte) j;
11064                                        }
11065                                        else
11066                                        {
11067                                                ch_map[j] = (byte) j;
11068                                                ch_map[j + 1] = (byte)(j + 1);
11069                                        }
11070                                }
11071                                for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11072                                {
11073                                        i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11074                                        j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11075                                        if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11076                                        {
11077                                                *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11078                                                w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11079                                                li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11080                                        }
11081                                        else
11082                                        {
11083                                                *p = 0x00;
11084                                                if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11085                                                {
11086                                                        w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11087                                                        if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11088                                                                *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11089                                                }
11090                                        }
11091                                        p++;
11092                                }
11093                        }
11094                        j = li_total_channels + 1;
11095                }
11096        }
11097        plci->li_write_channel = j;
11098        if (p != plci->internal_req_buffer)
11099        {
11100                plci->NData[0].P = plci->internal_req_buffer;
11101                plci->NData[0].PLength = p - plci->internal_req_buffer;
11102                plci->NL.X = plci->NData;
11103                plci->NL.ReqCh = 0;
11104                plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11105                plci->adapter->request(&plci->NL);
11106        }
11107        return (true);
11108}
11109
11110
11111static void mixer_notify_update(PLCI *plci, byte others)
11112{
11113        DIVA_CAPI_ADAPTER *a;
11114        word i, w;
11115        PLCI *notify_plci;
11116        byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11117
11118        dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11119                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11120                        (char *)(FILE_), __LINE__, others));
11121
11122        a = plci->adapter;
11123        if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11124        {
11125                if (others)
11126                        plci->li_notify_update = true;
11127                i = 0;
11128                do
11129                {
11130                        notify_plci = NULL;
11131                        if (others)
11132                        {
11133                                while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11134                                        i++;
11135                                if (i < li_total_channels)
11136                                        notify_plci = li_config_table[i++].plci;
11137                        }
11138                        else
11139                        {
11140                                if ((plci->li_bchannel_id != 0)
11141                                    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11142                                {
11143                                        notify_plci = plci;
11144                                }
11145                        }
11146                        if ((notify_plci != NULL)
11147                            && !notify_plci->li_notify_update
11148                            && (notify_plci->appl != NULL)
11149                            && (notify_plci->State)
11150                            && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11151                        {
11152                                notify_plci->li_notify_update = true;
11153                                ((CAPI_MSG *) msg)->header.length = 18;
11154                                ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11155                                ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11156                                ((CAPI_MSG *) msg)->header.number = 0;
11157                                ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11158                                ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11159                                ((CAPI_MSG *) msg)->header.ncci = 0;
11160                                ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11161                                ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11162                                ((CAPI_MSG *) msg)->info.facility_req.structs[1] = LI_REQ_SILENT_UPDATE & 0xff;
11163                                ((CAPI_MSG *) msg)->info.facility_req.structs[2] = LI_REQ_SILENT_UPDATE >> 8;
11164                                ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11165                                w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11166                                if (w != _QUEUE_FULL)
11167                                {
11168                                        if (w != 0)
11169                                        {
11170                                                dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11171                                                                (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11172                                                                (char *)(FILE_), __LINE__,
11173                                                                (dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11174                                        }
11175                                        notify_plci->li_notify_update = false;
11176                                }
11177                        }
11178                } while (others && (notify_plci != NULL));
11179                if (others)
11180                        plci->li_notify_update = false;
11181        }
11182}
11183
11184
11185static void mixer_clear_config(PLCI *plci)
11186{
11187        DIVA_CAPI_ADAPTER *a;
11188        word i, j;
11189
11190        dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11191                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11192                        (char *)(FILE_), __LINE__));
11193
11194        plci->li_notify_update = false;
11195        plci->li_plci_b_write_pos = 0;
11196        plci->li_plci_b_read_pos = 0;
11197        plci->li_plci_b_req_pos = 0;
11198        a = plci->adapter;
11199        if ((plci->li_bchannel_id != 0)
11200            && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11201        {
11202                i = a->li_base + (plci->li_bchannel_id - 1);
11203                li_config_table[i].curchnl = 0;
11204                li_config_table[i].channel = 0;
11205                li_config_table[i].chflags = 0;
11206                for (j = 0; j < li_total_channels; j++)
11207                {
11208                        li_config_table[j].flag_table[i] = 0;
11209                        li_config_table[i].flag_table[j] = 0;
11210                        li_config_table[i].coef_table[j] = 0;
11211                        li_config_table[j].coef_table[i] = 0;
11212                }
11213                if (!a->li_pri)
11214                {
11215                        li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11216                        if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11217                        {
11218                                i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11219                                li_config_table[i].curchnl = 0;
11220                                li_config_table[i].channel = 0;
11221                                li_config_table[i].chflags = 0;
11222                                for (j = 0; j < li_total_channels; j++)
11223                                {
11224                                        li_config_table[i].flag_table[j] = 0;
11225                                        li_config_table[j].flag_table[i] = 0;
11226                                        li_config_table[i].coef_table[j] = 0;
11227                                        li_config_table[j].coef_table[i] = 0;
11228                                }
11229                                if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11230                                {
11231                                        i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11232                                        li_config_table[i].curchnl = 0;
11233                                        li_config_table[i].channel = 0;
11234                                        li_config_table[i].chflags = 0;
11235                                        for (j = 0; j < li_total_channels; j++)
11236                                        {
11237                                                li_config_table[i].flag_table[j] = 0;
11238                                                li_config_table[j].flag_table[i] = 0;
11239                                                li_config_table[i].coef_table[j] = 0;
11240                                                li_config_table[j].coef_table[i] = 0;
11241                                        }
11242                                }
11243                        }
11244                }
11245        }
11246}
11247
11248
11249static void mixer_prepare_switch(dword Id, PLCI *plci)
11250{
11251
11252        dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11253                        UnMapId(Id), (char *)(FILE_), __LINE__));
11254
11255        do
11256        {
11257                mixer_indication_coefs_set(Id, plci);
11258        } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11259}
11260
11261
11262static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11263{
11264        DIVA_CAPI_ADAPTER *a;
11265        word i, j;
11266
11267        dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11268                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11269
11270        a = plci->adapter;
11271        if ((plci->li_bchannel_id != 0)
11272            && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11273        {
11274                i = a->li_base + (plci->li_bchannel_id - 1);
11275                for (j = 0; j < li_total_channels; j++)
11276                {
11277                        li_config_table[i].coef_table[j] &= 0xf;
11278                        li_config_table[j].coef_table[i] &= 0xf;
11279                }
11280                if (!a->li_pri)
11281                        li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11282        }
11283        return (GOOD);
11284}
11285
11286
11287static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11288{
11289        DIVA_CAPI_ADAPTER *a;
11290        word Info;
11291
11292        dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11293                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11294
11295        Info = GOOD;
11296        a = plci->adapter;
11297        if ((plci->B1_facilities & B1_FACILITY_MIXER)
11298            && (plci->li_bchannel_id != 0)
11299            && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11300        {
11301                switch (plci->adjust_b_state)
11302                {
11303                case ADJUST_B_RESTORE_MIXER_1:
11304                        if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11305                        {
11306                                plci->internal_command = plci->adjust_b_command;
11307                                if (plci_nl_busy(plci))
11308                                {
11309                                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11310                                        break;
11311                                }
11312                                xconnect_query_addresses(plci);
11313                                plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11314                                break;
11315                        }
11316                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11317                        Rc = OK;
11318                case ADJUST_B_RESTORE_MIXER_2:
11319                case ADJUST_B_RESTORE_MIXER_3:
11320                case ADJUST_B_RESTORE_MIXER_4:
11321                        if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11322                        {
11323                                dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11324                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11325                                Info = _WRONG_STATE;
11326                                break;
11327                        }
11328                        if (Rc == OK)
11329                        {
11330                                if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11331                                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11332                                else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11333                                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11334                        }
11335                        else if (Rc == 0)
11336                        {
11337                                if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11338                                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11339                                else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11340                                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11341                        }
11342                        if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11343                        {
11344                                plci->internal_command = plci->adjust_b_command;
11345                                break;
11346                        }
11347                case ADJUST_B_RESTORE_MIXER_5:
11348                        xconnect_write_coefs(plci, plci->adjust_b_command);
11349                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11350                        Rc = OK;
11351                case ADJUST_B_RESTORE_MIXER_6:
11352                        if (!xconnect_write_coefs_process(Id, plci, Rc))
11353                        {
11354                                dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11355                                                UnMapId(Id), (char *)(FILE_), __LINE__));
11356                                Info = _FACILITY_NOT_SUPPORTED;
11357                                break;
11358                        }
11359                        if (plci->internal_command)
11360                                break;
11361                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11362                case ADJUST_B_RESTORE_MIXER_7:
11363                        break;
11364                }
11365        }
11366        return (Info);
11367}
11368
11369
11370static void mixer_command(dword Id, PLCI *plci, byte Rc)
11371{
11372        DIVA_CAPI_ADAPTER *a;
11373        word i, internal_command;
11374
11375        dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11376                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11377                        plci->li_cmd));
11378
11379        a = plci->adapter;
11380        internal_command = plci->internal_command;
11381        plci->internal_command = 0;
11382        switch (plci->li_cmd)
11383        {
11384        case LI_REQ_CONNECT:
11385        case LI_REQ_DISCONNECT:
11386        case LI_REQ_SILENT_UPDATE:
11387                switch (internal_command)
11388                {
11389                default:
11390                        if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11391                        {
11392                                adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11393                                                                          B1_FACILITY_MIXER), MIXER_COMMAND_1);
11394                        }
11395                case MIXER_COMMAND_1:
11396                        if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11397                        {
11398                                if (adjust_b_process(Id, plci, Rc) != GOOD)
11399                                {
11400                                        dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11401                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
11402                                        break;
11403                                }
11404                                if (plci->internal_command)
11405                                        return;
11406                        }
11407                        plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11408                        if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11409                            || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11410                                && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11411                                                                                      ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11412                        {
11413                                xconnect_write_coefs(plci, MIXER_COMMAND_2);
11414                        }
11415                        else
11416                        {
11417                                do
11418                                {
11419                                        mixer_indication_coefs_set(Id, plci);
11420                                } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11421                        }
11422                case MIXER_COMMAND_2:
11423                        if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11424                            || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11425                                && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11426                                                                                      ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11427                        {
11428                                if (!xconnect_write_coefs_process(Id, plci, Rc))
11429                                {
11430                                        dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11431                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
11432                                        if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11433                                        {
11434                                                do
11435                                                {
11436                                                        plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11437                                                                LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11438                                                        i = (plci->li_plci_b_write_pos == 0) ?
11439                                                                LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11440                                                } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11441                                                         && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11442                                        }
11443                                        break;
11444                                }
11445                                if (plci->internal_command)
11446                                        return;
11447                        }
11448                        if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11449                        {
11450                                adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11451                                                                          ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11452                        }
11453                case MIXER_COMMAND_3:
11454                        if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11455                        {
11456                                if (adjust_b_process(Id, plci, Rc) != GOOD)
11457                                {
11458                                        dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11459                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
11460                                        break;
11461                                }
11462                                if (plci->internal_command)
11463                                        return;
11464                        }
11465                        break;
11466                }
11467                break;
11468        }
11469        if ((plci->li_bchannel_id == 0)
11470            || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11471        {
11472                dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11473                                UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11474        }
11475        else
11476        {
11477                i = a->li_base + (plci->li_bchannel_id - 1);
11478                li_config_table[i].curchnl = plci->li_channel_bits;
11479                if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11480                {
11481                        i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11482                        li_config_table[i].curchnl = plci->li_channel_bits;
11483                        if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11484                        {
11485                                i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11486                                li_config_table[i].curchnl = plci->li_channel_bits;
11487                        }
11488                }
11489        }
11490}
11491
11492
11493static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11494                              dword plci_b_id, byte connect, dword li_flags)
11495{
11496        word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11497        PLCI *plci_b;
11498        DIVA_CAPI_ADAPTER *a_b;
11499
11500        a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11501        plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11502        ch_a = a->li_base + (plci->li_bchannel_id - 1);
11503        if (!a->li_pri && (plci->tel == ADV_VOICE)
11504            && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11505        {
11506                ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11507                ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11508                        a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11509        }
11510        else
11511        {
11512                ch_a_v = ch_a;
11513                ch_a_s = ch_a;
11514        }
11515        ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11516        if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11517            && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11518        {
11519                ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11520                ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11521                        a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11522        }
11523        else
11524        {
11525                ch_b_v = ch_b;
11526                ch_b_s = ch_b;
11527        }
11528        if (connect)
11529        {
11530                li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11531                li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11532                li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11533                li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11534        }
11535        li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11536        li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11537        li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11538        li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11539        if (ch_a_v == ch_b_v)
11540        {
11541                li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11542                li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11543        }
11544        else
11545        {
11546                if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11547                {
11548                        for (i = 0; i < li_total_channels; i++)
11549                        {
11550                                if (i != ch_a_v)
11551                                        li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11552                        }
11553                }
11554                if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11555                {
11556                        for (i = 0; i < li_total_channels; i++)
11557                        {
11558                                if (i != ch_a_s)
11559                                        li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11560                        }
11561                }
11562                if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11563                {
11564                        for (i = 0; i < li_total_channels; i++)
11565                        {
11566                                if (i != ch_a_v)
11567                                        li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11568                        }
11569                }
11570                if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11571                {
11572                        for (i = 0; i < li_total_channels; i++)
11573                        {
11574                                if (i != ch_a_s)
11575                                        li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11576                        }
11577                }
11578        }
11579        if (li_flags & LI_FLAG_CONFERENCE_A_B)
11580        {
11581                li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11582                li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11583                li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11584                li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11585        }
11586        if (li_flags & LI_FLAG_CONFERENCE_B_A)
11587        {
11588                li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11589                li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11590                li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11591                li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11592        }
11593        if (li_flags & LI_FLAG_MONITOR_A)
11594        {
11595                li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11596                li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11597        }
11598        if (li_flags & LI_FLAG_MONITOR_B)
11599        {
11600                li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11601                li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11602        }
11603        if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11604        {
11605                li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11606                li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11607        }
11608        if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11609        {
11610                li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11611                li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11612        }
11613        if (li_flags & LI_FLAG_MIX_A)
11614        {
11615                li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11616                li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11617        }
11618        if (li_flags & LI_FLAG_MIX_B)
11619        {
11620                li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11621                li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11622        }
11623        if (ch_a_v != ch_a_s)
11624        {
11625                li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11626                li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11627        }
11628        if (ch_b_v != ch_b_s)
11629        {
11630                li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11631                li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11632        }
11633}
11634
11635
11636static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11637                               dword plci_b_id, byte connect, dword li_flags)
11638{
11639        word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11640        PLCI *plci_b;
11641        DIVA_CAPI_ADAPTER *a_b;
11642
11643        a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11644        plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11645        ch_a = a->li_base + (plci->li_bchannel_id - 1);
11646        if (!a->li_pri && (plci->tel == ADV_VOICE)
11647            && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11648        {
11649                ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11650                ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11651                        a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11652        }
11653        else
11654        {
11655                ch_a_v = ch_a;
11656                ch_a_s = ch_a;
11657        }
11658        ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11659        if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11660            && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11661        {
11662                ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11663                ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11664                        a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11665        }
11666        else
11667        {
11668                ch_b_v = ch_b;
11669                ch_b_s = ch_b;
11670        }
11671        if (connect)
11672        {
11673                li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11674                li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11675                li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11676                li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11677                li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11678                li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11679        }
11680        li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11681        li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11682        li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11683        li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11684        li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11685        li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11686        li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11687        li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11688        if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11689        {
11690                li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11691                li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11692                li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11693                li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11694        }
11695        if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11696        {
11697                li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11698                li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11699                li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11700                li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11701        }
11702        if (li_flags & LI2_FLAG_MONITOR_B)
11703        {
11704                li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11705                li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11706        }
11707        if (li_flags & LI2_FLAG_MIX_B)
11708        {
11709                li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11710                li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11711        }
11712        if (li_flags & LI2_FLAG_MONITOR_X)
11713                li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11714        if (li_flags & LI2_FLAG_MIX_X)
11715                li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11716        if (li_flags & LI2_FLAG_LOOP_B)
11717        {
11718                li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11719                li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11720                li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11721                li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11722        }
11723        if (li_flags & LI2_FLAG_LOOP_PC)
11724                li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11725        if (li_flags & LI2_FLAG_LOOP_X)
11726                li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11727        if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11728                li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11729        if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11730                li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11731        if (ch_a_v != ch_a_s)
11732        {
11733                li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11734                li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11735        }
11736        if (ch_b_v != ch_b_s)
11737        {
11738                li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11739                li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11740        }
11741}
11742
11743
11744static word li_check_main_plci(dword Id, PLCI *plci)
11745{
11746        if (plci == NULL)
11747        {
11748                dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11749                                UnMapId(Id), (char *)(FILE_), __LINE__));
11750                return (_WRONG_IDENTIFIER);
11751        }
11752        if (!plci->State
11753            || !plci->NL.Id || plci->nl_remove_id
11754            || (plci->li_bchannel_id == 0))
11755        {
11756                dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11757                                UnMapId(Id), (char *)(FILE_), __LINE__));
11758                return (_WRONG_STATE);
11759        }
11760        li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11761        return (GOOD);
11762}
11763
11764
11765static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11766                             dword plci_b_id, word plci_b_write_pos, byte *p_result)
11767{
11768        byte ctlr_b;
11769        PLCI *plci_b;
11770
11771        if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11772             LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11773        {
11774                dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11775                                UnMapId(Id), (char *)(FILE_), __LINE__));
11776                PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11777                return (NULL);
11778        }
11779        ctlr_b = 0;
11780        if ((plci_b_id & 0x7f) != 0)
11781        {
11782                ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11783                if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11784                        ctlr_b = 0;
11785        }
11786        if ((ctlr_b == 0)
11787            || (((plci_b_id >> 8) & 0xff) == 0)
11788            || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11789        {
11790                dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11791                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11792                PUT_WORD(p_result, _WRONG_IDENTIFIER);
11793                return (NULL);
11794        }
11795        plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11796        if (!plci_b->State
11797            || !plci_b->NL.Id || plci_b->nl_remove_id
11798            || (plci_b->li_bchannel_id == 0))
11799        {
11800                dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11801                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11802                PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11803                return (NULL);
11804        }
11805        li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11806        if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11807            ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11808            && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11809                || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11810        {
11811                dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11812                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11813                PUT_WORD(p_result, _WRONG_IDENTIFIER);
11814                return (NULL);
11815        }
11816        if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11817                                                          (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11818        {
11819                dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11820                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11821                PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11822                return (NULL);
11823        }
11824        return (plci_b);
11825}
11826
11827
11828static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11829                              dword plci_b_id, word plci_b_write_pos, byte *p_result)
11830{
11831        byte ctlr_b;
11832        PLCI *plci_b;
11833
11834        if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11835             LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11836        {
11837                dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11838                                UnMapId(Id), (char *)(FILE_), __LINE__));
11839                PUT_WORD(p_result, _WRONG_STATE);
11840                return (NULL);
11841        }
11842        ctlr_b = 0;
11843        if ((plci_b_id & 0x7f) != 0)
11844        {
11845                ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11846                if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11847                        ctlr_b = 0;
11848        }
11849        if ((ctlr_b == 0)
11850            || (((plci_b_id >> 8) & 0xff) == 0)
11851            || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11852        {
11853                dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11854                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11855                PUT_WORD(p_result, _WRONG_IDENTIFIER);
11856                return (NULL);
11857        }
11858        plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11859        if (!plci_b->State
11860            || !plci_b->NL.Id || plci_b->nl_remove_id
11861            || (plci_b->li_bchannel_id == 0)
11862            || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11863        {
11864                dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11865                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11866                PUT_WORD(p_result, _WRONG_STATE);
11867                return (NULL);
11868        }
11869        if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11870            ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11871            && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11872                || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11873        {
11874                dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11875                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11876                PUT_WORD(p_result, _WRONG_IDENTIFIER);
11877                return (NULL);
11878        }
11879        if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11880                                                          (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11881        {
11882                dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11883                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11884                PUT_WORD(p_result, _WRONG_STATE);
11885                return (NULL);
11886        }
11887        return (plci_b);
11888}
11889
11890
11891static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
11892{
11893        word Info;
11894        word i;
11895        dword d, li_flags, plci_b_id;
11896        PLCI *plci_b;
11897        API_PARSE li_parms[3];
11898        API_PARSE li_req_parms[3];
11899        API_PARSE li_participant_struct[2];
11900        API_PARSE li_participant_parms[3];
11901        word participant_parms_pos;
11902        byte result_buffer[32];
11903        byte *result;
11904        word result_pos;
11905        word plci_b_write_pos;
11906
11907        dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
11908                        UnMapId(Id), (char *)(FILE_), __LINE__));
11909
11910        Info = GOOD;
11911        result = result_buffer;
11912        result_buffer[0] = 0;
11913        if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
11914        {
11915                dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
11916                                UnMapId(Id), (char *)(FILE_), __LINE__));
11917                Info = _FACILITY_NOT_SUPPORTED;
11918        }
11919        else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
11920        {
11921                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
11922                                UnMapId(Id), (char *)(FILE_), __LINE__));
11923                Info = _WRONG_MESSAGE_FORMAT;
11924        }
11925        else
11926        {
11927                result_buffer[0] = 3;
11928                PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
11929                result_buffer[3] = 0;
11930                switch (GET_WORD(li_parms[0].info))
11931                {
11932                case LI_GET_SUPPORTED_SERVICES:
11933                        if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
11934                        {
11935                                result_buffer[0] = 17;
11936                                result_buffer[3] = 14;
11937                                PUT_WORD(&result_buffer[4], GOOD);
11938                                d = 0;
11939                                if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
11940                                        d |= LI_CONFERENCING_SUPPORTED;
11941                                if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
11942                                        d |= LI_MONITORING_SUPPORTED;
11943                                if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
11944                                        d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
11945                                if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11946                                        d |= LI_CROSS_CONTROLLER_SUPPORTED;
11947                                PUT_DWORD(&result_buffer[6], d);
11948                                if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11949                                {
11950                                        d = 0;
11951                                        for (i = 0; i < li_total_channels; i++)
11952                                        {
11953                                                if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11954                                                    && (li_config_table[i].adapter->li_pri
11955                                                        || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
11956                                                {
11957                                                        d++;
11958                                                }
11959                                        }
11960                                }
11961                                else
11962                                {
11963                                        d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
11964                                }
11965                                PUT_DWORD(&result_buffer[10], d / 2);
11966                                PUT_DWORD(&result_buffer[14], d);
11967                        }
11968                        else
11969                        {
11970                                result_buffer[0] = 25;
11971                                result_buffer[3] = 22;
11972                                PUT_WORD(&result_buffer[4], GOOD);
11973                                d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
11974                                if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
11975                                        d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
11976                                if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
11977                                        d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
11978                                if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
11979                                        d |= LI2_PC_LOOPING_SUPPORTED;
11980                                if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11981                                        d |= LI2_CROSS_CONTROLLER_SUPPORTED;
11982                                PUT_DWORD(&result_buffer[6], d);
11983                                d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
11984                                PUT_DWORD(&result_buffer[10], d / 2);
11985                                PUT_DWORD(&result_buffer[14], d - 1);
11986                                if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11987                                {
11988                                        d = 0;
11989                                        for (i = 0; i < li_total_channels; i++)
11990                                        {
11991                                                if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11992                                                    && (li_config_table[i].adapter->li_pri
11993                                                        || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
11994                                                {
11995                                                        d++;
11996                                                }
11997                                        }
11998                                }
11999                                PUT_DWORD(&result_buffer[18], d / 2);
12000                                PUT_DWORD(&result_buffer[22], d - 1);
12001                        }
12002                        break;
12003
12004                case LI_REQ_CONNECT:
12005                        if (li_parms[1].length == 8)
12006                        {
12007                                appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12008                                if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12009                                {
12010                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12011                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12012                                        Info = _WRONG_MESSAGE_FORMAT;
12013                                        break;
12014                                }
12015                                plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12016                                li_flags = GET_DWORD(li_req_parms[1].info);
12017                                Info = li_check_main_plci(Id, plci);
12018                                result_buffer[0] = 9;
12019                                result_buffer[3] = 6;
12020                                PUT_DWORD(&result_buffer[4], plci_b_id);
12021                                PUT_WORD(&result_buffer[8], GOOD);
12022                                if (Info != GOOD)
12023                                        break;
12024                                result = plci->saved_msg.info;
12025                                for (i = 0; i <= result_buffer[0]; i++)
12026                                        result[i] = result_buffer[i];
12027                                plci_b_write_pos = plci->li_plci_b_write_pos;
12028                                plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12029                                if (plci_b == NULL)
12030                                        break;
12031                                li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12032                                plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12033                                plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12034                                plci->li_plci_b_write_pos = plci_b_write_pos;
12035                        }
12036                        else
12037                        {
12038                                appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12039                                if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12040                                {
12041                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12042                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12043                                        Info = _WRONG_MESSAGE_FORMAT;
12044                                        break;
12045                                }
12046                                li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12047                                Info = li_check_main_plci(Id, plci);
12048                                result_buffer[0] = 7;
12049                                result_buffer[3] = 4;
12050                                PUT_WORD(&result_buffer[4], Info);
12051                                result_buffer[6] = 0;
12052                                if (Info != GOOD)
12053                                        break;
12054                                result = plci->saved_msg.info;
12055                                for (i = 0; i <= result_buffer[0]; i++)
12056                                        result[i] = result_buffer[i];
12057                                plci_b_write_pos = plci->li_plci_b_write_pos;
12058                                participant_parms_pos = 0;
12059                                result_pos = 7;
12060                                li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12061                                while (participant_parms_pos < li_req_parms[1].length)
12062                                {
12063                                        result[result_pos] = 6;
12064                                        result_pos += 7;
12065                                        PUT_DWORD(&result[result_pos - 6], 0);
12066                                        PUT_WORD(&result[result_pos - 2], GOOD);
12067                                        if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12068                                                      (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12069                                        {
12070                                                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12071                                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12072                                                PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12073                                                break;
12074                                        }
12075                                        if (api_parse(&li_participant_struct[0].info[1],
12076                                                      li_participant_struct[0].length, "dd", li_participant_parms))
12077                                        {
12078                                                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12079                                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12080                                                PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12081                                                break;
12082                                        }
12083                                        plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12084                                        li_flags = GET_DWORD(li_participant_parms[1].info);
12085                                        PUT_DWORD(&result[result_pos - 6], plci_b_id);
12086                                        if (sizeof(result) - result_pos < 7)
12087                                        {
12088                                                dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12089                                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12090                                                PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12091                                                break;
12092                                        }
12093                                        plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12094                                        if (plci_b != NULL)
12095                                        {
12096                                                li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12097                                                plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12098                                                        ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12099                                                                      LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12100                                                plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12101                                        }
12102                                        participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12103                                                                       (&li_req_parms[1].info[1]));
12104                                }
12105                                result[0] = (byte)(result_pos - 1);
12106                                result[3] = (byte)(result_pos - 4);
12107                                result[6] = (byte)(result_pos - 7);
12108                                i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12109                                if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12110                                    || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12111                                {
12112                                        plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12113                                        plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12114                                }
12115                                else
12116                                        plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12117                                plci->li_plci_b_write_pos = plci_b_write_pos;
12118                        }
12119                        mixer_calculate_coefs(a);
12120                        plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12121                        mixer_notify_update(plci, true);
12122                        sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12123                              "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12124                        plci->command = 0;
12125                        plci->li_cmd = GET_WORD(li_parms[0].info);
12126                        start_internal_command(Id, plci, mixer_command);
12127                        return (false);
12128
12129                case LI_REQ_DISCONNECT:
12130                        if (li_parms[1].length == 4)
12131                        {
12132                                appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12133                                if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12134                                {
12135                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12136                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12137                                        Info = _WRONG_MESSAGE_FORMAT;
12138                                        break;
12139                                }
12140                                plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12141                                Info = li_check_main_plci(Id, plci);
12142                                result_buffer[0] = 9;
12143                                result_buffer[3] = 6;
12144                                PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12145                                PUT_WORD(&result_buffer[8], GOOD);
12146                                if (Info != GOOD)
12147                                        break;
12148                                result = plci->saved_msg.info;
12149                                for (i = 0; i <= result_buffer[0]; i++)
12150                                        result[i] = result_buffer[i];
12151                                plci_b_write_pos = plci->li_plci_b_write_pos;
12152                                plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12153                                if (plci_b == NULL)
12154                                        break;
12155                                li_update_connect(Id, a, plci, plci_b_id, false, 0);
12156                                plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12157                                plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12158                                plci->li_plci_b_write_pos = plci_b_write_pos;
12159                        }
12160                        else
12161                        {
12162                                appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12163                                if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12164                                {
12165                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12166                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12167                                        Info = _WRONG_MESSAGE_FORMAT;
12168                                        break;
12169                                }
12170                                Info = li_check_main_plci(Id, plci);
12171                                result_buffer[0] = 7;
12172                                result_buffer[3] = 4;
12173                                PUT_WORD(&result_buffer[4], Info);
12174                                result_buffer[6] = 0;
12175                                if (Info != GOOD)
12176                                        break;
12177                                result = plci->saved_msg.info;
12178                                for (i = 0; i <= result_buffer[0]; i++)
12179                                        result[i] = result_buffer[i];
12180                                plci_b_write_pos = plci->li_plci_b_write_pos;
12181                                participant_parms_pos = 0;
12182                                result_pos = 7;
12183                                while (participant_parms_pos < li_req_parms[0].length)
12184                                {
12185                                        result[result_pos] = 6;
12186                                        result_pos += 7;
12187                                        PUT_DWORD(&result[result_pos - 6], 0);
12188                                        PUT_WORD(&result[result_pos - 2], GOOD);
12189                                        if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12190                                                      (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12191                                        {
12192                                                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12193                                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12194                                                PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12195                                                break;
12196                                        }
12197                                        if (api_parse(&li_participant_struct[0].info[1],
12198                                                      li_participant_struct[0].length, "d", li_participant_parms))
12199                                        {
12200                                                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12201                                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12202                                                PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12203                                                break;
12204                                        }
12205                                        plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12206                                        PUT_DWORD(&result[result_pos - 6], plci_b_id);
12207                                        if (sizeof(result) - result_pos < 7)
12208                                        {
12209                                                dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12210                                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12211                                                PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12212                                                break;
12213                                        }
12214                                        plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12215                                        if (plci_b != NULL)
12216                                        {
12217                                                li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12218                                                plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12219                                                plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12220                                        }
12221                                        participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12222                                                                       (&li_req_parms[0].info[1]));
12223                                }
12224                                result[0] = (byte)(result_pos - 1);
12225                                result[3] = (byte)(result_pos - 4);
12226                                result[6] = (byte)(result_pos - 7);
12227                                i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12228                                if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12229                                    || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12230                                {
12231                                        plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12232                                        plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12233                                }
12234                                else
12235                                        plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12236                                plci->li_plci_b_write_pos = plci_b_write_pos;
12237                        }
12238                        mixer_calculate_coefs(a);
12239                        plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12240                        mixer_notify_update(plci, true);
12241                        sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12242                              "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12243                        plci->command = 0;
12244                        plci->li_cmd = GET_WORD(li_parms[0].info);
12245                        start_internal_command(Id, plci, mixer_command);
12246                        return (false);
12247
12248                case LI_REQ_SILENT_UPDATE:
12249                        if (!plci || !plci->State
12250                            || !plci->NL.Id || plci->nl_remove_id
12251                            || (plci->li_bchannel_id == 0)
12252                            || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12253                        {
12254                                dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12255                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12256                                return (false);
12257                        }
12258                        plci_b_write_pos = plci->li_plci_b_write_pos;
12259                        if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12260                             LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12261                        {
12262                                dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12263                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12264                                return (false);
12265                        }
12266                        i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12267                        if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12268                            || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12269                        {
12270                                plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12271                                plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12272                        }
12273                        else
12274                                plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12275                        plci->li_plci_b_write_pos = plci_b_write_pos;
12276                        plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12277                        plci->command = 0;
12278                        plci->li_cmd = GET_WORD(li_parms[0].info);
12279                        start_internal_command(Id, plci, mixer_command);
12280                        return (false);
12281
12282                default:
12283                        dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12284                                        UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12285                        Info = _FACILITY_NOT_SUPPORTED;
12286                }
12287        }
12288        sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12289              "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12290        return (false);
12291}
12292
12293
12294static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12295{
12296        dword d;
12297        byte result[12];
12298
12299        dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12300                        UnMapId(Id), (char *)(FILE_), __LINE__));
12301
12302        if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12303        {
12304                do
12305                {
12306                        d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12307                        if (!(d & LI_PLCI_B_SKIP_FLAG))
12308                        {
12309                                if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12310                                {
12311                                        if (d & LI_PLCI_B_DISC_FLAG)
12312                                        {
12313                                                result[0] = 5;
12314                                                PUT_WORD(&result[1], LI_IND_DISCONNECT);
12315                                                result[3] = 2;
12316                                                PUT_WORD(&result[4], _LI_USER_INITIATED);
12317                                        }
12318                                        else
12319                                        {
12320                                                result[0] = 7;
12321                                                PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12322                                                result[3] = 4;
12323                                                PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12324                                        }
12325                                }
12326                                else
12327                                {
12328                                        if (d & LI_PLCI_B_DISC_FLAG)
12329                                        {
12330                                                result[0] = 9;
12331                                                PUT_WORD(&result[1], LI_IND_DISCONNECT);
12332                                                result[3] = 6;
12333                                                PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12334                                                PUT_WORD(&result[8], _LI_USER_INITIATED);
12335                                        }
12336                                        else
12337                                        {
12338                                                result[0] = 7;
12339                                                PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12340                                                result[3] = 4;
12341                                                PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12342                                        }
12343                                }
12344                                sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12345                                      "ws", SELECTOR_LINE_INTERCONNECT, result);
12346                        }
12347                        plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12348                                0 : plci->li_plci_b_read_pos + 1;
12349                } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12350        }
12351}
12352
12353
12354static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12355{
12356        word i, j, ch;
12357        struct xconnect_transfer_address_s s,   *p;
12358        DIVA_CAPI_ADAPTER *a;
12359
12360        dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12361                        UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12362
12363        a = plci->adapter;
12364        i = 1;
12365        for (i = 1; i < length; i += 16)
12366        {
12367                s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12368                s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12369                s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12370                ch = msg[i + 12] | (msg[i + 13] << 8);
12371                j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12372                if (!a->li_pri && (plci->li_bchannel_id == 2))
12373                        j = 1 - j;
12374                j += a->li_base;
12375                if (ch & XCONNECT_CHANNEL_PORT_PC)
12376                        p = &(li_config_table[j].send_pc);
12377                else
12378                        p = &(li_config_table[j].send_b);
12379                p->card_address.low = s.card_address.low;
12380                p->card_address.high = s.card_address.high;
12381                p->offset = s.offset;
12382                li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12383        }
12384        if (plci->internal_command_queue[0]
12385            && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12386                || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12387                || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12388        {
12389                (*(plci->internal_command_queue[0]))(Id, plci, 0);
12390                if (!plci->internal_command)
12391                        next_internal_command(Id, plci);
12392        }
12393        mixer_notify_update(plci, true);
12394}
12395
12396
12397static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12398{
12399
12400        dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12401                        UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12402
12403}
12404
12405
12406static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12407{
12408        word plci_b_write_pos;
12409
12410        plci_b_write_pos = plci->li_plci_b_write_pos;
12411        if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12412             LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12413        {
12414                dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12415                                (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12416                                (char *)(FILE_), __LINE__));
12417                return (false);
12418        }
12419        plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12420        plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12421        plci->li_plci_b_write_pos = plci_b_write_pos;
12422        return (true);
12423}
12424
12425
12426static void mixer_remove(PLCI *plci)
12427{
12428        DIVA_CAPI_ADAPTER *a;
12429        PLCI *notify_plci;
12430        dword plci_b_id;
12431        word i, j;
12432
12433        dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12434                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12435                        (char *)(FILE_), __LINE__));
12436
12437        a = plci->adapter;
12438        plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12439        if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12440        {
12441                if ((plci->li_bchannel_id != 0)
12442                    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12443                {
12444                        i = a->li_base + (plci->li_bchannel_id - 1);
12445                        if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12446                        {
12447                                for (j = 0; j < li_total_channels; j++)
12448                                {
12449                                        if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12450                                            || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12451                                        {
12452                                                notify_plci = li_config_table[j].plci;
12453                                                if ((notify_plci != NULL)
12454                                                    && (notify_plci != plci)
12455                                                    && (notify_plci->appl != NULL)
12456                                                    && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12457                                                    && (notify_plci->State)
12458                                                    && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12459                                                {
12460                                                        mixer_notify_source_removed(notify_plci, plci_b_id);
12461                                                }
12462                                        }
12463                                }
12464                                mixer_clear_config(plci);
12465                                mixer_calculate_coefs(a);
12466                                mixer_notify_update(plci, true);
12467                        }
12468                        li_config_table[i].plci = NULL;
12469                        plci->li_bchannel_id = 0;
12470                }
12471        }
12472}
12473
12474
12475/*------------------------------------------------------------------*/
12476/* Echo canceller facilities                                        */
12477/*------------------------------------------------------------------*/
12478
12479
12480static void ec_write_parameters(PLCI *plci)
12481{
12482        word w;
12483        byte parameter_buffer[6];
12484
12485        dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12486                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12487                        (char *)(FILE_), __LINE__));
12488
12489        parameter_buffer[0] = 5;
12490        parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12491        PUT_WORD(&parameter_buffer[2], plci->ec_idi_options);
12492        plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12493        w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12494        PUT_WORD(&parameter_buffer[4], w);
12495        add_p(plci, FTY, parameter_buffer);
12496        sig_req(plci, TEL_CTRL, 0);
12497        send_req(plci);
12498}
12499
12500
12501static void ec_clear_config(PLCI *plci)
12502{
12503
12504        dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12505                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12506                        (char *)(FILE_), __LINE__));
12507
12508        plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12509                LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12510        plci->ec_tail_length = 0;
12511}
12512
12513
12514static void ec_prepare_switch(dword Id, PLCI *plci)
12515{
12516
12517        dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12518                        UnMapId(Id), (char *)(FILE_), __LINE__));
12519
12520}
12521
12522
12523static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12524{
12525
12526        dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12527                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12528
12529        return (GOOD);
12530}
12531
12532
12533static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12534{
12535        word Info;
12536
12537        dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12538                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12539
12540        Info = GOOD;
12541        if (plci->B1_facilities & B1_FACILITY_EC)
12542        {
12543                switch (plci->adjust_b_state)
12544                {
12545                case ADJUST_B_RESTORE_EC_1:
12546                        plci->internal_command = plci->adjust_b_command;
12547                        if (plci->sig_req)
12548                        {
12549                                plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12550                                break;
12551                        }
12552                        ec_write_parameters(plci);
12553                        plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12554                        break;
12555                case ADJUST_B_RESTORE_EC_2:
12556                        if ((Rc != OK) && (Rc != OK_FC))
12557                        {
12558                                dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12559                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12560                                Info = _WRONG_STATE;
12561                                break;
12562                        }
12563                        break;
12564                }
12565        }
12566        return (Info);
12567}
12568
12569
12570static void ec_command(dword Id, PLCI *plci, byte Rc)
12571{
12572        word internal_command, Info;
12573        byte result[8];
12574
12575        dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12576                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12577                        plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12578
12579        Info = GOOD;
12580        if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12581        {
12582                result[0] = 2;
12583                PUT_WORD(&result[1], EC_SUCCESS);
12584        }
12585        else
12586        {
12587                result[0] = 5;
12588                PUT_WORD(&result[1], plci->ec_cmd);
12589                result[3] = 2;
12590                PUT_WORD(&result[4], GOOD);
12591        }
12592        internal_command = plci->internal_command;
12593        plci->internal_command = 0;
12594        switch (plci->ec_cmd)
12595        {
12596        case EC_ENABLE_OPERATION:
12597        case EC_FREEZE_COEFFICIENTS:
12598        case EC_RESUME_COEFFICIENT_UPDATE:
12599        case EC_RESET_COEFFICIENTS:
12600                switch (internal_command)
12601                {
12602                default:
12603                        adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12604                                                                  B1_FACILITY_EC), EC_COMMAND_1);
12605                case EC_COMMAND_1:
12606                        if (adjust_b_process(Id, plci, Rc) != GOOD)
12607                        {
12608                                dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12609                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12610                                Info = _FACILITY_NOT_SUPPORTED;
12611                                break;
12612                        }
12613                        if (plci->internal_command)
12614                                return;
12615                case EC_COMMAND_2:
12616                        if (plci->sig_req)
12617                        {
12618                                plci->internal_command = EC_COMMAND_2;
12619                                return;
12620                        }
12621                        plci->internal_command = EC_COMMAND_3;
12622                        ec_write_parameters(plci);
12623                        return;
12624                case EC_COMMAND_3:
12625                        if ((Rc != OK) && (Rc != OK_FC))
12626                        {
12627                                dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12628                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12629                                Info = _FACILITY_NOT_SUPPORTED;
12630                                break;
12631                        }
12632                        break;
12633                }
12634                break;
12635
12636        case EC_DISABLE_OPERATION:
12637                switch (internal_command)
12638                {
12639                default:
12640                case EC_COMMAND_1:
12641                        if (plci->B1_facilities & B1_FACILITY_EC)
12642                        {
12643                                if (plci->sig_req)
12644                                {
12645                                        plci->internal_command = EC_COMMAND_1;
12646                                        return;
12647                                }
12648                                plci->internal_command = EC_COMMAND_2;
12649                                ec_write_parameters(plci);
12650                                return;
12651                        }
12652                        Rc = OK;
12653                case EC_COMMAND_2:
12654                        if ((Rc != OK) && (Rc != OK_FC))
12655                        {
12656                                dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12657                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12658                                Info = _FACILITY_NOT_SUPPORTED;
12659                                break;
12660                        }
12661                        adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12662                                                                  ~B1_FACILITY_EC), EC_COMMAND_3);
12663                case EC_COMMAND_3:
12664                        if (adjust_b_process(Id, plci, Rc) != GOOD)
12665                        {
12666                                dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12667                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12668                                Info = _FACILITY_NOT_SUPPORTED;
12669                                break;
12670                        }
12671                        if (plci->internal_command)
12672                                return;
12673                        break;
12674                }
12675                break;
12676        }
12677        sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12678              "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12679              PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12680}
12681
12682
12683static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
12684{
12685        word Info;
12686        word opt;
12687        API_PARSE ec_parms[3];
12688        byte result[16];
12689
12690        dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12691                        UnMapId(Id), (char *)(FILE_), __LINE__));
12692
12693        Info = GOOD;
12694        result[0] = 0;
12695        if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12696        {
12697                dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12698                                UnMapId(Id), (char *)(FILE_), __LINE__));
12699                Info = _FACILITY_NOT_SUPPORTED;
12700        }
12701        else
12702        {
12703                if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12704                {
12705                        if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12706                        {
12707                                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12708                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12709                                Info = _WRONG_MESSAGE_FORMAT;
12710                        }
12711                        else
12712                        {
12713                                if (plci == NULL)
12714                                {
12715                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12716                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12717                                        Info = _WRONG_IDENTIFIER;
12718                                }
12719                                else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12720                                {
12721                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12722                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12723                                        Info = _WRONG_STATE;
12724                                }
12725                                else
12726                                {
12727                                        plci->command = 0;
12728                                        plci->ec_cmd = GET_WORD(ec_parms[0].info);
12729                                        plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12730                                        result[0] = 2;
12731                                        PUT_WORD(&result[1], EC_SUCCESS);
12732                                        if (msg[1].length >= 4)
12733                                        {
12734                                                opt = GET_WORD(&ec_parms[0].info[2]);
12735                                                plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12736                                                                          LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12737                                                if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12738                                                        plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12739                                                if (opt & EC_DETECT_DISABLE_TONE)
12740                                                        plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12741                                                if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12742                                                        plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12743                                                if (msg[1].length >= 6)
12744                                                {
12745                                                        plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12746                                                }
12747                                        }
12748                                        switch (plci->ec_cmd)
12749                                        {
12750                                        case EC_ENABLE_OPERATION:
12751                                                plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12752                                                start_internal_command(Id, plci, ec_command);
12753                                                return (false);
12754
12755                                        case EC_DISABLE_OPERATION:
12756                                                plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12757                                                        LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12758                                                        LEC_RESET_COEFFICIENTS;
12759                                                start_internal_command(Id, plci, ec_command);
12760                                                return (false);
12761
12762                                        case EC_FREEZE_COEFFICIENTS:
12763                                                plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12764                                                start_internal_command(Id, plci, ec_command);
12765                                                return (false);
12766
12767                                        case EC_RESUME_COEFFICIENT_UPDATE:
12768                                                plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12769                                                start_internal_command(Id, plci, ec_command);
12770                                                return (false);
12771
12772                                        case EC_RESET_COEFFICIENTS:
12773                                                plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12774                                                start_internal_command(Id, plci, ec_command);
12775                                                return (false);
12776
12777                                        default:
12778                                                dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12779                                                                UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12780                                                PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12781                                        }
12782                                }
12783                        }
12784                }
12785                else
12786                {
12787                        if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12788                        {
12789                                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12790                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12791                                Info = _WRONG_MESSAGE_FORMAT;
12792                        }
12793                        else
12794                        {
12795                                if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12796                                {
12797                                        result[0] = 11;
12798                                        PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12799                                        result[3] = 8;
12800                                        PUT_WORD(&result[4], GOOD);
12801                                        PUT_WORD(&result[6], 0x0007);
12802                                        PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12803                                        PUT_WORD(&result[10], 0);
12804                                }
12805                                else if (plci == NULL)
12806                                {
12807                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12808                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12809                                        Info = _WRONG_IDENTIFIER;
12810                                }
12811                                else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12812                                {
12813                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12814                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12815                                        Info = _WRONG_STATE;
12816                                }
12817                                else
12818                                {
12819                                        plci->command = 0;
12820                                        plci->ec_cmd = GET_WORD(ec_parms[0].info);
12821                                        plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12822                                        result[0] = 5;
12823                                        PUT_WORD(&result[1], plci->ec_cmd);
12824                                        result[3] = 2;
12825                                        PUT_WORD(&result[4], GOOD);
12826                                        plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12827                                                                  LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12828                                        plci->ec_tail_length = 0;
12829                                        if (ec_parms[1].length >= 2)
12830                                        {
12831                                                opt = GET_WORD(&ec_parms[1].info[1]);
12832                                                if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12833                                                        plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12834                                                if (opt & EC_DETECT_DISABLE_TONE)
12835                                                        plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12836                                                if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12837                                                        plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12838                                                if (ec_parms[1].length >= 4)
12839                                                {
12840                                                        plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12841                                                }
12842                                        }
12843                                        switch (plci->ec_cmd)
12844                                        {
12845                                        case EC_ENABLE_OPERATION:
12846                                                plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12847                                                start_internal_command(Id, plci, ec_command);
12848                                                return (false);
12849
12850                                        case EC_DISABLE_OPERATION:
12851                                                plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12852                                                        LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12853                                                        LEC_RESET_COEFFICIENTS;
12854                                                start_internal_command(Id, plci, ec_command);
12855                                                return (false);
12856
12857                                        default:
12858                                                dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12859                                                                UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12860                                                PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12861                                        }
12862                                }
12863                        }
12864                }
12865        }
12866        sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12867              "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12868              PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12869        return (false);
12870}
12871
12872
12873static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
12874{
12875        byte result[8];
12876
12877        dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
12878                        UnMapId(Id), (char *)(FILE_), __LINE__));
12879
12880        if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
12881        {
12882                if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12883                {
12884                        result[0] = 2;
12885                        PUT_WORD(&result[1], 0);
12886                        switch (msg[1])
12887                        {
12888                        case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
12889                                PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
12890                                break;
12891                        case LEC_DISABLE_TYPE_REVERSED_2100HZ:
12892                                PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
12893                                break;
12894                        case LEC_DISABLE_RELEASED:
12895                                PUT_WORD(&result[1], EC_BYPASS_RELEASED);
12896                                break;
12897                        }
12898                }
12899                else
12900                {
12901                        result[0] = 5;
12902                        PUT_WORD(&result[1], EC_BYPASS_INDICATION);
12903                        result[3] = 2;
12904                        PUT_WORD(&result[4], 0);
12905                        switch (msg[1])
12906                        {
12907                        case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
12908                                PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
12909                                break;
12910                        case LEC_DISABLE_TYPE_REVERSED_2100HZ:
12911                                PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
12912                                break;
12913                        case LEC_DISABLE_RELEASED:
12914                                PUT_WORD(&result[4], EC_BYPASS_RELEASED);
12915                                break;
12916                        }
12917                }
12918                sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12919                      PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12920        }
12921}
12922
12923
12924
12925/*------------------------------------------------------------------*/
12926/* Advanced voice                                                   */
12927/*------------------------------------------------------------------*/
12928
12929static void adv_voice_write_coefs(PLCI *plci, word write_command)
12930{
12931        DIVA_CAPI_ADAPTER *a;
12932        word i;
12933        byte *p;
12934
12935        word w, n, j, k;
12936        byte ch_map[MIXER_CHANNELS_BRI];
12937
12938        byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
12939
12940        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
12941                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12942                        (char *)(FILE_), __LINE__, write_command));
12943
12944        a = plci->adapter;
12945        p = coef_buffer + 1;
12946        *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
12947        i = 0;
12948        while (i + sizeof(word) <= a->adv_voice_coef_length)
12949        {
12950                PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
12951                p += 2;
12952                i += 2;
12953        }
12954        while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
12955        {
12956                PUT_WORD(p, 0x8000);
12957                p += 2;
12958                i += 2;
12959        }
12960
12961        if (!a->li_pri && (plci->li_bchannel_id == 0))
12962        {
12963                if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
12964                {
12965                        plci->li_bchannel_id = 1;
12966                        li_config_table[a->li_base].plci = plci;
12967                        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
12968                                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12969                                        (char *)(FILE_), __LINE__, plci->li_bchannel_id));
12970                }
12971                else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
12972                {
12973                        plci->li_bchannel_id = 2;
12974                        li_config_table[a->li_base + 1].plci = plci;
12975                        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
12976                                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12977                                        (char *)(FILE_), __LINE__, plci->li_bchannel_id));
12978                }
12979        }
12980        if (!a->li_pri && (plci->li_bchannel_id != 0)
12981            && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12982        {
12983                i = a->li_base + (plci->li_bchannel_id - 1);
12984                switch (write_command)
12985                {
12986                case ADV_VOICE_WRITE_ACTIVATION:
12987                        j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
12988                        k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
12989                        if (!(plci->B1_facilities & B1_FACILITY_MIXER))
12990                        {
12991                                li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
12992                                li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
12993                        }
12994                        if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
12995                        {
12996                                li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
12997                                li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
12998                                li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
12999                                li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13000                        }
13001                        mixer_calculate_coefs(a);
13002                        li_config_table[i].curchnl = li_config_table[i].channel;
13003                        li_config_table[j].curchnl = li_config_table[j].channel;
13004                        if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13005                                li_config_table[k].curchnl = li_config_table[k].channel;
13006                        break;
13007
13008                case ADV_VOICE_WRITE_DEACTIVATION:
13009                        for (j = 0; j < li_total_channels; j++)
13010                        {
13011                                li_config_table[i].flag_table[j] = 0;
13012                                li_config_table[j].flag_table[i] = 0;
13013                        }
13014                        k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13015                        for (j = 0; j < li_total_channels; j++)
13016                        {
13017                                li_config_table[k].flag_table[j] = 0;
13018                                li_config_table[j].flag_table[k] = 0;
13019                        }
13020                        if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13021                        {
13022                                k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13023                                for (j = 0; j < li_total_channels; j++)
13024                                {
13025                                        li_config_table[k].flag_table[j] = 0;
13026                                        li_config_table[j].flag_table[k] = 0;
13027                                }
13028                        }
13029                        mixer_calculate_coefs(a);
13030                        break;
13031                }
13032                if (plci->B1_facilities & B1_FACILITY_MIXER)
13033                {
13034                        w = 0;
13035                        if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13036                                w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13037                        if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13038                                w |= MIXER_FEATURE_ENABLE_TX_DATA;
13039                        if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13040                                w |= MIXER_FEATURE_ENABLE_RX_DATA;
13041                        *(p++) = (byte) w;
13042                        *(p++) = (byte)(w >> 8);
13043                        for (j = 0; j < sizeof(ch_map); j += 2)
13044                        {
13045                                ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13046                                ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13047                        }
13048                        for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13049                        {
13050                                i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13051                                j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13052                                if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13053                                {
13054                                        *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13055                                        w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13056                                        li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13057                                }
13058                                else
13059                                {
13060                                        *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13061                                                a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13062                                }
13063                        }
13064                }
13065                else
13066                {
13067                        for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13068                                *(p++) = a->adv_voice_coef_buffer[i];
13069                }
13070        }
13071        else
13072
13073        {
13074                for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13075                        *(p++) = a->adv_voice_coef_buffer[i];
13076        }
13077        coef_buffer[0] = (p - coef_buffer) - 1;
13078        add_p(plci, FTY, coef_buffer);
13079        sig_req(plci, TEL_CTRL, 0);
13080        send_req(plci);
13081}
13082
13083
13084static void adv_voice_clear_config(PLCI *plci)
13085{
13086        DIVA_CAPI_ADAPTER *a;
13087
13088        word i, j;
13089
13090
13091        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13092                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13093                        (char *)(FILE_), __LINE__));
13094
13095        a = plci->adapter;
13096        if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13097        {
13098                a->adv_voice_coef_length = 0;
13099
13100                if (!a->li_pri && (plci->li_bchannel_id != 0)
13101                    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13102                {
13103                        i = a->li_base + (plci->li_bchannel_id - 1);
13104                        li_config_table[i].curchnl = 0;
13105                        li_config_table[i].channel = 0;
13106                        li_config_table[i].chflags = 0;
13107                        for (j = 0; j < li_total_channels; j++)
13108                        {
13109                                li_config_table[i].flag_table[j] = 0;
13110                                li_config_table[j].flag_table[i] = 0;
13111                                li_config_table[i].coef_table[j] = 0;
13112                                li_config_table[j].coef_table[i] = 0;
13113                        }
13114                        li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13115                        i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13116                        li_config_table[i].curchnl = 0;
13117                        li_config_table[i].channel = 0;
13118                        li_config_table[i].chflags = 0;
13119                        for (j = 0; j < li_total_channels; j++)
13120                        {
13121                                li_config_table[i].flag_table[j] = 0;
13122                                li_config_table[j].flag_table[i] = 0;
13123                                li_config_table[i].coef_table[j] = 0;
13124                                li_config_table[j].coef_table[i] = 0;
13125                        }
13126                        if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13127                        {
13128                                i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13129                                li_config_table[i].curchnl = 0;
13130                                li_config_table[i].channel = 0;
13131                                li_config_table[i].chflags = 0;
13132                                for (j = 0; j < li_total_channels; j++)
13133                                {
13134                                        li_config_table[i].flag_table[j] = 0;
13135                                        li_config_table[j].flag_table[i] = 0;
13136                                        li_config_table[i].coef_table[j] = 0;
13137                                        li_config_table[j].coef_table[i] = 0;
13138                                }
13139                        }
13140                }
13141
13142        }
13143}
13144
13145
13146static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13147{
13148
13149        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13150                        UnMapId(Id), (char *)(FILE_), __LINE__));
13151
13152}
13153
13154
13155static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13156{
13157
13158        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13159                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13160
13161        return (GOOD);
13162}
13163
13164
13165static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13166{
13167        DIVA_CAPI_ADAPTER *a;
13168        word Info;
13169
13170        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13171                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13172
13173        Info = GOOD;
13174        a = plci->adapter;
13175        if ((plci->B1_facilities & B1_FACILITY_VOICE)
13176            && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13177        {
13178                switch (plci->adjust_b_state)
13179                {
13180                case ADJUST_B_RESTORE_VOICE_1:
13181                        plci->internal_command = plci->adjust_b_command;
13182                        if (plci->sig_req)
13183                        {
13184                                plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13185                                break;
13186                        }
13187                        adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13188                        plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13189                        break;
13190                case ADJUST_B_RESTORE_VOICE_2:
13191                        if ((Rc != OK) && (Rc != OK_FC))
13192                        {
13193                                dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13194                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13195                                Info = _WRONG_STATE;
13196                                break;
13197                        }
13198                        break;
13199                }
13200        }
13201        return (Info);
13202}
13203
13204
13205
13206
13207/*------------------------------------------------------------------*/
13208/* B1 resource switching                                            */
13209/*------------------------------------------------------------------*/
13210
13211static byte b1_facilities_table[] =
13212{
13213        0x00,  /* 0  No bchannel resources      */
13214        0x00,  /* 1  Codec (automatic law)      */
13215        0x00,  /* 2  Codec (A-law)              */
13216        0x00,  /* 3  Codec (y-law)              */
13217        0x00,  /* 4  HDLC for X.21              */
13218        0x00,  /* 5  HDLC                       */
13219        0x00,  /* 6  External Device 0          */
13220        0x00,  /* 7  External Device 1          */
13221        0x00,  /* 8  HDLC 56k                   */
13222        0x00,  /* 9  Transparent                */
13223        0x00,  /* 10 Loopback to network        */
13224        0x00,  /* 11 Test pattern to net        */
13225        0x00,  /* 12 Rate adaptation sync       */
13226        0x00,  /* 13 Rate adaptation async      */
13227        0x00,  /* 14 R-Interface                */
13228        0x00,  /* 15 HDLC 128k leased line      */
13229        0x00,  /* 16 FAX                        */
13230        0x00,  /* 17 Modem async                */
13231        0x00,  /* 18 Modem sync HDLC            */
13232        0x00,  /* 19 V.110 async HDLC           */
13233        0x12,  /* 20 Adv voice (Trans,mixer)    */
13234        0x00,  /* 21 Codec connected to IC      */
13235        0x0c,  /* 22 Trans,DTMF                 */
13236        0x1e,  /* 23 Trans,DTMF+mixer           */
13237        0x1f,  /* 24 Trans,DTMF+mixer+local     */
13238        0x13,  /* 25 Trans,mixer+local          */
13239        0x12,  /* 26 HDLC,mixer                 */
13240        0x12,  /* 27 HDLC 56k,mixer             */
13241        0x2c,  /* 28 Trans,LEC+DTMF             */
13242        0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13243        0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13244        0x2c,  /* 31 RTP,LEC+DTMF               */
13245        0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13246        0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13247        0x00,  /* 34 Signaling task             */
13248        0x00,  /* 35 PIAFS                      */
13249        0x0c,  /* 36 Trans,DTMF+TONE            */
13250        0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13251        0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13252};
13253
13254
13255static word get_b1_facilities(PLCI *plci, byte b1_resource)
13256{
13257        word b1_facilities;
13258
13259        b1_facilities = b1_facilities_table[b1_resource];
13260        if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13261        {
13262
13263                if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13264                      || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13265
13266                {
13267                        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13268                                b1_facilities |= B1_FACILITY_DTMFX;
13269                        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13270                                b1_facilities |= B1_FACILITY_DTMFR;
13271                }
13272        }
13273        if ((b1_resource == 17) || (b1_resource == 18))
13274        {
13275                if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13276                        b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13277        }
13278/*
13279  dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13280  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13281  (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13282*/
13283        return (b1_facilities);
13284}
13285
13286
13287static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13288{
13289        byte b;
13290
13291        switch (b1_resource)
13292        {
13293        case 5:
13294        case 26:
13295                if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13296                        b = 26;
13297                else
13298                        b = 5;
13299                break;
13300
13301        case 8:
13302        case 27:
13303                if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13304                        b = 27;
13305                else
13306                        b = 8;
13307                break;
13308
13309        case 9:
13310        case 20:
13311        case 22:
13312        case 23:
13313        case 24:
13314        case 25:
13315        case 28:
13316        case 29:
13317        case 30:
13318        case 36:
13319        case 37:
13320        case 38:
13321                if (b1_facilities & B1_FACILITY_EC)
13322                {
13323                        if (b1_facilities & B1_FACILITY_LOCAL)
13324                                b = 30;
13325                        else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13326                                b = 29;
13327                        else
13328                                b = 28;
13329                }
13330
13331                else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13332                         && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13333                             || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13334                {
13335                        if (b1_facilities & B1_FACILITY_LOCAL)
13336                                b = 38;
13337                        else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13338                                b = 37;
13339                        else
13340                                b = 36;
13341                }
13342
13343                else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13344                          && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13345                         || ((b1_facilities & B1_FACILITY_DTMFR)
13346                             && ((b1_facilities & B1_FACILITY_MIXER)
13347                                 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13348                         || ((b1_facilities & B1_FACILITY_DTMFX)
13349                             && ((b1_facilities & B1_FACILITY_MIXER)
13350                                 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13351                {
13352                        if (b1_facilities & B1_FACILITY_LOCAL)
13353                                b = 24;
13354                        else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13355                                b = 23;
13356                        else
13357                                b = 22;
13358                }
13359                else
13360                {
13361                        if (b1_facilities & B1_FACILITY_LOCAL)
13362                                b = 25;
13363                        else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13364                                b = 20;
13365                        else
13366                                b = 9;
13367                }
13368                break;
13369
13370        case 31:
13371        case 32:
13372        case 33:
13373                if (b1_facilities & B1_FACILITY_LOCAL)
13374                        b = 33;
13375                else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13376                        b = 32;
13377                else
13378                        b = 31;
13379                break;
13380
13381        default:
13382                b = b1_resource;
13383        }
13384        dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13385                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13386                        (char *)(FILE_), __LINE__,
13387                        b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13388        return (b);
13389}
13390
13391
13392static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13393{
13394        word removed_facilities;
13395
13396        dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13397                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13398                        (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13399                        new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13400
13401        new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13402        removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13403
13404        if (removed_facilities & B1_FACILITY_EC)
13405                ec_clear_config(plci);
13406
13407
13408        if (removed_facilities & B1_FACILITY_DTMFR)
13409        {
13410                dtmf_rec_clear_config(plci);
13411                dtmf_parameter_clear_config(plci);
13412        }
13413        if (removed_facilities & B1_FACILITY_DTMFX)
13414                dtmf_send_clear_config(plci);
13415
13416
13417        if (removed_facilities & B1_FACILITY_MIXER)
13418                mixer_clear_config(plci);
13419
13420        if (removed_facilities & B1_FACILITY_VOICE)
13421                adv_voice_clear_config(plci);
13422        plci->B1_facilities = new_b1_facilities;
13423}
13424
13425
13426static void adjust_b_clear(PLCI *plci)
13427{
13428
13429        dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13430                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13431                        (char *)(FILE_), __LINE__));
13432
13433        plci->adjust_b_restore = false;
13434}
13435
13436
13437static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13438{
13439        word Info;
13440        byte b1_resource;
13441        NCCI *ncci_ptr;
13442        API_PARSE bp[2];
13443
13444        dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13445                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13446
13447        Info = GOOD;
13448        switch (plci->adjust_b_state)
13449        {
13450        case ADJUST_B_START:
13451                if ((plci->adjust_b_parms_msg == NULL)
13452                    && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13453                    && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13454                                                 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13455                {
13456                        b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13457                                0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13458                        if (b1_resource == plci->B1_resource)
13459                        {
13460                                adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13461                                break;
13462                        }
13463                        if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13464                        {
13465                                dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13466                                                UnMapId(Id), (char *)(FILE_), __LINE__,
13467                                                plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13468                                Info = _WRONG_STATE;
13469                                break;
13470                        }
13471                }
13472                if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13473                {
13474
13475                        mixer_prepare_switch(Id, plci);
13476
13477
13478                        dtmf_prepare_switch(Id, plci);
13479                        dtmf_parameter_prepare_switch(Id, plci);
13480
13481
13482                        ec_prepare_switch(Id, plci);
13483
13484                        adv_voice_prepare_switch(Id, plci);
13485                }
13486                plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13487                Rc = OK;
13488        case ADJUST_B_SAVE_MIXER_1:
13489                if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13490                {
13491
13492                        Info = mixer_save_config(Id, plci, Rc);
13493                        if ((Info != GOOD) || plci->internal_command)
13494                                break;
13495
13496                }
13497                plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13498                Rc = OK;
13499        case ADJUST_B_SAVE_DTMF_1:
13500                if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13501                {
13502
13503                        Info = dtmf_save_config(Id, plci, Rc);
13504                        if ((Info != GOOD) || plci->internal_command)
13505                                break;
13506
13507                }
13508                plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13509        case ADJUST_B_REMOVE_L23_1:
13510                if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13511                    && plci->NL.Id && !plci->nl_remove_id)
13512                {
13513                        plci->internal_command = plci->adjust_b_command;
13514                        if (plci->adjust_b_ncci != 0)
13515                        {
13516                                ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13517                                while (ncci_ptr->data_pending)
13518                                {
13519                                        plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13520                                        data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13521                                }
13522                                while (ncci_ptr->data_ack_pending)
13523                                        data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13524                        }
13525                        nl_req_ncci(plci, REMOVE,
13526                                    (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13527                        send_req(plci);
13528                        plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13529                        break;
13530                }
13531                plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13532                Rc = OK;
13533        case ADJUST_B_REMOVE_L23_2:
13534                if ((Rc != OK) && (Rc != OK_FC))
13535                {
13536                        dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13537                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13538                        Info = _WRONG_STATE;
13539                        break;
13540                }
13541                if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13542                {
13543                        if (plci_nl_busy(plci))
13544                        {
13545                                plci->internal_command = plci->adjust_b_command;
13546                                break;
13547                        }
13548                }
13549                plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13550                Rc = OK;
13551        case ADJUST_B_SAVE_EC_1:
13552                if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13553                {
13554
13555                        Info = ec_save_config(Id, plci, Rc);
13556                        if ((Info != GOOD) || plci->internal_command)
13557                                break;
13558
13559                }
13560                plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13561                Rc = OK;
13562        case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13563                if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13564                {
13565
13566                        Info = dtmf_parameter_save_config(Id, plci, Rc);
13567                        if ((Info != GOOD) || plci->internal_command)
13568                                break;
13569
13570                }
13571                plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13572                Rc = OK;
13573        case ADJUST_B_SAVE_VOICE_1:
13574                if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13575                {
13576                        Info = adv_voice_save_config(Id, plci, Rc);
13577                        if ((Info != GOOD) || plci->internal_command)
13578                                break;
13579                }
13580                plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13581        case ADJUST_B_SWITCH_L1_1:
13582                if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13583                {
13584                        if (plci->sig_req)
13585                        {
13586                                plci->internal_command = plci->adjust_b_command;
13587                                break;
13588                        }
13589                        if (plci->adjust_b_parms_msg != NULL)
13590                                api_load_msg(plci->adjust_b_parms_msg, bp);
13591                        else
13592                                api_load_msg(&plci->B_protocol, bp);
13593                        Info = add_b1(plci, bp,
13594                                      (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13595                                      plci->adjust_b_facilities);
13596                        if (Info != GOOD)
13597                        {
13598                                dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13599                                                UnMapId(Id), (char *)(FILE_), __LINE__,
13600                                                plci->B1_resource, plci->adjust_b_facilities));
13601                                break;
13602                        }
13603                        plci->internal_command = plci->adjust_b_command;
13604                        sig_req(plci, RESOURCES, 0);
13605                        send_req(plci);
13606                        plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13607                        break;
13608                }
13609                plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13610                Rc = OK;
13611        case ADJUST_B_SWITCH_L1_2:
13612                if ((Rc != OK) && (Rc != OK_FC))
13613                {
13614                        dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13615                                        UnMapId(Id), (char *)(FILE_), __LINE__,
13616                                        Rc, plci->B1_resource, plci->adjust_b_facilities));
13617                        Info = _WRONG_STATE;
13618                        break;
13619                }
13620                plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13621                Rc = OK;
13622        case ADJUST_B_RESTORE_VOICE_1:
13623        case ADJUST_B_RESTORE_VOICE_2:
13624                if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13625                {
13626                        Info = adv_voice_restore_config(Id, plci, Rc);
13627                        if ((Info != GOOD) || plci->internal_command)
13628                                break;
13629                }
13630                plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13631                Rc = OK;
13632        case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13633        case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13634                if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13635                {
13636
13637                        Info = dtmf_parameter_restore_config(Id, plci, Rc);
13638                        if ((Info != GOOD) || plci->internal_command)
13639                                break;
13640
13641                }
13642                plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13643                Rc = OK;
13644        case ADJUST_B_RESTORE_EC_1:
13645        case ADJUST_B_RESTORE_EC_2:
13646                if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13647                {
13648
13649                        Info = ec_restore_config(Id, plci, Rc);
13650                        if ((Info != GOOD) || plci->internal_command)
13651                                break;
13652
13653                }
13654                plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13655        case ADJUST_B_ASSIGN_L23_1:
13656                if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13657                {
13658                        if (plci_nl_busy(plci))
13659                        {
13660                                plci->internal_command = plci->adjust_b_command;
13661                                break;
13662                        }
13663                        if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13664                                plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13665                        if (plci->adjust_b_parms_msg != NULL)
13666                                api_load_msg(plci->adjust_b_parms_msg, bp);
13667                        else
13668                                api_load_msg(&plci->B_protocol, bp);
13669                        Info = add_b23(plci, bp);
13670                        if (Info != GOOD)
13671                        {
13672                                dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13673                                                UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13674                                break;
13675                        }
13676                        plci->internal_command = plci->adjust_b_command;
13677                        nl_req_ncci(plci, ASSIGN, 0);
13678                        send_req(plci);
13679                        plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13680                        break;
13681                }
13682                plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13683                Rc = ASSIGN_OK;
13684        case ADJUST_B_ASSIGN_L23_2:
13685                if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13686                {
13687                        dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13688                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13689                        Info = _WRONG_STATE;
13690                        break;
13691                }
13692                if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13693                {
13694                        if (Rc != ASSIGN_OK)
13695                        {
13696                                plci->internal_command = plci->adjust_b_command;
13697                                break;
13698                        }
13699                }
13700                if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13701                {
13702                        plci->adjust_b_restore = true;
13703                        break;
13704                }
13705                plci->adjust_b_state = ADJUST_B_CONNECT_1;
13706        case ADJUST_B_CONNECT_1:
13707                if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13708                {
13709                        plci->internal_command = plci->adjust_b_command;
13710                        if (plci_nl_busy(plci))
13711                                break;
13712                        nl_req_ncci(plci, N_CONNECT, 0);
13713                        send_req(plci);
13714                        plci->adjust_b_state = ADJUST_B_CONNECT_2;
13715                        break;
13716                }
13717                plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13718                Rc = OK;
13719        case ADJUST_B_CONNECT_2:
13720        case ADJUST_B_CONNECT_3:
13721        case ADJUST_B_CONNECT_4:
13722                if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13723                {
13724                        dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13725                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13726                        Info = _WRONG_STATE;
13727                        break;
13728                }
13729                if (Rc == OK)
13730                {
13731                        if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13732                        {
13733                                get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13734                                Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13735                        }
13736                        if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13737                                plci->adjust_b_state = ADJUST_B_CONNECT_3;
13738                        else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13739                                plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13740                }
13741                else if (Rc == 0)
13742                {
13743                        if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13744                                plci->adjust_b_state = ADJUST_B_CONNECT_4;
13745                        else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13746                                plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13747                }
13748                if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13749                {
13750                        plci->internal_command = plci->adjust_b_command;
13751                        break;
13752                }
13753                Rc = OK;
13754        case ADJUST_B_RESTORE_DTMF_1:
13755        case ADJUST_B_RESTORE_DTMF_2:
13756                if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13757                {
13758
13759                        Info = dtmf_restore_config(Id, plci, Rc);
13760                        if ((Info != GOOD) || plci->internal_command)
13761                                break;
13762
13763                }
13764                plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13765                Rc = OK;
13766        case ADJUST_B_RESTORE_MIXER_1:
13767        case ADJUST_B_RESTORE_MIXER_2:
13768        case ADJUST_B_RESTORE_MIXER_3:
13769        case ADJUST_B_RESTORE_MIXER_4:
13770        case ADJUST_B_RESTORE_MIXER_5:
13771        case ADJUST_B_RESTORE_MIXER_6:
13772        case ADJUST_B_RESTORE_MIXER_7:
13773                if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13774                {
13775
13776                        Info = mixer_restore_config(Id, plci, Rc);
13777                        if ((Info != GOOD) || plci->internal_command)
13778                                break;
13779
13780                }
13781                plci->adjust_b_state = ADJUST_B_END;
13782        case ADJUST_B_END:
13783                break;
13784        }
13785        return (Info);
13786}
13787
13788
13789static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13790{
13791
13792        dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13793                        UnMapId(Id), (char *)(FILE_), __LINE__,
13794                        plci->B1_resource, b1_facilities));
13795
13796        plci->adjust_b_parms_msg = bp_msg;
13797        plci->adjust_b_facilities = b1_facilities;
13798        plci->adjust_b_command = internal_command;
13799        plci->adjust_b_ncci = (word)(Id >> 16);
13800        if ((bp_msg == NULL) && (plci->B1_resource == 0))
13801                plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13802        else
13803                plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13804        plci->adjust_b_state = ADJUST_B_START;
13805        dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13806                        UnMapId(Id), (char *)(FILE_), __LINE__,
13807                        plci->B1_resource, b1_facilities));
13808}
13809
13810
13811static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13812{
13813        word internal_command;
13814
13815        dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13816                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13817
13818        internal_command = plci->internal_command;
13819        plci->internal_command = 0;
13820        switch (internal_command)
13821        {
13822        default:
13823                plci->command = 0;
13824                if (plci->req_in != 0)
13825                {
13826                        plci->internal_command = ADJUST_B_RESTORE_1;
13827                        break;
13828                }
13829                Rc = OK;
13830        case ADJUST_B_RESTORE_1:
13831                if ((Rc != OK) && (Rc != OK_FC))
13832                {
13833                        dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13834                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13835                }
13836                plci->adjust_b_parms_msg = NULL;
13837                plci->adjust_b_facilities = plci->B1_facilities;
13838                plci->adjust_b_command = ADJUST_B_RESTORE_2;
13839                plci->adjust_b_ncci = (word)(Id >> 16);
13840                plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13841                plci->adjust_b_state = ADJUST_B_START;
13842                dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13843                                UnMapId(Id), (char *)(FILE_), __LINE__));
13844        case ADJUST_B_RESTORE_2:
13845                if (adjust_b_process(Id, plci, Rc) != GOOD)
13846                {
13847                        dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13848                                        UnMapId(Id), (char *)(FILE_), __LINE__));
13849                }
13850                if (plci->internal_command)
13851                        break;
13852                break;
13853        }
13854}
13855
13856
13857static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
13858{
13859        word Info;
13860        word internal_command;
13861
13862        dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
13863                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13864
13865        Info = GOOD;
13866        internal_command = plci->internal_command;
13867        plci->internal_command = 0;
13868        switch (internal_command)
13869        {
13870        default:
13871                plci->command = 0;
13872                plci->adjust_b_parms_msg = NULL;
13873                plci->adjust_b_facilities = plci->B1_facilities;
13874                plci->adjust_b_command = RESET_B3_COMMAND_1;
13875                plci->adjust_b_ncci = (word)(Id >> 16);
13876                plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
13877                plci->adjust_b_state = ADJUST_B_START;
13878                dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
13879                                UnMapId(Id), (char *)(FILE_), __LINE__));
13880        case RESET_B3_COMMAND_1:
13881                Info = adjust_b_process(Id, plci, Rc);
13882                if (Info != GOOD)
13883                {
13884                        dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
13885                                        UnMapId(Id), (char *)(FILE_), __LINE__));
13886                        break;
13887                }
13888                if (plci->internal_command)
13889                        return;
13890                break;
13891        }
13892/*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
13893        sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
13894}
13895
13896
13897static void select_b_command(dword Id, PLCI *plci, byte Rc)
13898{
13899        word Info;
13900        word internal_command;
13901        byte esc_chi[3];
13902
13903        dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
13904                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13905
13906        Info = GOOD;
13907        internal_command = plci->internal_command;
13908        plci->internal_command = 0;
13909        switch (internal_command)
13910        {
13911        default:
13912                plci->command = 0;
13913                plci->adjust_b_parms_msg = &plci->saved_msg;
13914                if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
13915                        plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
13916                else
13917                        plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
13918                plci->adjust_b_command = SELECT_B_COMMAND_1;
13919                plci->adjust_b_ncci = (word)(Id >> 16);
13920                if (plci->saved_msg.parms[0].length == 0)
13921                {
13922                        plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
13923                                ADJUST_B_MODE_NO_RESOURCE;
13924                }
13925                else
13926                {
13927                        plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
13928                                ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
13929                }
13930                plci->adjust_b_state = ADJUST_B_START;
13931                dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
13932                                UnMapId(Id), (char *)(FILE_), __LINE__));
13933        case SELECT_B_COMMAND_1:
13934                Info = adjust_b_process(Id, plci, Rc);
13935                if (Info != GOOD)
13936                {
13937                        dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
13938                                        UnMapId(Id), (char *)(FILE_), __LINE__));
13939                        break;
13940                }
13941                if (plci->internal_command)
13942                        return;
13943                if (plci->tel == ADV_VOICE)
13944                {
13945                        esc_chi[0] = 0x02;
13946                        esc_chi[1] = 0x18;
13947                        esc_chi[2] = plci->b_channel;
13948                        SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
13949                }
13950                break;
13951        }
13952        sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
13953}
13954
13955
13956static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
13957{
13958        word internal_command;
13959
13960        dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
13961                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13962
13963        internal_command = plci->internal_command;
13964        plci->internal_command = 0;
13965        switch (internal_command)
13966        {
13967        default:
13968                plci->command = 0;
13969        case FAX_CONNECT_ACK_COMMAND_1:
13970                if (plci_nl_busy(plci))
13971                {
13972                        plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
13973                        return;
13974                }
13975                plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
13976                plci->NData[0].P = plci->fax_connect_info_buffer;
13977                plci->NData[0].PLength = plci->fax_connect_info_length;
13978                plci->NL.X = plci->NData;
13979                plci->NL.ReqCh = 0;
13980                plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
13981                plci->adapter->request(&plci->NL);
13982                return;
13983        case FAX_CONNECT_ACK_COMMAND_2:
13984                if ((Rc != OK) && (Rc != OK_FC))
13985                {
13986                        dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
13987                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13988                        break;
13989                }
13990        }
13991        if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
13992            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
13993        {
13994                if (plci->B3_prot == 4)
13995                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
13996                else
13997                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
13998                plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
13999        }
14000}
14001
14002
14003static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14004{
14005        word internal_command;
14006
14007        dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14008                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14009
14010        internal_command = plci->internal_command;
14011        plci->internal_command = 0;
14012        switch (internal_command)
14013        {
14014        default:
14015                plci->command = 0;
14016        case FAX_EDATA_ACK_COMMAND_1:
14017                if (plci_nl_busy(plci))
14018                {
14019                        plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14020                        return;
14021                }
14022                plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14023                plci->NData[0].P = plci->fax_connect_info_buffer;
14024                plci->NData[0].PLength = plci->fax_edata_ack_length;
14025                plci->NL.X = plci->NData;
14026                plci->NL.ReqCh = 0;
14027                plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14028                plci->adapter->request(&plci->NL);
14029                return;
14030        case FAX_EDATA_ACK_COMMAND_2:
14031                if ((Rc != OK) && (Rc != OK_FC))
14032                {
14033                        dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14034                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14035                        break;
14036                }
14037        }
14038}
14039
14040
14041static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14042{
14043        word Info;
14044        word internal_command;
14045
14046        dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14047                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14048
14049        Info = GOOD;
14050        internal_command = plci->internal_command;
14051        plci->internal_command = 0;
14052        switch (internal_command)
14053        {
14054        default:
14055                plci->command = 0;
14056        case FAX_CONNECT_INFO_COMMAND_1:
14057                if (plci_nl_busy(plci))
14058                {
14059                        plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14060                        return;
14061                }
14062                plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14063                plci->NData[0].P = plci->fax_connect_info_buffer;
14064                plci->NData[0].PLength = plci->fax_connect_info_length;
14065                plci->NL.X = plci->NData;
14066                plci->NL.ReqCh = 0;
14067                plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14068                plci->adapter->request(&plci->NL);
14069                return;
14070        case FAX_CONNECT_INFO_COMMAND_2:
14071                if ((Rc != OK) && (Rc != OK_FC))
14072                {
14073                        dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14074                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14075                        Info = _WRONG_STATE;
14076                        break;
14077                }
14078                if (plci_nl_busy(plci))
14079                {
14080                        plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14081                        return;
14082                }
14083                plci->command = _CONNECT_B3_R;
14084                nl_req_ncci(plci, N_CONNECT, 0);
14085                send_req(plci);
14086                return;
14087        }
14088        sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14089}
14090
14091
14092static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14093{
14094        word Info;
14095        word internal_command;
14096
14097        dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14098                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14099
14100        Info = GOOD;
14101        internal_command = plci->internal_command;
14102        plci->internal_command = 0;
14103        switch (internal_command)
14104        {
14105        default:
14106                plci->command = 0;
14107                plci->adjust_b_parms_msg = NULL;
14108                plci->adjust_b_facilities = plci->B1_facilities;
14109                plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14110                plci->adjust_b_ncci = (word)(Id >> 16);
14111                plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14112                plci->adjust_b_state = ADJUST_B_START;
14113                dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14114                                UnMapId(Id), (char *)(FILE_), __LINE__));
14115        case FAX_ADJUST_B23_COMMAND_1:
14116                Info = adjust_b_process(Id, plci, Rc);
14117                if (Info != GOOD)
14118                {
14119                        dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14120                                        UnMapId(Id), (char *)(FILE_), __LINE__));
14121                        break;
14122                }
14123                if (plci->internal_command)
14124                        return;
14125        case FAX_ADJUST_B23_COMMAND_2:
14126                if (plci_nl_busy(plci))
14127                {
14128                        plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14129                        return;
14130                }
14131                plci->command = _CONNECT_B3_R;
14132                nl_req_ncci(plci, N_CONNECT, 0);
14133                send_req(plci);
14134                return;
14135        }
14136        sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14137}
14138
14139
14140static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14141{
14142        word internal_command;
14143
14144        dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14145                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14146
14147        internal_command = plci->internal_command;
14148        plci->internal_command = 0;
14149        switch (internal_command)
14150        {
14151        default:
14152                plci->command = 0;
14153                plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14154                return;
14155        case FAX_DISCONNECT_COMMAND_1:
14156        case FAX_DISCONNECT_COMMAND_2:
14157        case FAX_DISCONNECT_COMMAND_3:
14158                if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14159                {
14160                        dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14161                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14162                        break;
14163                }
14164                if (Rc == OK)
14165                {
14166                        if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14167                            || (internal_command == FAX_DISCONNECT_COMMAND_2))
14168                        {
14169                                plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14170                        }
14171                }
14172                else if (Rc == 0)
14173                {
14174                        if (internal_command == FAX_DISCONNECT_COMMAND_1)
14175                                plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14176                }
14177                return;
14178        }
14179}
14180
14181
14182
14183static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14184{
14185        word Info;
14186        word internal_command;
14187
14188        dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14189                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14190
14191        Info = GOOD;
14192        internal_command = plci->internal_command;
14193        plci->internal_command = 0;
14194        switch (internal_command)
14195        {
14196        default:
14197                plci->command = 0;
14198        case RTP_CONNECT_B3_REQ_COMMAND_1:
14199                if (plci_nl_busy(plci))
14200                {
14201                        plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14202                        return;
14203                }
14204                plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14205                nl_req_ncci(plci, N_CONNECT, 0);
14206                send_req(plci);
14207                return;
14208        case RTP_CONNECT_B3_REQ_COMMAND_2:
14209                if ((Rc != OK) && (Rc != OK_FC))
14210                {
14211                        dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14212                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14213                        Info = _WRONG_STATE;
14214                        break;
14215                }
14216                if (plci_nl_busy(plci))
14217                {
14218                        plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14219                        return;
14220                }
14221                plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14222                plci->NData[0].PLength = plci->internal_req_buffer[0];
14223                plci->NData[0].P = plci->internal_req_buffer + 1;
14224                plci->NL.X = plci->NData;
14225                plci->NL.ReqCh = 0;
14226                plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14227                plci->adapter->request(&plci->NL);
14228                break;
14229        case RTP_CONNECT_B3_REQ_COMMAND_3:
14230                return;
14231        }
14232        sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14233}
14234
14235
14236static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14237{
14238        word internal_command;
14239
14240        dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14241                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14242
14243        internal_command = plci->internal_command;
14244        plci->internal_command = 0;
14245        switch (internal_command)
14246        {
14247        default:
14248                plci->command = 0;
14249        case RTP_CONNECT_B3_RES_COMMAND_1:
14250                if (plci_nl_busy(plci))
14251                {
14252                        plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14253                        return;
14254                }
14255                plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14256                nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14257                send_req(plci);
14258                return;
14259        case RTP_CONNECT_B3_RES_COMMAND_2:
14260                if ((Rc != OK) && (Rc != OK_FC))
14261                {
14262                        dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14263                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14264                        break;
14265                }
14266                if (plci_nl_busy(plci))
14267                {
14268                        plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14269                        return;
14270                }
14271                sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14272                plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14273                plci->NData[0].PLength = plci->internal_req_buffer[0];
14274                plci->NData[0].P = plci->internal_req_buffer + 1;
14275                plci->NL.X = plci->NData;
14276                plci->NL.ReqCh = 0;
14277                plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14278                plci->adapter->request(&plci->NL);
14279                return;
14280        case RTP_CONNECT_B3_RES_COMMAND_3:
14281                return;
14282        }
14283}
14284
14285
14286
14287static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14288{
14289        byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14290        word Info;
14291        word internal_command;
14292
14293        dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14294                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14295
14296        Info = GOOD;
14297        internal_command = plci->internal_command;
14298        plci->internal_command = 0;
14299        switch (internal_command)
14300        {
14301        default:
14302                if (!plci->NL.Id)
14303                        break;
14304                plci->command = 0;
14305                plci->adjust_b_parms_msg = NULL;
14306                plci->adjust_b_facilities = plci->B1_facilities;
14307                plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14308                plci->adjust_b_ncci = (word)(Id >> 16);
14309                plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14310                plci->adjust_b_state = ADJUST_B_START;
14311                dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14312                                UnMapId(Id), (char *)(FILE_), __LINE__));
14313        case HOLD_SAVE_COMMAND_1:
14314                Info = adjust_b_process(Id, plci, Rc);
14315                if (Info != GOOD)
14316                {
14317                        dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14318                                        UnMapId(Id), (char *)(FILE_), __LINE__));
14319                        break;
14320                }
14321                if (plci->internal_command)
14322                        return;
14323        }
14324        sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14325}
14326
14327
14328static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14329{
14330        byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14331        word Info;
14332        word internal_command;
14333
14334        dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14335                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14336
14337        Info = GOOD;
14338        internal_command = plci->internal_command;
14339        plci->internal_command = 0;
14340        switch (internal_command)
14341        {
14342        default:
14343                plci->command = 0;
14344                plci->adjust_b_parms_msg = NULL;
14345                plci->adjust_b_facilities = plci->B1_facilities;
14346                plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14347                plci->adjust_b_ncci = (word)(Id >> 16);
14348                plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14349                plci->adjust_b_state = ADJUST_B_START;
14350                dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14351                                UnMapId(Id), (char *)(FILE_), __LINE__));
14352        case RETRIEVE_RESTORE_COMMAND_1:
14353                Info = adjust_b_process(Id, plci, Rc);
14354                if (Info != GOOD)
14355                {
14356                        dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14357                                        UnMapId(Id), (char *)(FILE_), __LINE__));
14358                        break;
14359                }
14360                if (plci->internal_command)
14361                        return;
14362        }
14363        sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14364}
14365
14366
14367static void init_b1_config(PLCI *plci)
14368{
14369
14370        dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14371                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14372                        (char *)(FILE_), __LINE__));
14373
14374        plci->B1_resource = 0;
14375        plci->B1_facilities = 0;
14376
14377        plci->li_bchannel_id = 0;
14378        mixer_clear_config(plci);
14379
14380
14381        ec_clear_config(plci);
14382
14383
14384        dtmf_rec_clear_config(plci);
14385        dtmf_send_clear_config(plci);
14386        dtmf_parameter_clear_config(plci);
14387
14388        adv_voice_clear_config(plci);
14389        adjust_b_clear(plci);
14390}
14391
14392
14393static void clear_b1_config(PLCI *plci)
14394{
14395
14396        dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14397                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14398                        (char *)(FILE_), __LINE__));
14399
14400        adv_voice_clear_config(plci);
14401        adjust_b_clear(plci);
14402
14403        ec_clear_config(plci);
14404
14405
14406        dtmf_rec_clear_config(plci);
14407        dtmf_send_clear_config(plci);
14408        dtmf_parameter_clear_config(plci);
14409
14410
14411        if ((plci->li_bchannel_id != 0)
14412            && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14413        {
14414                mixer_clear_config(plci);
14415                li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14416                plci->li_bchannel_id = 0;
14417        }
14418
14419        plci->B1_resource = 0;
14420        plci->B1_facilities = 0;
14421}
14422
14423
14424/* -----------------------------------------------------------------
14425   XON protocol local helpers
14426   ----------------------------------------------------------------- */
14427static void channel_flow_control_remove(PLCI *plci) {
14428        DIVA_CAPI_ADAPTER *a = plci->adapter;
14429        word i;
14430        for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14431                if (a->ch_flow_plci[i] == plci->Id) {
14432                        a->ch_flow_plci[i] = 0;
14433                        a->ch_flow_control[i] = 0;
14434                }
14435        }
14436}
14437
14438static void channel_x_on(PLCI *plci, byte ch) {
14439        DIVA_CAPI_ADAPTER *a = plci->adapter;
14440        if (a->ch_flow_control[ch] & N_XON_SENT) {
14441                a->ch_flow_control[ch] &= ~N_XON_SENT;
14442        }
14443}
14444
14445static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14446        DIVA_CAPI_ADAPTER *a = plci->adapter;
14447        if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14448                a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14449                a->ch_flow_plci[ch] = plci->Id;
14450                a->ch_flow_control_pending++;
14451        }
14452}
14453
14454static void channel_request_xon(PLCI *plci, byte ch) {
14455        DIVA_CAPI_ADAPTER *a = plci->adapter;
14456
14457        if (a->ch_flow_control[ch] & N_CH_XOFF) {
14458                a->ch_flow_control[ch] |= N_XON_REQ;
14459                a->ch_flow_control[ch] &= ~N_CH_XOFF;
14460                a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14461        }
14462}
14463
14464static void channel_xmit_extended_xon(PLCI *plci) {
14465        DIVA_CAPI_ADAPTER *a;
14466        int max_ch = ARRAY_SIZE(a->ch_flow_control);
14467        int i, one_requested = 0;
14468
14469        if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14470                return;
14471        }
14472
14473        for (i = 0; i < max_ch; i++) {
14474                if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14475                    (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14476                    (plci->Id == a->ch_flow_plci[i])) {
14477                        channel_request_xon(plci, (byte)i);
14478                        one_requested = 1;
14479                }
14480        }
14481
14482        if (one_requested) {
14483                channel_xmit_xon(plci);
14484        }
14485}
14486
14487/*
14488  Try to xmit next X_ON
14489*/
14490static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14491        int max_ch = ARRAY_SIZE(a->ch_flow_control);
14492        int i;
14493
14494        if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14495                return (0);
14496        }
14497
14498        if (a->last_flow_control_ch >= max_ch) {
14499                a->last_flow_control_ch = 1;
14500        }
14501        for (i = a->last_flow_control_ch; i < max_ch; i++) {
14502                if ((a->ch_flow_control[i] & N_XON_REQ) &&
14503                    (plci->Id == a->ch_flow_plci[i])) {
14504                        a->last_flow_control_ch = i + 1;
14505                        return (i);
14506                }
14507        }
14508
14509        for (i = 1; i < a->last_flow_control_ch; i++) {
14510                if ((a->ch_flow_control[i] & N_XON_REQ) &&
14511                    (plci->Id == a->ch_flow_plci[i])) {
14512                        a->last_flow_control_ch = i + 1;
14513                        return (i);
14514                }
14515        }
14516
14517        return (0);
14518}
14519
14520static void channel_xmit_xon(PLCI *plci) {
14521        DIVA_CAPI_ADAPTER *a = plci->adapter;
14522        byte ch;
14523
14524        if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14525                return;
14526        }
14527        if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14528                return;
14529        }
14530        a->ch_flow_control[ch] &= ~N_XON_REQ;
14531        a->ch_flow_control[ch] |= N_XON_SENT;
14532
14533        plci->NL.Req = plci->nl_req = (byte)N_XON;
14534        plci->NL.ReqCh         = ch;
14535        plci->NL.X             = plci->NData;
14536        plci->NL.XNum          = 1;
14537        plci->NData[0].P       = &plci->RBuffer[0];
14538        plci->NData[0].PLength = 0;
14539
14540        plci->adapter->request(&plci->NL);
14541}
14542
14543static int channel_can_xon(PLCI *plci, byte ch) {
14544        APPL *APPLptr;
14545        DIVA_CAPI_ADAPTER *a;
14546        word NCCIcode;
14547        dword count;
14548        word Num;
14549        word i;
14550
14551        APPLptr = plci->appl;
14552        a = plci->adapter;
14553
14554        if (!APPLptr)
14555                return (0);
14556
14557        NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14558
14559        /* count all buffers within the Application pool    */
14560        /* belonging to the same NCCI. XON if a first is    */
14561        /* used.                                            */
14562        count = 0;
14563        Num = 0xffff;
14564        for (i = 0; i < APPLptr->MaxBuffer; i++) {
14565                if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14566                if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14567        }
14568        if ((count > 2) || (Num == 0xffff)) {
14569                return (0);
14570        }
14571        return (1);
14572}
14573
14574
14575/*------------------------------------------------------------------*/
14576
14577static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14578{
14579        return 1;
14580}
14581
14582
14583
14584/**********************************************************************************/
14585/* function groups the listening applications according to the CIP mask and the   */
14586/* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14587/* are not multi-instance capable, so they start e.g. 30 applications what causes */
14588/* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14589/* function must be enabled by setting "a->group_optimization_enabled" from the   */
14590/* OS specific part (per adapter).                                                */
14591/**********************************************************************************/
14592static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14593{
14594        word i, j, k, busy, group_found;
14595        dword info_mask_group[MAX_CIP_TYPES];
14596        dword cip_mask_group[MAX_CIP_TYPES];
14597        word appl_number_group_type[MAX_APPL];
14598        PLCI *auxplci;
14599
14600        /* all APPLs within this inc. call are allowed to dial in */
14601        bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
14602
14603        if (!a->group_optimization_enabled)
14604        {
14605                dbug(1, dprintf("No group optimization"));
14606                return;
14607        }
14608
14609        dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14610
14611        for (i = 0; i < MAX_CIP_TYPES; i++)
14612        {
14613                info_mask_group[i] = 0;
14614                cip_mask_group[i] = 0;
14615        }
14616        for (i = 0; i < MAX_APPL; i++)
14617        {
14618                appl_number_group_type[i] = 0;
14619        }
14620        for (i = 0; i < max_appl; i++) /* check if any multi instance capable application is present */
14621        {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14622                if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14623                {
14624                        dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14625                        return; /* allow good application unfiltered access */
14626                }
14627        }
14628        for (i = 0; i < max_appl; i++) /* Build CIP Groups */
14629        {
14630                if (application[i].Id && a->CIP_Mask[i])
14631                {
14632                        for (k = 0, busy = false; k < a->max_plci; k++)
14633                        {
14634                                if (a->plci[k].Id)
14635                                {
14636                                        auxplci = &a->plci[k];
14637                                        if (auxplci->appl == &application[i]) {
14638                                                /* application has a busy PLCI */
14639                                                busy = true;
14640                                                dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14641                                        } else if (test_bit(i, plci->c_ind_mask_table)) {
14642                                                /* application has an incoming call pending */
14643                                                busy = true;
14644                                                dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14645                                        }
14646                                }
14647                        }
14648
14649                        for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++)     /* build groups with free applications only */
14650                        {
14651                                if (j == MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14652                                {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14653                                        appl_number_group_type[i] = MAX_CIP_TYPES;
14654                                        group_found = true;
14655                                        dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14656                                }
14657                                else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14658                                {                                      /* is group already present ?                  */
14659                                        appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14660                                        group_found = true;
14661                                        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]));
14662                                }
14663                                else if (!info_mask_group[j])
14664                                {                                      /* establish a new group                       */
14665                                        appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14666                                        info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14667                                        cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14668                                        group_found = true;
14669                                        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]));
14670                                }
14671                        }
14672                }
14673        }
14674
14675        for (i = 0; i < max_appl; i++) /* Build group_optimization_mask_table */
14676        {
14677                if (appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14678                {
14679                        if (appl_number_group_type[i] == MAX_CIP_TYPES)
14680                        {
14681                                dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14682                        }
14683                        else
14684                        {
14685                                dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14686                                for (j = i + 1; j < max_appl; j++)   /* search other group members and mark them as busy        */
14687                                {
14688                                        if (appl_number_group_type[i] == appl_number_group_type[j])
14689                                        {
14690                                                dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14691                                                /* disable call on other group members */
14692                                                __clear_bit(j, plci->group_optimization_mask_table);
14693                                                appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14694                                        }
14695                                }
14696                        }
14697                }
14698                else                                                 /* application should not get a call */
14699                {
14700                        __clear_bit(i, plci->group_optimization_mask_table);
14701                }
14702        }
14703
14704}
14705
14706
14707
14708/* OS notifies the driver about a application Capi_Register */
14709word CapiRegister(word id)
14710{
14711        word i, j, appls_found;
14712
14713        PLCI *plci;
14714        DIVA_CAPI_ADAPTER *a;
14715
14716        for (i = 0, appls_found = 0; i < max_appl; i++)
14717        {
14718                if (application[i].Id && (application[i].Id != id))
14719                {
14720                        appls_found++;                       /* an application has been found */
14721                }
14722        }
14723
14724        if (appls_found) return true;
14725        for (i = 0; i < max_adapter; i++)                   /* scan all adapters...    */
14726        {
14727                a = &adapter[i];
14728                if (a->request)
14729                {
14730                        if (a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14731                        {
14732                                if (!appls_found)           /* first application does a capi register   */
14733                                {
14734                                        if ((j = get_plci(a)))                    /* activate L1 of all adapters */
14735                                        {
14736                                                plci = &a->plci[j - 1];
14737                                                plci->command = 0;
14738                                                add_p(plci, OAD, "\x01\xfd");
14739                                                add_p(plci, CAI, "\x01\x80");
14740                                                add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14741                                                add_p(plci, SHIFT | 6, NULL);
14742                                                add_p(plci, SIN, "\x02\x00\x00");
14743                                                plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14744                                                sig_req(plci, ASSIGN, DSIG_ID);
14745                                                add_p(plci, FTY, "\x02\xff\x07"); /* l1 start */
14746                                                sig_req(plci, SIG_CTRL, 0);
14747                                                send_req(plci);
14748                                        }
14749                                }
14750                        }
14751                }
14752        }
14753        return false;
14754}
14755
14756/*------------------------------------------------------------------*/
14757
14758/* Functions for virtual Switching e.g. Transfer by join, Conference */
14759
14760static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14761{
14762        word i;
14763        /* Format of vswitch_t:
14764           0 byte length
14765           1 byte VSWITCHIE
14766           2 byte VSWITCH_REQ/VSWITCH_IND
14767           3 byte reserved
14768           4 word VSwitchcommand
14769           6 word returnerror
14770           8... Params
14771        */
14772        if (!plci ||
14773            !plci->appl ||
14774            !plci->State ||
14775            plci->Sig.Ind == NCR_FACILITY
14776                )
14777                return;
14778
14779        for (i = 0; i < MAX_MULTI_IE; i++)
14780        {
14781                if (!parms[i][0]) continue;
14782                if (parms[i][0] < 7)
14783                {
14784                        parms[i][0] = 0; /* kill it */
14785                        continue;
14786                }
14787                dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14788                switch (parms[i][4])
14789                {
14790                case VSJOIN:
14791                        if (!plci->relatedPTYPLCI ||
14792                            (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14793                        { /* Error */
14794                                break;
14795                        }
14796                        /* remember all necessary informations */
14797                        if (parms[i][0] != 11 || parms[i][8] != 3) /* Length Test */
14798                        {
14799                                break;
14800                        }
14801                        if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14802                        {   /* first indication after ECT-Request on Consultation Call */
14803                                plci->vswitchstate = parms[i][9];
14804                                parms[i][9] = 2; /* State */
14805                                /* now ask first Call to join */
14806                        }
14807                        else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14808                        { /* Answer of VSWITCH_REQ from first Call */
14809                                plci->vswitchstate = parms[i][9];
14810                                /* tell consultation call to join
14811                                   and the protocol capabilities of the first call */
14812                        }
14813                        else
14814                        { /* Error */
14815                                break;
14816                        }
14817                        plci->vsprot = parms[i][10]; /* protocol */
14818                        plci->vsprotdialect = parms[i][11]; /* protocoldialect */
14819                        /* send join request to related PLCI */
14820                        parms[i][1] = VSWITCHIE;
14821                        parms[i][2] = VSWITCH_REQ;
14822
14823                        plci->relatedPTYPLCI->command = 0;
14824                        plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14825                        add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14826                        sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14827                        send_req(plci->relatedPTYPLCI);
14828                        break;
14829                case VSTRANSPORT:
14830                default:
14831                        if (plci->relatedPTYPLCI &&
14832                            plci->vswitchstate == 3 &&
14833                            plci->relatedPTYPLCI->vswitchstate == 3)
14834                        {
14835                                add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14836                                sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14837                                send_req(plci->relatedPTYPLCI);
14838                        }
14839                        break;
14840                }
14841                parms[i][0] = 0; /* kill it */
14842        }
14843}
14844
14845
14846/*------------------------------------------------------------------*/
14847
14848static int diva_get_dma_descriptor(PLCI *plci, dword   *dma_magic) {
14849        ENTITY e;
14850        IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14851
14852        if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14853                return (-1);
14854        }
14855
14856        pReq->xdi_dma_descriptor_operation.Req = 0;
14857        pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14858
14859        pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14860        pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
14861        pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14862        pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
14863
14864        e.user[0] = plci->adapter->Id - 1;
14865        plci->adapter->request((ENTITY *)pReq);
14866
14867        if (!pReq->xdi_dma_descriptor_operation.info.operation &&
14868            (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
14869            pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
14870                *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
14871                dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
14872                                plci->adapter->Id,
14873                                pReq->xdi_dma_descriptor_operation.info.descriptor_number,
14874                                *dma_magic));
14875                return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
14876        } else {
14877                dbug(1, dprintf("dma_alloc failed"));
14878                return (-1);
14879        }
14880}
14881
14882static void diva_free_dma_descriptor(PLCI *plci, int nr) {
14883        ENTITY e;
14884        IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14885
14886        if (nr < 0) {
14887                return;
14888        }
14889
14890        pReq->xdi_dma_descriptor_operation.Req = 0;
14891        pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14892
14893        pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
14894        pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
14895        pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14896        pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
14897
14898        e.user[0] = plci->adapter->Id - 1;
14899        plci->adapter->request((ENTITY *)pReq);
14900
14901        if (!pReq->xdi_dma_descriptor_operation.info.operation) {
14902                dbug(1, dprintf("dma_free(%d)", nr));
14903        } else {
14904                dbug(1, dprintf("dma_free failed (%d)", nr));
14905        }
14906}
14907
14908/*------------------------------------------------------------------*/
14909