linux/drivers/isdn/hardware/eicon/message.c
<<
>>
Prefs
   1/*
   2 *
   3 Copyright (c) Eicon Networks, 2002.
   4 *
   5 This source file is supplied for the use with
   6 Eicon Networks range of DIVA Server Adapters.
   7 *
   8 Eicon File Revision :    2.1
   9 *
  10 This program is free software; you can redistribute it and/or modify
  11 it under the terms of the GNU General Public License as published by
  12 the Free Software Foundation; either version 2, or (at your option)
  13 any later version.
  14 *
  15 This program is distributed in the hope that it will be useful,
  16 but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
  17 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  18 See the GNU General Public License for more details.
  19 *
  20 You should have received a copy of the GNU General Public License
  21 along with this program; if not, write to the Free Software
  22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23 *
  24 */
  25
  26
  27
  28
  29
  30#include "platform.h"
  31#include "di_defs.h"
  32#include "pc.h"
  33#include "capi20.h"
  34#include "divacapi.h"
  35#include "mdm_msg.h"
  36#include "divasync.h"
  37
  38
  39
  40#define FILE_ "MESSAGE.C"
  41#define dprintf
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51/*------------------------------------------------------------------*/
  52/* This is options supported for all adapters that are server by    */
  53/* XDI driver. Allo it is not necessary to ask it from every adapter*/
  54/* and it is not necessary to save it separate for every adapter    */
  55/* Macrose defined here have only local meaning                     */
  56/*------------------------------------------------------------------*/
  57static dword diva_xdi_extended_features = 0;
  58
  59#define DIVA_CAPI_USE_CMA                 0x00000001
  60#define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR  0x00000002
  61#define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL  0x00000004
  62#define DIVA_CAPI_XDI_PROVIDES_RX_DMA     0x00000008
  63
  64/*
  65  CAPI can request to process all return codes self only if:
  66  protocol code supports this && xdi supports this
  67*/
  68#define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__)   (((__a__)->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL) && ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) && (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
  69
  70/*------------------------------------------------------------------*/
  71/* local function prototypes                                        */
  72/*------------------------------------------------------------------*/
  73
  74static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci);
  75static void set_group_ind_mask(PLCI *plci);
  76static void clear_group_ind_mask_bit(PLCI *plci, word b);
  77static byte test_group_ind_mask_bit(PLCI *plci, word b);
  78void AutomaticLaw(DIVA_CAPI_ADAPTER *);
  79word CapiRelease(word);
  80word CapiRegister(word);
  81word api_put(APPL *, CAPI_MSG *);
  82static word api_parse(byte *, word, byte *, API_PARSE *);
  83static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out);
  84static void api_load_msg(API_SAVE *in, API_PARSE *out);
  85
  86word api_remove_start(void);
  87void api_remove_complete(void);
  88
  89static void plci_remove(PLCI *);
  90static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a);
  91static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *);
  92
  93void callback(ENTITY *);
  94
  95static void control_rc(PLCI *, byte, byte, byte, byte, byte);
  96static void data_rc(PLCI *, byte);
  97static void data_ack(PLCI *, byte);
  98static void sig_ind(PLCI *);
  99static void SendInfo(PLCI *, dword, byte **, byte);
 100static void SendSetupInfo(APPL *, PLCI *, dword, byte **, byte);
 101static void SendSSExtInd(APPL *, PLCI *plci, dword Id, byte **parms);
 102
 103static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
 104
 105static void nl_ind(PLCI *);
 106
 107static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 108static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 109static byte connect_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 110static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 111static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 112static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 113static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 114static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 115static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 116static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 117static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 118static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 119static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 120static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 121static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 122static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 123static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 124static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 125static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 126static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 127static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 128static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 129static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 130static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 131
 132static word get_plci(DIVA_CAPI_ADAPTER *);
 133static void add_p(PLCI *, byte, byte *);
 134static void add_s(PLCI *plci, byte code, API_PARSE *p);
 135static void add_ss(PLCI *plci, byte code, API_PARSE *p);
 136static void add_ie(PLCI *plci, byte code, byte *p, word p_length);
 137static void add_d(PLCI *, word, byte *);
 138static void add_ai(PLCI *, API_PARSE *);
 139static word add_b1(PLCI *, API_PARSE *, word, word);
 140static word add_b23(PLCI *, API_PARSE *);
 141static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms);
 142static void sig_req(PLCI *, byte, byte);
 143static void nl_req_ncci(PLCI *, byte, byte);
 144static void send_req(PLCI *);
 145static void send_data(PLCI *);
 146static word plci_remove_check(PLCI *);
 147static void listen_check(DIVA_CAPI_ADAPTER *);
 148static byte AddInfo(byte **, byte **, byte *, byte *);
 149static byte getChannel(API_PARSE *);
 150static void IndParse(PLCI *, word *, byte **, byte);
 151static byte ie_compare(byte *, byte *);
 152static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *);
 153static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *, word);
 154
 155/*
 156  XON protocol helpers
 157*/
 158static void channel_flow_control_remove(PLCI *plci);
 159static void channel_x_off(PLCI *plci, byte ch, byte flag);
 160static void channel_x_on(PLCI *plci, byte ch);
 161static void channel_request_xon(PLCI *plci, byte ch);
 162static void channel_xmit_xon(PLCI *plci);
 163static int channel_can_xon(PLCI *plci, byte ch);
 164static void channel_xmit_extended_xon(PLCI *plci);
 165
 166static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type, dword info_mask, byte setupParse);
 167static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte);
 168static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *);
 169static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER *);
 170static void VoiceChannelOff(PLCI *plci);
 171static void adv_voice_write_coefs(PLCI *plci, word write_command);
 172static void adv_voice_clear_config(PLCI *plci);
 173
 174static word get_b1_facilities(PLCI *plci, byte b1_resource);
 175static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities);
 176static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities);
 177static word adjust_b_process(dword Id, PLCI *plci, byte Rc);
 178static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command);
 179static void adjust_b_restore(dword Id, PLCI *plci, byte Rc);
 180static void reset_b3_command(dword Id, PLCI *plci, byte Rc);
 181static void select_b_command(dword Id, PLCI *plci, byte Rc);
 182static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc);
 183static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc);
 184static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc);
 185static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc);
 186static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc);
 187static void hold_save_command(dword Id, PLCI *plci, byte Rc);
 188static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc);
 189static void init_b1_config(PLCI *plci);
 190static void clear_b1_config(PLCI *plci);
 191
 192static void dtmf_command(dword Id, PLCI *plci, byte Rc);
 193static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
 194static void dtmf_confirmation(dword Id, PLCI *plci);
 195static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length);
 196static void dtmf_parameter_write(PLCI *plci);
 197
 198
 199static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id);
 200static void mixer_set_bchannel_id(PLCI *plci, byte *chi);
 201static void mixer_clear_config(PLCI *plci);
 202static void mixer_notify_update(PLCI *plci, byte others);
 203static void mixer_command(dword Id, PLCI *plci, byte Rc);
 204static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
 205static void mixer_indication_coefs_set(dword Id, PLCI *plci);
 206static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length);
 207static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length);
 208static void mixer_remove(PLCI *plci);
 209
 210
 211static void ec_command(dword Id, PLCI *plci, byte Rc);
 212static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
 213static void ec_indication(dword Id, PLCI *plci, byte *msg, word length);
 214
 215
 216static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc);
 217static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc);
 218
 219
 220static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic);
 221static void diva_free_dma_descriptor(PLCI *plci, int nr);
 222
 223/*------------------------------------------------------------------*/
 224/* external function prototypes                                     */
 225/*------------------------------------------------------------------*/
 226
 227extern byte MapController(byte);
 228extern byte UnMapController(byte);
 229#define MapId(Id)(((Id) & 0xffffff00L) | MapController((byte)(Id)))
 230#define UnMapId(Id)(((Id) & 0xffffff00L) | UnMapController((byte)(Id)))
 231
 232void sendf(APPL *, word, dword, word, byte *, ...);
 233void *TransmitBufferSet(APPL *appl, dword ref);
 234void *TransmitBufferGet(APPL *appl, void *p);
 235void TransmitBufferFree(APPL *appl, void *p);
 236void *ReceiveBufferGet(APPL *appl, int Num);
 237
 238int fax_head_line_time(char *buffer);
 239
 240
 241/*------------------------------------------------------------------*/
 242/* Global data definitions                                          */
 243/*------------------------------------------------------------------*/
 244extern byte max_adapter;
 245extern byte max_appl;
 246extern DIVA_CAPI_ADAPTER *adapter;
 247extern APPL *application;
 248
 249
 250
 251
 252
 253
 254
 255static byte remove_started = false;
 256static PLCI dummy_plci;
 257
 258
 259static struct _ftable {
 260        word command;
 261        byte *format;
 262        byte (*function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
 263} ftable[] = {
 264        {_DATA_B3_R,                          "dwww",         data_b3_req},
 265        {_DATA_B3_I | RESPONSE,               "w",            data_b3_res},
 266        {_INFO_R,                             "ss",           info_req},
 267        {_INFO_I | RESPONSE,                  "",             info_res},
 268        {_CONNECT_R,                          "wsssssssss",   connect_req},
 269        {_CONNECT_I | RESPONSE,               "wsssss",       connect_res},
 270        {_CONNECT_ACTIVE_I | RESPONSE,        "",             connect_a_res},
 271        {_DISCONNECT_R,                       "s",            disconnect_req},
 272        {_DISCONNECT_I | RESPONSE,            "",             disconnect_res},
 273        {_LISTEN_R,                           "dddss",        listen_req},
 274        {_ALERT_R,                            "s",            alert_req},
 275        {_FACILITY_R,                         "ws",           facility_req},
 276        {_FACILITY_I | RESPONSE,              "ws",           facility_res},
 277        {_CONNECT_B3_R,                       "s",            connect_b3_req},
 278        {_CONNECT_B3_I | RESPONSE,            "ws",           connect_b3_res},
 279        {_CONNECT_B3_ACTIVE_I | RESPONSE,     "",             connect_b3_a_res},
 280        {_DISCONNECT_B3_R,                    "s",            disconnect_b3_req},
 281        {_DISCONNECT_B3_I | RESPONSE,         "",             disconnect_b3_res},
 282        {_RESET_B3_R,                         "s",            reset_b3_req},
 283        {_RESET_B3_I | RESPONSE,              "",             reset_b3_res},
 284        {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "ws",           connect_b3_t90_a_res},
 285        {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "",             connect_b3_t90_a_res},
 286        {_SELECT_B_REQ,                       "s",            select_b_req},
 287        {_MANUFACTURER_R,                     "dws",          manufacturer_req},
 288        {_MANUFACTURER_I | RESPONSE,          "dws",          manufacturer_res},
 289        {_MANUFACTURER_I | RESPONSE,          "",             manufacturer_res}
 290};
 291
 292static byte *cip_bc[29][2] = {
 293        { "",                     ""                     }, /* 0 */
 294        { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 1 */
 295        { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 2 */
 296        { "\x02\x89\x90",         "\x02\x89\x90"         }, /* 3 */
 297        { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 4 */
 298        { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 5 */
 299        { "\x02\x98\x90",         "\x02\x98\x90"         }, /* 6 */
 300        { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
 301        { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
 302        { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 9 */
 303        { "",                     ""                     }, /* 10 */
 304        { "",                     ""                     }, /* 11 */
 305        { "",                     ""                     }, /* 12 */
 306        { "",                     ""                     }, /* 13 */
 307        { "",                     ""                     }, /* 14 */
 308        { "",                     ""                     }, /* 15 */
 309
 310        { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 16 */
 311        { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 17 */
 312        { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 18 */
 313        { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 19 */
 314        { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 20 */
 315        { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 21 */
 316        { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 22 */
 317        { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 23 */
 318        { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 24 */
 319        { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 25 */
 320        { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 26 */
 321        { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 27 */
 322        { "\x02\x88\x90",         "\x02\x88\x90"         }  /* 28 */
 323};
 324
 325static byte *cip_hlc[29] = {
 326        "",                           /* 0 */
 327        "",                           /* 1 */
 328        "",                           /* 2 */
 329        "",                           /* 3 */
 330        "",                           /* 4 */
 331        "",                           /* 5 */
 332        "",                           /* 6 */
 333        "",                           /* 7 */
 334        "",                           /* 8 */
 335        "",                           /* 9 */
 336        "",                           /* 10 */
 337        "",                           /* 11 */
 338        "",                           /* 12 */
 339        "",                           /* 13 */
 340        "",                           /* 14 */
 341        "",                           /* 15 */
 342
 343        "\x02\x91\x81",               /* 16 */
 344        "\x02\x91\x84",               /* 17 */
 345        "\x02\x91\xa1",               /* 18 */
 346        "\x02\x91\xa4",               /* 19 */
 347        "\x02\x91\xa8",               /* 20 */
 348        "\x02\x91\xb1",               /* 21 */
 349        "\x02\x91\xb2",               /* 22 */
 350        "\x02\x91\xb5",               /* 23 */
 351        "\x02\x91\xb8",               /* 24 */
 352        "\x02\x91\xc1",               /* 25 */
 353        "\x02\x91\x81",               /* 26 */
 354        "\x03\x91\xe0\x01",           /* 27 */
 355        "\x03\x91\xe0\x02"            /* 28 */
 356};
 357
 358/*------------------------------------------------------------------*/
 359
 360#define V120_HEADER_LENGTH 1
 361#define V120_HEADER_EXTEND_BIT  0x80
 362#define V120_HEADER_BREAK_BIT   0x40
 363#define V120_HEADER_C1_BIT      0x04
 364#define V120_HEADER_C2_BIT      0x08
 365#define V120_HEADER_FLUSH_COND  (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
 366
 367static byte v120_default_header[] =
 368{
 369
 370        0x83                          /*  Ext, BR , res, res, C2 , C1 , B  , F   */
 371
 372};
 373
 374static byte v120_break_header[] =
 375{
 376
 377        0xc3 | V120_HEADER_BREAK_BIT  /*  Ext, BR , res, res, C2 , C1 , B  , F   */
 378
 379};
 380
 381
 382/*------------------------------------------------------------------*/
 383/* API_PUT function                                                 */
 384/*------------------------------------------------------------------*/
 385
 386word api_put(APPL *appl, CAPI_MSG *msg)
 387{
 388        word i, j, k, l, n;
 389        word ret;
 390        byte c;
 391        byte controller;
 392        DIVA_CAPI_ADAPTER *a;
 393        PLCI *plci;
 394        NCCI *ncci_ptr;
 395        word ncci;
 396        CAPI_MSG *m;
 397        API_PARSE msg_parms[MAX_MSG_PARMS + 1];
 398
 399        if (msg->header.length < sizeof(msg->header) ||
 400            msg->header.length > MAX_MSG_SIZE) {
 401                dbug(1, dprintf("bad len"));
 402                return _BAD_MSG;
 403        }
 404
 405        controller = (byte)((msg->header.controller & 0x7f) - 1);
 406
 407        /* controller starts with 0 up to (max_adapter - 1) */
 408        if (controller >= max_adapter)
 409        {
 410                dbug(1, dprintf("invalid ctrl"));
 411                return _BAD_MSG;
 412        }
 413
 414        a = &adapter[controller];
 415        plci = NULL;
 416        if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
 417        {
 418                dbug(1, dprintf("plci=%x", msg->header.plci));
 419                plci = &a->plci[msg->header.plci - 1];
 420                ncci = GET_WORD(&msg->header.ncci);
 421                if (plci->Id
 422                    && (plci->appl
 423                        || (plci->State == INC_CON_PENDING)
 424                        || (plci->State == INC_CON_ALERT)
 425                        || (msg->header.command == (_DISCONNECT_I | RESPONSE)))
 426                    && ((ncci == 0)
 427                        || (msg->header.command == (_DISCONNECT_B3_I | RESPONSE))
 428                        || ((ncci < MAX_NCCI + 1) && (a->ncci_plci[ncci] == plci->Id))))
 429                {
 430                        i = plci->msg_in_read_pos;
 431                        j = plci->msg_in_write_pos;
 432                        if (j >= i)
 433                        {
 434                                if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
 435                                        i += MSG_IN_QUEUE_SIZE - j;
 436                                else
 437                                        j = 0;
 438                        }
 439                        else
 440                        {
 441
 442                                n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
 443
 444                                if (i > MSG_IN_QUEUE_SIZE - n)
 445                                        i = MSG_IN_QUEUE_SIZE - n + 1;
 446                                i -= j;
 447                        }
 448
 449                        if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
 450
 451                        {
 452                                dbug(0, dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
 453                                                msg->header.length, plci->msg_in_write_pos,
 454                                                plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
 455
 456                                return _QUEUE_FULL;
 457                        }
 458                        c = false;
 459                        if ((((byte *) msg) < ((byte *)(plci->msg_in_queue)))
 460                            || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
 461                        {
 462                                if (plci->msg_in_write_pos != plci->msg_in_read_pos)
 463                                        c = true;
 464                        }
 465                        if (msg->header.command == _DATA_B3_R)
 466                        {
 467                                if (msg->header.length < 20)
 468                                {
 469                                        dbug(1, dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
 470                                        return _BAD_MSG;
 471                                }
 472                                ncci_ptr = &(a->ncci[ncci]);
 473                                n = ncci_ptr->data_pending;
 474                                l = ncci_ptr->data_ack_pending;
 475                                k = plci->msg_in_read_pos;
 476                                while (k != plci->msg_in_write_pos)
 477                                {
 478                                        if (k == plci->msg_in_wrap_pos)
 479                                                k = 0;
 480                                        if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
 481                                            && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
 482                                        {
 483                                                n++;
 484                                                if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
 485                                                        l++;
 486                                        }
 487
 488                                        k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
 489                                              MSG_IN_OVERHEAD + 3) & 0xfffc;
 490
 491                                }
 492                                if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
 493                                {
 494                                        dbug(0, dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
 495                                                        ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
 496
 497                                        return _QUEUE_FULL;
 498                                }
 499                                if (plci->req_in || plci->internal_command)
 500                                {
 501                                        if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
 502                                            && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
 503                                        {
 504                                                dbug(0, dprintf("Q-FULL3(requeue)"));
 505
 506                                                return _QUEUE_FULL;
 507                                        }
 508                                        c = true;
 509                                }
 510                        }
 511                        else
 512                        {
 513                                if (plci->req_in || plci->internal_command)
 514                                        c = true;
 515                                else
 516                                {
 517                                        plci->command = msg->header.command;
 518                                        plci->number = msg->header.number;
 519                                }
 520                        }
 521                        if (c)
 522                        {
 523                                dbug(1, dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
 524                                                msg->header.command, plci->req_in, plci->internal_command,
 525                                                msg->header.length, plci->msg_in_write_pos,
 526                                                plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
 527                                if (j == 0)
 528                                        plci->msg_in_wrap_pos = plci->msg_in_write_pos;
 529                                m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
 530                                for (i = 0; i < msg->header.length; i++)
 531                                        ((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i];
 532                                if (m->header.command == _DATA_B3_R)
 533                                {
 534
 535                                        m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet(appl, m->info.data_b3_req.Data));
 536
 537                                }
 538
 539                                j = (j + 3) & 0xfffc;
 540
 541                                *((APPL **)(&((byte *)(plci->msg_in_queue))[j])) = appl;
 542                                plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
 543                                return 0;
 544                        }
 545                }
 546                else
 547                {
 548                        plci = NULL;
 549                }
 550        }
 551        dbug(1, dprintf("com=%x", msg->header.command));
 552
 553        for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
 554        for (i = 0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
 555
 556                if (ftable[i].command == msg->header.command) {
 557                        /* break loop if the message is correct, otherwise continue scan  */
 558                        /* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */
 559                        if (!api_parse(msg->info.b, (word)(msg->header.length - 12), ftable[i].format, msg_parms)) {
 560                                ret = 0;
 561                                break;
 562                        }
 563                        for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
 564                }
 565        }
 566        if (ret) {
 567                dbug(1, dprintf("BAD_MSG"));
 568                if (plci) plci->command = 0;
 569                return ret;
 570        }
 571
 572
 573        c = ftable[i].function(GET_DWORD(&msg->header.controller),
 574                               msg->header.number,
 575                               a,
 576                               plci,
 577                               appl,
 578                               msg_parms);
 579
 580        channel_xmit_extended_xon(plci);
 581
 582        if (c == 1) send_req(plci);
 583        if (c == 2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
 584        if (plci && !plci->req_in) plci->command = 0;
 585        return 0;
 586}
 587
 588
 589/*------------------------------------------------------------------*/
 590/* api_parse function, check the format of api messages             */
 591/*------------------------------------------------------------------*/
 592
 593static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
 594{
 595        word i;
 596        word p;
 597
 598        for (i = 0, p = 0; format[i]; i++) {
 599                if (parms)
 600                {
 601                        parms[i].info = &msg[p];
 602                }
 603                switch (format[i]) {
 604                case 'b':
 605                        p += 1;
 606                        break;
 607                case 'w':
 608                        p += 2;
 609                        break;
 610                case 'd':
 611                        p += 4;
 612                        break;
 613                case 's':
 614                        if (msg[p] == 0xff) {
 615                                parms[i].info += 2;
 616                                parms[i].length = msg[p + 1] + (msg[p + 2] << 8);
 617                                p += (parms[i].length + 3);
 618                        }
 619                        else {
 620                                parms[i].length = msg[p];
 621                                p += (parms[i].length + 1);
 622                        }
 623                        break;
 624                }
 625
 626                if (p > length) return true;
 627        }
 628        if (parms) parms[i].info = NULL;
 629        return false;
 630}
 631
 632static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
 633{
 634        word i, j, n = 0;
 635        byte *p;
 636
 637        p = out->info;
 638        for (i = 0; format[i] != '\0'; i++)
 639        {
 640                out->parms[i].info = p;
 641                out->parms[i].length = in[i].length;
 642                switch (format[i])
 643                {
 644                case 'b':
 645                        n = 1;
 646                        break;
 647                case 'w':
 648                        n = 2;
 649                        break;
 650                case 'd':
 651                        n = 4;
 652                        break;
 653                case 's':
 654                        n = in[i].length + 1;
 655                        break;
 656                }
 657                for (j = 0; j < n; j++)
 658                        *(p++) = in[i].info[j];
 659        }
 660        out->parms[i].info = NULL;
 661        out->parms[i].length = 0;
 662}
 663
 664static void api_load_msg(API_SAVE *in, API_PARSE *out)
 665{
 666        word i;
 667
 668        i = 0;
 669        do
 670        {
 671                out[i].info = in->parms[i].info;
 672                out[i].length = in->parms[i].length;
 673        } while (in->parms[i++].info);
 674}
 675
 676
 677/*------------------------------------------------------------------*/
 678/* CAPI remove function                                             */
 679/*------------------------------------------------------------------*/
 680
 681word api_remove_start(void)
 682{
 683        word i;
 684        word j;
 685
 686        if (!remove_started) {
 687                remove_started = true;
 688                for (i = 0; i < max_adapter; i++) {
 689                        if (adapter[i].request) {
 690                                for (j = 0; j < adapter[i].max_plci; j++) {
 691                                        if (adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
 692                                }
 693                        }
 694                }
 695                return 1;
 696        }
 697        else {
 698                for (i = 0; i < max_adapter; i++) {
 699                        if (adapter[i].request) {
 700                                for (j = 0; j < adapter[i].max_plci; j++) {
 701                                        if (adapter[i].plci[j].Sig.Id) return 1;
 702                                }
 703                        }
 704                }
 705        }
 706        api_remove_complete();
 707        return 0;
 708}
 709
 710
 711/*------------------------------------------------------------------*/
 712/* internal command queue                                           */
 713/*------------------------------------------------------------------*/
 714
 715static void init_internal_command_queue(PLCI *plci)
 716{
 717        word i;
 718
 719        dbug(1, dprintf("%s,%d: init_internal_command_queue",
 720                        (char *)(FILE_), __LINE__));
 721
 722        plci->internal_command = 0;
 723        for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
 724                plci->internal_command_queue[i] = NULL;
 725}
 726
 727
 728static void start_internal_command(dword Id, PLCI *plci, t_std_internal_command command_function)
 729{
 730        word i;
 731
 732        dbug(1, dprintf("[%06lx] %s,%d: start_internal_command",
 733                        UnMapId(Id), (char *)(FILE_), __LINE__));
 734
 735        if (plci->internal_command == 0)
 736        {
 737                plci->internal_command_queue[0] = command_function;
 738                (*command_function)(Id, plci, OK);
 739        }
 740        else
 741        {
 742                i = 1;
 743                while (plci->internal_command_queue[i] != NULL)
 744                        i++;
 745                plci->internal_command_queue[i] = command_function;
 746        }
 747}
 748
 749
 750static void next_internal_command(dword Id, PLCI *plci)
 751{
 752        word i;
 753
 754        dbug(1, dprintf("[%06lx] %s,%d: next_internal_command",
 755                        UnMapId(Id), (char *)(FILE_), __LINE__));
 756
 757        plci->internal_command = 0;
 758        plci->internal_command_queue[0] = NULL;
 759        while (plci->internal_command_queue[1] != NULL)
 760        {
 761                for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
 762                        plci->internal_command_queue[i] = plci->internal_command_queue[i + 1];
 763                plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
 764                (*(plci->internal_command_queue[0]))(Id, plci, OK);
 765                if (plci->internal_command != 0)
 766                        return;
 767                plci->internal_command_queue[0] = NULL;
 768        }
 769}
 770
 771
 772/*------------------------------------------------------------------*/
 773/* NCCI allocate/remove function                                    */
 774/*------------------------------------------------------------------*/
 775
 776static dword ncci_mapping_bug = 0;
 777
 778static word get_ncci(PLCI *plci, byte ch, word force_ncci)
 779{
 780        DIVA_CAPI_ADAPTER *a;
 781        word ncci, i, j, k;
 782
 783        a = plci->adapter;
 784        if (!ch || a->ch_ncci[ch])
 785        {
 786                ncci_mapping_bug++;
 787                dbug(1, dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
 788                                ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
 789                ncci = ch;
 790        }
 791        else
 792        {
 793                if (force_ncci)
 794                        ncci = force_ncci;
 795                else
 796                {
 797                        if ((ch < MAX_NCCI + 1) && !a->ncci_ch[ch])
 798                                ncci = ch;
 799                        else
 800                        {
 801                                ncci = 1;
 802                                while ((ncci < MAX_NCCI + 1) && a->ncci_ch[ncci])
 803                                        ncci++;
 804                                if (ncci == MAX_NCCI + 1)
 805                                {
 806                                        ncci_mapping_bug++;
 807                                        i = 1;
 808                                        do
 809                                        {
 810                                                j = 1;
 811                                                while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i))
 812                                                        j++;
 813                                                k = j;
 814                                                if (j < MAX_NCCI + 1)
 815                                                {
 816                                                        do
 817                                                        {
 818                                                                j++;
 819                                                        } while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i));
 820                                                }
 821                                        } while ((i < MAX_NL_CHANNEL + 1) && (j < MAX_NCCI + 1));
 822                                        if (i < MAX_NL_CHANNEL + 1)
 823                                        {
 824                                                dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
 825                                                                ncci_mapping_bug, ch, force_ncci, i, k, j));
 826                                        }
 827                                        else
 828                                        {
 829                                                dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x",
 830                                                                ncci_mapping_bug, ch, force_ncci));
 831                                        }
 832                                        ncci = ch;
 833                                }
 834                        }
 835                        a->ncci_plci[ncci] = plci->Id;
 836                        a->ncci_state[ncci] = IDLE;
 837                        if (!plci->ncci_ring_list)
 838                                plci->ncci_ring_list = ncci;
 839                        else
 840                                a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
 841                        a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
 842                }
 843                a->ncci_ch[ncci] = ch;
 844                a->ch_ncci[ch] = (byte) ncci;
 845                dbug(1, dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
 846                                ncci_mapping_bug, ch, force_ncci, ch, ncci));
 847        }
 848        return (ncci);
 849}
 850
 851
 852static void ncci_free_receive_buffers(PLCI *plci, word ncci)
 853{
 854        DIVA_CAPI_ADAPTER *a;
 855        APPL *appl;
 856        word i, ncci_code;
 857        dword Id;
 858
 859        a = plci->adapter;
 860        Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
 861        if (ncci)
 862        {
 863                if (a->ncci_plci[ncci] == plci->Id)
 864                {
 865                        if (!plci->appl)
 866                        {
 867                                ncci_mapping_bug++;
 868                                dbug(1, dprintf("NCCI mapping appl expected %ld %08lx",
 869                                                ncci_mapping_bug, Id));
 870                        }
 871                        else
 872                        {
 873                                appl = plci->appl;
 874                                ncci_code = ncci | (((word) a->Id) << 8);
 875                                for (i = 0; i < appl->MaxBuffer; i++)
 876                                {
 877                                        if ((appl->DataNCCI[i] == ncci_code)
 878                                            && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
 879                                        {
 880                                                appl->DataNCCI[i] = 0;
 881                                        }
 882                                }
 883                        }
 884                }
 885        }
 886        else
 887        {
 888                for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
 889                {
 890                        if (a->ncci_plci[ncci] == plci->Id)
 891                        {
 892                                if (!plci->appl)
 893                                {
 894                                        ncci_mapping_bug++;
 895                                        dbug(1, dprintf("NCCI mapping no appl %ld %08lx",
 896                                                        ncci_mapping_bug, Id));
 897                                }
 898                                else
 899                                {
 900                                        appl = plci->appl;
 901                                        ncci_code = ncci | (((word) a->Id) << 8);
 902                                        for (i = 0; i < appl->MaxBuffer; i++)
 903                                        {
 904                                                if ((appl->DataNCCI[i] == ncci_code)
 905                                                    && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
 906                                                {
 907                                                        appl->DataNCCI[i] = 0;
 908                                                }
 909                                        }
 910                                }
 911                        }
 912                }
 913        }
 914}
 915
 916
 917static void cleanup_ncci_data(PLCI *plci, word ncci)
 918{
 919        NCCI *ncci_ptr;
 920
 921        if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
 922        {
 923                ncci_ptr = &(plci->adapter->ncci[ncci]);
 924                if (plci->appl)
 925                {
 926                        while (ncci_ptr->data_pending != 0)
 927                        {
 928                                if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
 929                                        TransmitBufferFree(plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
 930                                (ncci_ptr->data_out)++;
 931                                if (ncci_ptr->data_out == MAX_DATA_B3)
 932                                        ncci_ptr->data_out = 0;
 933                                (ncci_ptr->data_pending)--;
 934                        }
 935                }
 936                ncci_ptr->data_out = 0;
 937                ncci_ptr->data_pending = 0;
 938                ncci_ptr->data_ack_out = 0;
 939                ncci_ptr->data_ack_pending = 0;
 940        }
 941}
 942
 943
 944static void ncci_remove(PLCI *plci, word ncci, byte preserve_ncci)
 945{
 946        DIVA_CAPI_ADAPTER *a;
 947        dword Id;
 948        word i;
 949
 950        a = plci->adapter;
 951        Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
 952        if (!preserve_ncci)
 953                ncci_free_receive_buffers(plci, ncci);
 954        if (ncci)
 955        {
 956                if (a->ncci_plci[ncci] != plci->Id)
 957                {
 958                        ncci_mapping_bug++;
 959                        dbug(1, dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
 960                                        ncci_mapping_bug, Id, preserve_ncci));
 961                }
 962                else
 963                {
 964                        cleanup_ncci_data(plci, ncci);
 965                        dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
 966                                        ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
 967                        a->ch_ncci[a->ncci_ch[ncci]] = 0;
 968                        if (!preserve_ncci)
 969                        {
 970                                a->ncci_ch[ncci] = 0;
 971                                a->ncci_plci[ncci] = 0;
 972                                a->ncci_state[ncci] = IDLE;
 973                                i = plci->ncci_ring_list;
 974                                while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
 975                                        i = a->ncci_next[i];
 976                                if ((i != 0) && (a->ncci_next[i] == ncci))
 977                                {
 978                                        if (i == ncci)
 979                                                plci->ncci_ring_list = 0;
 980                                        else if (plci->ncci_ring_list == ncci)
 981                                                plci->ncci_ring_list = i;
 982                                        a->ncci_next[i] = a->ncci_next[ncci];
 983                                }
 984                                a->ncci_next[ncci] = 0;
 985                        }
 986                }
 987        }
 988        else
 989        {
 990                for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
 991                {
 992                        if (a->ncci_plci[ncci] == plci->Id)
 993                        {
 994                                cleanup_ncci_data(plci, ncci);
 995                                dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
 996                                                ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
 997                                a->ch_ncci[a->ncci_ch[ncci]] = 0;
 998                                if (!preserve_ncci)
 999                                {
1000                                        a->ncci_ch[ncci] = 0;
1001                                        a->ncci_plci[ncci] = 0;
1002                                        a->ncci_state[ncci] = IDLE;
1003                                        a->ncci_next[ncci] = 0;
1004                                }
1005                        }
1006                }
1007                if (!preserve_ncci)
1008                        plci->ncci_ring_list = 0;
1009        }
1010}
1011
1012
1013/*------------------------------------------------------------------*/
1014/* PLCI remove function                                             */
1015/*------------------------------------------------------------------*/
1016
1017static void plci_free_msg_in_queue(PLCI *plci)
1018{
1019        word i;
1020
1021        if (plci->appl)
1022        {
1023                i = plci->msg_in_read_pos;
1024                while (i != plci->msg_in_write_pos)
1025                {
1026                        if (i == plci->msg_in_wrap_pos)
1027                                i = 0;
1028                        if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1029                        {
1030
1031                                TransmitBufferFree(plci->appl,
1032                                                   (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1033
1034                        }
1035
1036                        i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1037                              MSG_IN_OVERHEAD + 3) & 0xfffc;
1038
1039                }
1040        }
1041        plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1042        plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1043        plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1044}
1045
1046
1047static void plci_remove(PLCI *plci)
1048{
1049
1050        if (!plci) {
1051                dbug(1, dprintf("plci_remove(no plci)"));
1052                return;
1053        }
1054        init_internal_command_queue(plci);
1055        dbug(1, dprintf("plci_remove(%x,tel=%x)", plci->Id, plci->tel));
1056        if (plci_remove_check(plci))
1057        {
1058                return;
1059        }
1060        if (plci->Sig.Id == 0xff)
1061        {
1062                dbug(1, dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1063                if (plci->NL.Id && !plci->nl_remove_id)
1064                {
1065                        nl_req_ncci(plci, REMOVE, 0);
1066                        send_req(plci);
1067                }
1068        }
1069        else
1070        {
1071                if (!plci->sig_remove_id
1072                    && (plci->Sig.Id
1073                        || (plci->req_in != plci->req_out)
1074                        || (plci->nl_req || plci->sig_req)))
1075                {
1076                        sig_req(plci, HANGUP, 0);
1077                        send_req(plci);
1078                }
1079        }
1080        ncci_remove(plci, 0, false);
1081        plci_free_msg_in_queue(plci);
1082
1083        plci->channels = 0;
1084        plci->appl = NULL;
1085        if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1086                plci->State = OUTG_DIS_PENDING;
1087}
1088
1089/*------------------------------------------------------------------*/
1090/* Application Group function helpers                               */
1091/*------------------------------------------------------------------*/
1092
1093static void set_group_ind_mask(PLCI *plci)
1094{
1095        word i;
1096
1097        for (i = 0; i < C_IND_MASK_DWORDS; i++)
1098                plci->group_optimization_mask_table[i] = 0xffffffffL;
1099}
1100
1101static void clear_group_ind_mask_bit(PLCI *plci, word b)
1102{
1103        plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1104}
1105
1106static byte test_group_ind_mask_bit(PLCI *plci, word b)
1107{
1108        return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1109}
1110
1111/*------------------------------------------------------------------*/
1112/* c_ind_mask operations for arbitrary MAX_APPL                     */
1113/*------------------------------------------------------------------*/
1114
1115static void clear_c_ind_mask(PLCI *plci)
1116{
1117        word i;
1118
1119        for (i = 0; i < C_IND_MASK_DWORDS; i++)
1120                plci->c_ind_mask_table[i] = 0;
1121}
1122
1123static byte c_ind_mask_empty(PLCI *plci)
1124{
1125        word i;
1126
1127        i = 0;
1128        while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1129                i++;
1130        return (i == C_IND_MASK_DWORDS);
1131}
1132
1133static void set_c_ind_mask_bit(PLCI *plci, word b)
1134{
1135        plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1136}
1137
1138static void clear_c_ind_mask_bit(PLCI *plci, word b)
1139{
1140        plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1141}
1142
1143static byte test_c_ind_mask_bit(PLCI *plci, word b)
1144{
1145        return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1146}
1147
1148static void dump_c_ind_mask(PLCI *plci)
1149{
1150        static char hex_digit_table[0x10] =
1151                {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
1152        word i, j, k;
1153        dword d;
1154        char *p;
1155        char buf[40];
1156
1157        for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1158        {
1159                p = buf + 36;
1160                *p = '\0';
1161                for (j = 0; j < 4; j++)
1162                {
1163                        if (i + j < C_IND_MASK_DWORDS)
1164                        {
1165                                d = plci->c_ind_mask_table[i + j];
1166                                for (k = 0; k < 8; k++)
1167                                {
1168                                        *(--p) = hex_digit_table[d & 0xf];
1169                                        d >>= 4;
1170                                }
1171                        }
1172                        else if (i != 0)
1173                        {
1174                                for (k = 0; k < 8; k++)
1175                                        *(--p) = ' ';
1176                        }
1177                        *(--p) = ' ';
1178                }
1179                dbug(1, dprintf("c_ind_mask =%s", (char *) p));
1180        }
1181}
1182
1183
1184
1185
1186
1187#define dump_plcis(a)
1188
1189
1190
1191/*------------------------------------------------------------------*/
1192/* translation function for each message                            */
1193/*------------------------------------------------------------------*/
1194
1195static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1196                        PLCI *plci, APPL *appl, API_PARSE *parms)
1197{
1198        word ch;
1199        word i;
1200        word Info;
1201        byte LinkLayer;
1202        API_PARSE *ai;
1203        API_PARSE *bp;
1204        API_PARSE ai_parms[5];
1205        word channel = 0;
1206        dword ch_mask;
1207        byte m;
1208        static byte esc_chi[35] = {0x02, 0x18, 0x01};
1209        static byte lli[2] = {0x01, 0x00};
1210        byte noCh = 0;
1211        word dir = 0;
1212        byte *p_chi = "";
1213
1214        for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1215
1216        dbug(1, dprintf("connect_req(%d)", parms->length));
1217        Info = _WRONG_IDENTIFIER;
1218        if (a)
1219        {
1220                if (a->adapter_disabled)
1221                {
1222                        dbug(1, dprintf("adapter disabled"));
1223                        Id = ((word)1 << 8) | a->Id;
1224                        sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
1225                        sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1226                        return false;
1227                }
1228                Info = _OUT_OF_PLCI;
1229                if ((i = get_plci(a)))
1230                {
1231                        Info = 0;
1232                        plci = &a->plci[i - 1];
1233                        plci->appl = appl;
1234                        plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1235                        /* check 'external controller' bit for codec support */
1236                        if (Id & EXT_CONTROLLER)
1237                        {
1238                                if (AdvCodecSupport(a, plci, appl, 0))
1239                                {
1240                                        plci->Id = 0;
1241                                        sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1242                                        return 2;
1243                                }
1244                        }
1245                        ai = &parms[9];
1246                        bp = &parms[5];
1247                        ch = 0;
1248                        if (bp->length)LinkLayer = bp->info[3];
1249                        else LinkLayer = 0;
1250                        if (ai->length)
1251                        {
1252                                ch = 0xffff;
1253                                if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1254                                {
1255                                        ch = 0;
1256                                        if (ai_parms[0].length)
1257                                        {
1258                                                ch = GET_WORD(ai_parms[0].info + 1);
1259                                                if (ch > 4) ch = 0; /* safety -> ignore ChannelID */
1260                                                if (ch == 4) /* explizit CHI in message */
1261                                                {
1262                                                        /* check length of B-CH struct */
1263                                                        if ((ai_parms[0].info)[3] >= 1)
1264                                                        {
1265                                                                if ((ai_parms[0].info)[4] == CHI)
1266                                                                {
1267                                                                        p_chi = &((ai_parms[0].info)[5]);
1268                                                                }
1269                                                                else
1270                                                                {
1271                                                                        p_chi = &((ai_parms[0].info)[3]);
1272                                                                }
1273                                                                if (p_chi[0] > 35) /* check length of channel ID */
1274                                                                {
1275                                                                        Info = _WRONG_MESSAGE_FORMAT;
1276                                                                }
1277                                                        }
1278                                                        else Info = _WRONG_MESSAGE_FORMAT;
1279                                                }
1280
1281                                                if (ch == 3 && ai_parms[0].length >= 7 && ai_parms[0].length <= 36)
1282                                                {
1283                                                        dir = GET_WORD(ai_parms[0].info + 3);
1284                                                        ch_mask = 0;
1285                                                        m = 0x3f;
1286                                                        for (i = 0; i + 5 <= ai_parms[0].length; i++)
1287                                                        {
1288                                                                if (ai_parms[0].info[i + 5] != 0)
1289                                                                {
1290                                                                        if ((ai_parms[0].info[i + 5] | m) != 0xff)
1291                                                                                Info = _WRONG_MESSAGE_FORMAT;
1292                                                                        else
1293                                                                        {
1294                                                                                if (ch_mask == 0)
1295                                                                                        channel = i;
1296                                                                                ch_mask |= 1L << i;
1297                                                                        }
1298                                                                }
1299                                                                m = 0;
1300                                                        }
1301                                                        if (ch_mask == 0)
1302                                                                Info = _WRONG_MESSAGE_FORMAT;
1303                                                        if (!Info)
1304                                                        {
1305                                                                if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1306                                                                {
1307                                                                        esc_chi[0] = (byte)(ai_parms[0].length - 2);
1308                                                                        for (i = 0; i + 5 <= ai_parms[0].length; i++)
1309                                                                                esc_chi[i + 3] = ai_parms[0].info[i + 5];
1310                                                                }
1311                                                                else
1312                                                                        esc_chi[0] = 2;
1313                                                                esc_chi[2] = (byte)channel;
1314                                                                plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1315                                                                add_p(plci, LLI, lli);
1316                                                                add_p(plci, ESC, esc_chi);
1317                                                                plci->State = LOCAL_CONNECT;
1318                                                                if (!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
1319                                                        }
1320                                                }
1321                                        }
1322                                }
1323                                else  Info = _WRONG_MESSAGE_FORMAT;
1324                        }
1325
1326                        dbug(1, dprintf("ch=%x,dir=%x,p_ch=%d", ch, dir, channel));
1327                        plci->command = _CONNECT_R;
1328                        plci->number = Number;
1329                        /* x.31 or D-ch free SAPI in LinkLayer? */
1330                        if (ch == 1 && LinkLayer != 3 && LinkLayer != 12) noCh = true;
1331                        if ((ch == 0 || ch == 2 || noCh || ch == 3 || ch == 4) && !Info)
1332                        {
1333                                /* B-channel used for B3 connections (ch==0), or no B channel    */
1334                                /* is used (ch==2) or perm. connection (3) is used  do a CALL    */
1335                                if (noCh) Info = add_b1(plci, &parms[5], 2, 0);    /* no resource    */
1336                                else     Info = add_b1(plci, &parms[5], ch, 0);
1337                                add_s(plci, OAD, &parms[2]);
1338                                add_s(plci, OSA, &parms[4]);
1339                                add_s(plci, BC, &parms[6]);
1340                                add_s(plci, LLC, &parms[7]);
1341                                add_s(plci, HLC, &parms[8]);
1342                                if (a->Info_Mask[appl->Id - 1] & 0x200)
1343                                {
1344                                        /* early B3 connect (CIP mask bit 9) no release after a disc */
1345                                        add_p(plci, LLI, "\x01\x01");
1346                                }
1347                                if (GET_WORD(parms[0].info) < 29) {
1348                                        add_p(plci, BC, cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1349                                        add_p(plci, HLC, cip_hlc[GET_WORD(parms[0].info)]);
1350                                }
1351                                add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1352                                sig_req(plci, ASSIGN, DSIG_ID);
1353                        }
1354                        else if (ch == 1) {
1355
1356                                /* D-Channel used for B3 connections */
1357                                plci->Sig.Id = 0xff;
1358                                Info = 0;
1359                        }
1360
1361                        if (!Info && ch != 2 && !noCh) {
1362                                Info = add_b23(plci, &parms[5]);
1363                                if (!Info) {
1364                                        if (!(plci->tel && !plci->adv_nl))nl_req_ncci(plci, ASSIGN, 0);
1365                                }
1366                        }
1367
1368                        if (!Info)
1369                        {
1370                                if (ch == 0 || ch == 2 || ch == 3 || noCh || ch == 4)
1371                                {
1372                                        if (plci->spoofed_msg == SPOOFING_REQUIRED)
1373                                        {
1374                                                api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1375                                                plci->spoofed_msg = CALL_REQ;
1376                                                plci->internal_command = BLOCK_PLCI;
1377                                                plci->command = 0;
1378                                                dbug(1, dprintf("Spoof"));
1379                                                send_req(plci);
1380                                                return false;
1381                                        }
1382                                        if (ch == 4)add_p(plci, CHI, p_chi);
1383                                        add_s(plci, CPN, &parms[1]);
1384                                        add_s(plci, DSA, &parms[3]);
1385                                        if (noCh) add_p(plci, ESC, "\x02\x18\xfd");  /* D-channel, no B-L3 */
1386                                        add_ai(plci, &parms[9]);
1387                                        if (!dir)sig_req(plci, CALL_REQ, 0);
1388                                        else
1389                                        {
1390                                                plci->command = PERM_LIST_REQ;
1391                                                plci->appl = appl;
1392                                                sig_req(plci, LISTEN_REQ, 0);
1393                                                send_req(plci);
1394                                                return false;
1395                                        }
1396                                }
1397                                send_req(plci);
1398                                return false;
1399                        }
1400                        plci->Id = 0;
1401                }
1402        }
1403        sendf(appl,
1404              _CONNECT_R | CONFIRM,
1405              Id,
1406              Number,
1407              "w", Info);
1408        return 2;
1409}
1410
1411static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1412                        PLCI *plci, APPL *appl, API_PARSE *parms)
1413{
1414        word i, Info;
1415        word Reject;
1416        static byte cau_t[] = {0, 0, 0x90, 0x91, 0xac, 0x9d, 0x86, 0xd8, 0x9b};
1417        static byte esc_t[] = {0x03, 0x08, 0x00, 0x00};
1418        API_PARSE *ai;
1419        API_PARSE ai_parms[5];
1420        word ch = 0;
1421
1422        if (!plci) {
1423                dbug(1, dprintf("connect_res(no plci)"));
1424                return 0;  /* no plci, no send */
1425        }
1426
1427        dbug(1, dprintf("connect_res(State=0x%x)", plci->State));
1428        for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1429        ai = &parms[5];
1430        dbug(1, dprintf("ai->length=%d", ai->length));
1431
1432        if (ai->length)
1433        {
1434                if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1435                {
1436                        dbug(1, dprintf("ai_parms[0].length=%d/0x%x", ai_parms[0].length, GET_WORD(ai_parms[0].info + 1)));
1437                        ch = 0;
1438                        if (ai_parms[0].length)
1439                        {
1440                                ch = GET_WORD(ai_parms[0].info + 1);
1441                                dbug(1, dprintf("BCH-I=0x%x", ch));
1442                        }
1443                }
1444        }
1445
1446        if (plci->State == INC_CON_CONNECTED_ALERT)
1447        {
1448                dbug(1, dprintf("Connected Alert Call_Res"));
1449                if (a->Info_Mask[appl->Id - 1] & 0x200)
1450                {
1451                        /* early B3 connect (CIP mask bit 9) no release after a disc */
1452                        add_p(plci, LLI, "\x01\x01");
1453                }
1454                add_s(plci, CONN_NR, &parms[2]);
1455                add_s(plci, LLC, &parms[4]);
1456                add_ai(plci, &parms[5]);
1457                plci->State = INC_CON_ACCEPT;
1458                sig_req(plci, CALL_RES, 0);
1459                return 1;
1460        }
1461        else if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT) {
1462                clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1463                dump_c_ind_mask(plci);
1464                Reject = GET_WORD(parms[0].info);
1465                dbug(1, dprintf("Reject=0x%x", Reject));
1466                if (Reject)
1467                {
1468                        if (c_ind_mask_empty(plci))
1469                        {
1470                                if ((Reject & 0xff00) == 0x3400)
1471                                {
1472                                        esc_t[2] = ((byte)(Reject & 0x00ff)) | 0x80;
1473                                        add_p(plci, ESC, esc_t);
1474                                        add_ai(plci, &parms[5]);
1475                                        sig_req(plci, REJECT, 0);
1476                                }
1477                                else if (Reject == 1 || Reject >= 9)
1478                                {
1479                                        add_ai(plci, &parms[5]);
1480                                        sig_req(plci, HANGUP, 0);
1481                                }
1482                                else
1483                                {
1484                                        esc_t[2] = cau_t[(Reject&0x000f)];
1485                                        add_p(plci, ESC, esc_t);
1486                                        add_ai(plci, &parms[5]);
1487                                        sig_req(plci, REJECT, 0);
1488                                }
1489                                plci->appl = appl;
1490                        }
1491                        else
1492                        {
1493                                sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1494                        }
1495                }
1496                else {
1497                        plci->appl = appl;
1498                        if (Id & EXT_CONTROLLER) {
1499                                if (AdvCodecSupport(a, plci, appl, 0)) {
1500                                        dbug(1, dprintf("connect_res(error from AdvCodecSupport)"));
1501                                        sig_req(plci, HANGUP, 0);
1502                                        return 1;
1503                                }
1504                                if (plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1505                                {
1506                                        Info = add_b23(plci, &parms[1]);
1507                                        if (Info)
1508                                        {
1509                                                dbug(1, dprintf("connect_res(error from add_b23)"));
1510                                                sig_req(plci, HANGUP, 0);
1511                                                return 1;
1512                                        }
1513                                        if (plci->adv_nl)
1514                                        {
1515                                                nl_req_ncci(plci, ASSIGN, 0);
1516                                        }
1517                                }
1518                        }
1519                        else
1520                        {
1521                                plci->tel = 0;
1522                                if (ch != 2)
1523                                {
1524                                        Info = add_b23(plci, &parms[1]);
1525                                        if (Info)
1526                                        {
1527                                                dbug(1, dprintf("connect_res(error from add_b23 2)"));
1528                                                sig_req(plci, HANGUP, 0);
1529                                                return 1;
1530                                        }
1531                                }
1532                                nl_req_ncci(plci, ASSIGN, 0);
1533                        }
1534
1535                        if (plci->spoofed_msg == SPOOFING_REQUIRED)
1536                        {
1537                                api_save_msg(parms, "wsssss", &plci->saved_msg);
1538                                plci->spoofed_msg = CALL_RES;
1539                                plci->internal_command = BLOCK_PLCI;
1540                                plci->command = 0;
1541                                dbug(1, dprintf("Spoof"));
1542                        }
1543                        else
1544                        {
1545                                add_b1(plci, &parms[1], ch, plci->B1_facilities);
1546                                if (a->Info_Mask[appl->Id - 1] & 0x200)
1547                                {
1548                                        /* early B3 connect (CIP mask bit 9) no release after a disc */
1549                                        add_p(plci, LLI, "\x01\x01");
1550                                }
1551                                add_s(plci, CONN_NR, &parms[2]);
1552                                add_s(plci, LLC, &parms[4]);
1553                                add_ai(plci, &parms[5]);
1554                                plci->State = INC_CON_ACCEPT;
1555                                sig_req(plci, CALL_RES, 0);
1556                        }
1557
1558                        for (i = 0; i < max_appl; i++) {
1559                                if (test_c_ind_mask_bit(plci, i)) {
1560                                        sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1561                                }
1562                        }
1563                }
1564        }
1565        return 1;
1566}
1567
1568static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1569                          PLCI *plci, APPL *appl, API_PARSE *msg)
1570{
1571        dbug(1, dprintf("connect_a_res"));
1572        return false;
1573}
1574
1575static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1576                           PLCI *plci, APPL *appl, API_PARSE *msg)
1577{
1578        word Info;
1579        word i;
1580
1581        dbug(1, dprintf("disconnect_req"));
1582
1583        Info = _WRONG_IDENTIFIER;
1584
1585        if (plci)
1586        {
1587                if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
1588                {
1589                        clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1590                        plci->appl = appl;
1591                        for (i = 0; i < max_appl; i++)
1592                        {
1593                                if (test_c_ind_mask_bit(plci, i))
1594                                        sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1595                        }
1596                        plci->State = OUTG_DIS_PENDING;
1597                }
1598                if (plci->Sig.Id && plci->appl)
1599                {
1600                        Info = 0;
1601                        if (plci->Sig.Id != 0xff)
1602                        {
1603                                if (plci->State != INC_DIS_PENDING)
1604                                {
1605                                        add_ai(plci, &msg[0]);
1606                                        sig_req(plci, HANGUP, 0);
1607                                        plci->State = OUTG_DIS_PENDING;
1608                                        return 1;
1609                                }
1610                        }
1611                        else
1612                        {
1613                                if (plci->NL.Id && !plci->nl_remove_id)
1614                                {
1615                                        mixer_remove(plci);
1616                                        nl_req_ncci(plci, REMOVE, 0);
1617                                        sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
1618                                        sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1619                                        plci->State = INC_DIS_PENDING;
1620                                }
1621                                return 1;
1622                        }
1623                }
1624        }
1625
1626        if (!appl)  return false;
1627        sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", Info);
1628        return false;
1629}
1630
1631static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1632                           PLCI *plci, APPL *appl, API_PARSE *msg)
1633{
1634        dbug(1, dprintf("disconnect_res"));
1635        if (plci)
1636        {
1637                /* clear ind mask bit, just in case of collsion of          */
1638                /* DISCONNECT_IND and CONNECT_RES                           */
1639                clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1640                ncci_free_receive_buffers(plci, 0);
1641                if (plci_remove_check(plci))
1642                {
1643                        return 0;
1644                }
1645                if (plci->State == INC_DIS_PENDING
1646                    || plci->State == SUSPENDING) {
1647                        if (c_ind_mask_empty(plci)) {
1648                                if (plci->State != SUSPENDING) plci->State = IDLE;
1649                                dbug(1, dprintf("chs=%d", plci->channels));
1650                                if (!plci->channels) {
1651                                        plci_remove(plci);
1652                                }
1653                        }
1654                }
1655        }
1656        return 0;
1657}
1658
1659static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1660                       PLCI *plci, APPL *appl, API_PARSE *parms)
1661{
1662        word Info;
1663        byte i;
1664
1665        dbug(1, dprintf("listen_req(Appl=0x%x)", appl->Id));
1666
1667        Info = _WRONG_IDENTIFIER;
1668        if (a) {
1669                Info = 0;
1670                a->Info_Mask[appl->Id - 1] = GET_DWORD(parms[0].info);
1671                a->CIP_Mask[appl->Id - 1] = GET_DWORD(parms[1].info);
1672                dbug(1, dprintf("CIP_MASK=0x%lx", GET_DWORD(parms[1].info)));
1673                if (a->Info_Mask[appl->Id - 1] & 0x200) { /* early B3 connect provides */
1674                        a->Info_Mask[appl->Id - 1] |=  0x10;   /* call progression infos    */
1675                }
1676
1677                /* check if external controller listen and switch listen on or off*/
1678                if (Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)) {
1679                        if (a->profile.Global_Options & ON_BOARD_CODEC) {
1680                                dummy_plci.State = IDLE;
1681                                a->codec_listen[appl->Id - 1] = &dummy_plci;
1682                                a->TelOAD[0] = (byte)(parms[3].length);
1683                                for (i = 1; parms[3].length >= i && i < 22; i++) {
1684                                        a->TelOAD[i] = parms[3].info[i];
1685                                }
1686                                a->TelOAD[i] = 0;
1687                                a->TelOSA[0] = (byte)(parms[4].length);
1688                                for (i = 1; parms[4].length >= i && i < 22; i++) {
1689                                        a->TelOSA[i] = parms[4].info[i];
1690                                }
1691                                a->TelOSA[i] = 0;
1692                        }
1693                        else Info = 0x2002; /* wrong controller, codec not supported */
1694                }
1695                else{               /* clear listen */
1696                        a->codec_listen[appl->Id - 1] = (PLCI *)0;
1697                }
1698        }
1699        sendf(appl,
1700              _LISTEN_R | CONFIRM,
1701              Id,
1702              Number,
1703              "w", Info);
1704
1705        if (a) listen_check(a);
1706        return false;
1707}
1708
1709static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1710                     PLCI *plci, APPL *appl, API_PARSE *msg)
1711{
1712        word i;
1713        API_PARSE *ai;
1714        PLCI *rc_plci = NULL;
1715        API_PARSE ai_parms[5];
1716        word Info = 0;
1717
1718        dbug(1, dprintf("info_req"));
1719        for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1720
1721        ai = &msg[1];
1722
1723        if (ai->length)
1724        {
1725                if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1726                {
1727                        dbug(1, dprintf("AddInfo wrong"));
1728                        Info = _WRONG_MESSAGE_FORMAT;
1729                }
1730        }
1731        if (!a) Info = _WRONG_STATE;
1732
1733        if (!Info && plci)
1734        {                /* no fac, with CPN, or KEY */
1735                rc_plci = plci;
1736                if (!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length))
1737                {
1738                        /* overlap sending option */
1739                        dbug(1, dprintf("OvlSnd"));
1740                        add_s(plci, CPN, &msg[0]);
1741                        add_s(plci, KEY, &ai_parms[1]);
1742                        sig_req(plci, INFO_REQ, 0);
1743                        send_req(plci);
1744                        return false;
1745                }
1746
1747                if (plci->State && ai_parms[2].length)
1748                {
1749                        /* User_Info option */
1750                        dbug(1, dprintf("UUI"));
1751                        add_s(plci, UUI, &ai_parms[2]);
1752                        sig_req(plci, USER_DATA, 0);
1753                }
1754                else if (plci->State && ai_parms[3].length)
1755                {
1756                        /* Facility option */
1757                        dbug(1, dprintf("FAC"));
1758                        add_s(plci, CPN, &msg[0]);
1759                        add_ai(plci, &msg[1]);
1760                        sig_req(plci, FACILITY_REQ, 0);
1761                }
1762                else
1763                {
1764                        Info = _WRONG_STATE;
1765                }
1766        }
1767        else if ((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1768        {
1769                /* NCR_Facility option -> send UUI and Keypad too */
1770                dbug(1, dprintf("NCR_FAC"));
1771                if ((i = get_plci(a)))
1772                {
1773                        rc_plci = &a->plci[i - 1];
1774                        appl->NullCREnable = true;
1775                        rc_plci->internal_command = C_NCR_FAC_REQ;
1776                        rc_plci->appl = appl;
1777                        add_p(rc_plci, CAI, "\x01\x80");
1778                        add_p(rc_plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1779                        sig_req(rc_plci, ASSIGN, DSIG_ID);
1780                        send_req(rc_plci);
1781                }
1782                else
1783                {
1784                        Info = _OUT_OF_PLCI;
1785                }
1786
1787                if (!Info)
1788                {
1789                        add_s(rc_plci, CPN, &msg[0]);
1790                        add_ai(rc_plci, &msg[1]);
1791                        sig_req(rc_plci, NCR_FACILITY, 0);
1792                        send_req(rc_plci);
1793                        return false;
1794                        /* for application controlled supplementary services    */
1795                }
1796        }
1797
1798        if (!rc_plci)
1799        {
1800                Info = _WRONG_MESSAGE_FORMAT;
1801        }
1802
1803        if (!Info)
1804        {
1805                send_req(rc_plci);
1806        }
1807        else
1808        {  /* appl is not assigned to a PLCI or error condition */
1809                dbug(1, dprintf("localInfoCon"));
1810                sendf(appl,
1811                      _INFO_R | CONFIRM,
1812                      Id,
1813                      Number,
1814                      "w", Info);
1815        }
1816        return false;
1817}
1818
1819static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1820                     PLCI *plci, APPL *appl, API_PARSE *msg)
1821{
1822        dbug(1, dprintf("info_res"));
1823        return false;
1824}
1825
1826static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1827                      PLCI *plci, APPL *appl, API_PARSE *msg)
1828{
1829        word Info;
1830        byte ret;
1831
1832        dbug(1, dprintf("alert_req"));
1833
1834        Info = _WRONG_IDENTIFIER;
1835        ret = false;
1836        if (plci) {
1837                Info = _ALERT_IGNORED;
1838                if (plci->State != INC_CON_ALERT) {
1839                        Info = _WRONG_STATE;
1840                        if (plci->State == INC_CON_PENDING) {
1841                                Info = 0;
1842                                plci->State = INC_CON_ALERT;
1843                                add_ai(plci, &msg[0]);
1844                                sig_req(plci, CALL_ALERT, 0);
1845                                ret = 1;
1846                        }
1847                }
1848        }
1849        sendf(appl,
1850              _ALERT_R | CONFIRM,
1851              Id,
1852              Number,
1853              "w", Info);
1854        return ret;
1855}
1856
1857static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1858                         PLCI *plci, APPL *appl, API_PARSE *msg)
1859{
1860        word Info = 0;
1861        word i    = 0;
1862
1863        word selector;
1864        word SSreq;
1865        long relatedPLCIvalue;
1866        DIVA_CAPI_ADAPTER *relatedadapter;
1867        byte *SSparms  = "";
1868        byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1869        byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1870        API_PARSE *parms;
1871        API_PARSE ss_parms[11];
1872        PLCI *rplci;
1873        byte cai[15];
1874        dword d;
1875        API_PARSE dummy;
1876
1877        dbug(1, dprintf("facility_req"));
1878        for (i = 0; i < 9; i++) ss_parms[i].length = 0;
1879
1880        parms = &msg[1];
1881
1882        if (!a)
1883        {
1884                dbug(1, dprintf("wrong Ctrl"));
1885                Info = _WRONG_IDENTIFIER;
1886        }
1887
1888        selector = GET_WORD(msg[0].info);
1889
1890        if (!Info)
1891        {
1892                switch (selector)
1893                {
1894                case SELECTOR_HANDSET:
1895                        Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1896                        break;
1897
1898                case SELECTOR_SU_SERV:
1899                        if (!msg[1].length)
1900                        {
1901                                Info = _WRONG_MESSAGE_FORMAT;
1902                                break;
1903                        }
1904                        SSreq = GET_WORD(&(msg[1].info[1]));
1905                        PUT_WORD(&RCparms[1], SSreq);
1906                        SSparms = RCparms;
1907                        switch (SSreq)
1908                        {
1909                        case S_GET_SUPPORTED_SERVICES:
1910                                if ((i = get_plci(a)))
1911                                {
1912                                        rplci = &a->plci[i - 1];
1913                                        rplci->appl = appl;
1914                                        add_p(rplci, CAI, "\x01\x80");
1915                                        add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1916                                        sig_req(rplci, ASSIGN, DSIG_ID);
1917                                        send_req(rplci);
1918                                }
1919                                else
1920                                {
1921                                        PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1922                                        SSparms = (byte *)SSstruct;
1923                                        break;
1924                                }
1925                                rplci->internal_command = GETSERV_REQ_PEND;
1926                                rplci->number = Number;
1927                                rplci->appl = appl;
1928                                sig_req(rplci, S_SUPPORTED, 0);
1929                                send_req(rplci);
1930                                return false;
1931                                break;
1932
1933                        case S_LISTEN:
1934                                if (parms->length == 7)
1935                                {
1936                                        if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1937                                        {
1938                                                dbug(1, dprintf("format wrong"));
1939                                                Info = _WRONG_MESSAGE_FORMAT;
1940                                                break;
1941                                        }
1942                                }
1943                                else
1944                                {
1945                                        Info = _WRONG_MESSAGE_FORMAT;
1946                                        break;
1947                                }
1948                                a->Notification_Mask[appl->Id - 1] = GET_DWORD(ss_parms[2].info);
1949                                if (a->Notification_Mask[appl->Id - 1] & SMASK_MWI) /* MWI active? */
1950                                {
1951                                        if ((i = get_plci(a)))
1952                                        {
1953                                                rplci = &a->plci[i - 1];
1954                                                rplci->appl = appl;
1955                                                add_p(rplci, CAI, "\x01\x80");
1956                                                add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1957                                                sig_req(rplci, ASSIGN, DSIG_ID);
1958                                                send_req(rplci);
1959                                        }
1960                                        else
1961                                        {
1962                                                break;
1963                                        }
1964                                        rplci->internal_command = GET_MWI_STATE;
1965                                        rplci->number = Number;
1966                                        sig_req(rplci, MWI_POLL, 0);
1967                                        send_req(rplci);
1968                                }
1969                                break;
1970
1971                        case S_HOLD:
1972                                api_parse(&parms->info[1], (word)parms->length, "ws", ss_parms);
1973                                if (plci && plci->State && plci->SuppState == IDLE)
1974                                {
1975                                        plci->SuppState = HOLD_REQUEST;
1976                                        plci->command = C_HOLD_REQ;
1977                                        add_s(plci, CAI, &ss_parms[1]);
1978                                        sig_req(plci, CALL_HOLD, 0);
1979                                        send_req(plci);
1980                                        return false;
1981                                }
1982                                else Info = 0x3010;                    /* wrong state           */
1983                                break;
1984                        case S_RETRIEVE:
1985                                if (plci && plci->State && plci->SuppState == CALL_HELD)
1986                                {
1987                                        if (Id & EXT_CONTROLLER)
1988                                        {
1989                                                if (AdvCodecSupport(a, plci, appl, 0))
1990                                                {
1991                                                        Info = 0x3010;                    /* wrong state           */
1992                                                        break;
1993                                                }
1994                                        }
1995                                        else plci->tel = 0;
1996
1997                                        plci->SuppState = RETRIEVE_REQUEST;
1998                                        plci->command = C_RETRIEVE_REQ;
1999                                        if (plci->spoofed_msg == SPOOFING_REQUIRED)
2000                                        {
2001                                                plci->spoofed_msg = CALL_RETRIEVE;
2002                                                plci->internal_command = BLOCK_PLCI;
2003                                                plci->command = 0;
2004                                                dbug(1, dprintf("Spoof"));
2005                                                return false;
2006                                        }
2007                                        else
2008                                        {
2009                                                sig_req(plci, CALL_RETRIEVE, 0);
2010                                                send_req(plci);
2011                                                return false;
2012                                        }
2013                                }
2014                                else Info = 0x3010;                    /* wrong state           */
2015                                break;
2016                        case S_SUSPEND:
2017                                if (parms->length)
2018                                {
2019                                        if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2020                                        {
2021                                                dbug(1, dprintf("format wrong"));
2022                                                Info = _WRONG_MESSAGE_FORMAT;
2023                                                break;
2024                                        }
2025                                }
2026                                if (plci && plci->State)
2027                                {
2028                                        add_s(plci, CAI, &ss_parms[2]);
2029                                        plci->command = SUSPEND_REQ;
2030                                        sig_req(plci, SUSPEND, 0);
2031                                        plci->State = SUSPENDING;
2032                                        send_req(plci);
2033                                }
2034                                else Info = 0x3010;                    /* wrong state           */
2035                                break;
2036
2037                        case S_RESUME:
2038                                if (!(i = get_plci(a)))
2039                                {
2040                                        Info = _OUT_OF_PLCI;
2041                                        break;
2042                                }
2043                                rplci = &a->plci[i - 1];
2044                                rplci->appl = appl;
2045                                rplci->number = Number;
2046                                rplci->tel = 0;
2047                                rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2048                                /* check 'external controller' bit for codec support */
2049                                if (Id & EXT_CONTROLLER)
2050                                {
2051                                        if (AdvCodecSupport(a, rplci, appl, 0))
2052                                        {
2053                                                rplci->Id = 0;
2054                                                Info = 0x300A;
2055                                                break;
2056                                        }
2057                                }
2058                                if (parms->length)
2059                                {
2060                                        if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2061                                        {
2062                                                dbug(1, dprintf("format wrong"));
2063                                                rplci->Id = 0;
2064                                                Info = _WRONG_MESSAGE_FORMAT;
2065                                                break;
2066                                        }
2067                                }
2068                                dummy.length = 0;
2069                                dummy.info = "\x00";
2070                                add_b1(rplci, &dummy, 0, 0);
2071                                if (a->Info_Mask[appl->Id - 1] & 0x200)
2072                                {
2073                                        /* early B3 connect (CIP mask bit 9) no release after a disc */
2074                                        add_p(rplci, LLI, "\x01\x01");
2075                                }
2076                                add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2077                                sig_req(rplci, ASSIGN, DSIG_ID);
2078                                send_req(rplci);
2079                                add_s(rplci, CAI, &ss_parms[2]);
2080                                rplci->command = RESUME_REQ;
2081                                sig_req(rplci, RESUME, 0);
2082                                rplci->State = RESUMING;
2083                                send_req(rplci);
2084                                break;
2085
2086                        case S_CONF_BEGIN: /* Request */
2087                        case S_CONF_DROP:
2088                        case S_CONF_ISOLATE:
2089                        case S_CONF_REATTACH:
2090                                if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2091                                {
2092                                        dbug(1, dprintf("format wrong"));
2093                                        Info = _WRONG_MESSAGE_FORMAT;
2094                                        break;
2095                                }
2096                                if (plci && plci->State && ((plci->SuppState == IDLE) || (plci->SuppState == CALL_HELD)))
2097                                {
2098                                        d = GET_DWORD(ss_parms[2].info);
2099                                        if (d >= 0x80)
2100                                        {
2101                                                dbug(1, dprintf("format wrong"));
2102                                                Info = _WRONG_MESSAGE_FORMAT;
2103                                                break;
2104                                        }
2105                                        plci->ptyState = (byte)SSreq;
2106                                        plci->command = 0;
2107                                        cai[0] = 2;
2108                                        switch (SSreq)
2109                                        {
2110                                        case S_CONF_BEGIN:
2111                                                cai[1] = CONF_BEGIN;
2112                                                plci->internal_command = CONF_BEGIN_REQ_PEND;
2113                                                break;
2114                                        case S_CONF_DROP:
2115                                                cai[1] = CONF_DROP;
2116                                                plci->internal_command = CONF_DROP_REQ_PEND;
2117                                                break;
2118                                        case S_CONF_ISOLATE:
2119                                                cai[1] = CONF_ISOLATE;
2120                                                plci->internal_command = CONF_ISOLATE_REQ_PEND;
2121                                                break;
2122                                        case S_CONF_REATTACH:
2123                                                cai[1] = CONF_REATTACH;
2124                                                plci->internal_command = CONF_REATTACH_REQ_PEND;
2125                                                break;
2126                                        }
2127                                        cai[2] = (byte)d; /* Conference Size resp. PartyId */
2128                                        add_p(plci, CAI, cai);
2129                                        sig_req(plci, S_SERVICE, 0);
2130                                        send_req(plci);
2131                                        return false;
2132                                }
2133                                else Info = 0x3010;                    /* wrong state           */
2134                                break;
2135
2136                        case S_ECT:
2137                        case S_3PTY_BEGIN:
2138                        case S_3PTY_END:
2139                        case S_CONF_ADD:
2140                                if (parms->length == 7)
2141                                {
2142                                        if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2143                                        {
2144                                                dbug(1, dprintf("format wrong"));
2145                                                Info = _WRONG_MESSAGE_FORMAT;
2146                                                break;
2147                                        }
2148                                }
2149                                else if (parms->length == 8) /* workaround for the T-View-S */
2150                                {
2151                                        if (api_parse(&parms->info[1], (word)parms->length, "wbdb", ss_parms))
2152                                        {
2153                                                dbug(1, dprintf("format wrong"));
2154                                                Info = _WRONG_MESSAGE_FORMAT;
2155                                                break;
2156                                        }
2157                                }
2158                                else
2159                                {
2160                                        Info = _WRONG_MESSAGE_FORMAT;
2161                                        break;
2162                                }
2163                                if (!msg[1].length)
2164                                {
2165                                        Info = _WRONG_MESSAGE_FORMAT;
2166                                        break;
2167                                }
2168                                if (!plci)
2169                                {
2170                                        Info = _WRONG_IDENTIFIER;
2171                                        break;
2172                                }
2173                                relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2174                                relatedPLCIvalue &= 0x0000FFFF;
2175                                dbug(1, dprintf("PTY/ECT/addCONF,relPLCI=%lx", relatedPLCIvalue));
2176                                /* controller starts with 0 up to (max_adapter - 1) */
2177                                if (((relatedPLCIvalue & 0x7f) == 0)
2178                                    || (MapController((byte)(relatedPLCIvalue & 0x7f)) == 0)
2179                                    || (MapController((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2180                                {
2181                                        if (SSreq == S_3PTY_END)
2182                                        {
2183                                                dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2184                                                rplci = plci;
2185                                        }
2186                                        else
2187                                        {
2188                                                Info = 0x3010;                    /* wrong state           */
2189                                                break;
2190                                        }
2191                                }
2192                                else
2193                                {
2194                                        relatedadapter = &adapter[MapController((byte)(relatedPLCIvalue & 0x7f)) - 1];
2195                                        relatedPLCIvalue >>= 8;
2196                                        /* find PLCI PTR*/
2197                                        for (i = 0, rplci = NULL; i < relatedadapter->max_plci; i++)
2198                                        {
2199                                                if (relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2200                                                {
2201                                                        rplci = &relatedadapter->plci[i];
2202                                                }
2203                                        }
2204                                        if (!rplci || !relatedPLCIvalue)
2205                                        {
2206                                                if (SSreq == S_3PTY_END)
2207                                                {
2208                                                        dbug(1, dprintf("use 2nd PLCI=PLCI"));
2209                                                        rplci = plci;
2210                                                }
2211                                                else
2212                                                {
2213                                                        Info = 0x3010;                    /* wrong state           */
2214                                                        break;
2215                                                }
2216                                        }
2217                                }
2218/*
2219  dbug(1, dprintf("rplci:%x", rplci));
2220  dbug(1, dprintf("plci:%x", plci));
2221  dbug(1, dprintf("rplci->ptyState:%x", rplci->ptyState));
2222  dbug(1, dprintf("plci->ptyState:%x", plci->ptyState));
2223  dbug(1, dprintf("SSreq:%x", SSreq));
2224  dbug(1, dprintf("rplci->internal_command:%x", rplci->internal_command));
2225  dbug(1, dprintf("rplci->appl:%x", rplci->appl));
2226  dbug(1, dprintf("rplci->Id:%x", rplci->Id));
2227*/
2228                                /* send PTY/ECT req, cannot check all states because of US stuff */
2229                                if (!rplci->internal_command && rplci->appl)
2230                                {
2231                                        plci->command = 0;
2232                                        rplci->relatedPTYPLCI = plci;
2233                                        plci->relatedPTYPLCI = rplci;
2234                                        rplci->ptyState = (byte)SSreq;
2235                                        if (SSreq == S_ECT)
2236                                        {
2237                                                rplci->internal_command = ECT_REQ_PEND;
2238                                                cai[1] = ECT_EXECUTE;
2239
2240                                                rplci->vswitchstate = 0;
2241                                                rplci->vsprot = 0;
2242                                                rplci->vsprotdialect = 0;
2243                                                plci->vswitchstate = 0;
2244                                                plci->vsprot = 0;
2245                                                plci->vsprotdialect = 0;
2246
2247                                        }
2248                                        else if (SSreq == S_CONF_ADD)
2249                                        {
2250                                                rplci->internal_command = CONF_ADD_REQ_PEND;
2251                                                cai[1] = CONF_ADD;
2252                                        }
2253                                        else
2254                                        {
2255                                                rplci->internal_command = PTY_REQ_PEND;
2256                                                cai[1] = (byte)(SSreq - 3);
2257                                        }
2258                                        rplci->number = Number;
2259                                        if (plci != rplci) /* explicit invocation */
2260                                        {
2261                                                cai[0] = 2;
2262                                                cai[2] = plci->Sig.Id;
2263                                                dbug(1, dprintf("explicit invocation"));
2264                                        }
2265                                        else
2266                                        {
2267                                                dbug(1, dprintf("implicit invocation"));
2268                                                cai[0] = 1;
2269                                        }
2270                                        add_p(rplci, CAI, cai);
2271                                        sig_req(rplci, S_SERVICE, 0);
2272                                        send_req(rplci);
2273                                        return false;
2274                                }
2275                                else
2276                                {
2277                                        dbug(0, dprintf("Wrong line"));
2278                                        Info = 0x3010;                    /* wrong state           */
2279                                        break;
2280                                }
2281                                break;
2282
2283                        case S_CALL_DEFLECTION:
2284                                if (api_parse(&parms->info[1], (word)parms->length, "wbwss", ss_parms))
2285                                {
2286                                        dbug(1, dprintf("format wrong"));
2287                                        Info = _WRONG_MESSAGE_FORMAT;
2288                                        break;
2289                                }
2290                                if (!plci)
2291                                {
2292                                        Info = _WRONG_IDENTIFIER;
2293                                        break;
2294                                }
2295                                /* reuse unused screening indicator */
2296                                ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2297                                plci->command = 0;
2298                                plci->internal_command = CD_REQ_PEND;
2299                                appl->CDEnable = true;
2300                                cai[0] = 1;
2301                                cai[1] = CALL_DEFLECTION;
2302                                add_p(plci, CAI, cai);
2303                                add_p(plci, CPN, ss_parms[3].info);
2304                                sig_req(plci, S_SERVICE, 0);
2305                                send_req(plci);
2306                                return false;
2307                                break;
2308
2309                        case S_CALL_FORWARDING_START:
2310                                if (api_parse(&parms->info[1], (word)parms->length, "wbdwwsss", ss_parms))
2311                                {
2312                                        dbug(1, dprintf("format wrong"));
2313                                        Info = _WRONG_MESSAGE_FORMAT;
2314                                        break;
2315                                }
2316
2317                                if ((i = get_plci(a)))
2318                                {
2319                                        rplci = &a->plci[i - 1];
2320                                        rplci->appl = appl;
2321                                        add_p(rplci, CAI, "\x01\x80");
2322                                        add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2323                                        sig_req(rplci, ASSIGN, DSIG_ID);
2324                                        send_req(rplci);
2325                                }
2326                                else
2327                                {
2328                                        Info = _OUT_OF_PLCI;
2329                                        break;
2330                                }
2331
2332                                /* reuse unused screening indicator */
2333                                rplci->internal_command = CF_START_PEND;
2334                                rplci->appl = appl;
2335                                rplci->number = Number;
2336                                appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2337                                cai[0] = 2;
2338                                cai[1] = 0x70 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2339                                cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2340                                add_p(rplci, CAI, cai);
2341                                add_p(rplci, OAD, ss_parms[5].info);
2342                                add_p(rplci, CPN, ss_parms[6].info);
2343                                sig_req(rplci, S_SERVICE, 0);
2344                                send_req(rplci);
2345                                return false;
2346                                break;
2347
2348                        case S_INTERROGATE_DIVERSION:
2349                        case S_INTERROGATE_NUMBERS:
2350                        case S_CALL_FORWARDING_STOP:
2351                        case S_CCBS_REQUEST:
2352                        case S_CCBS_DEACTIVATE:
2353                        case S_CCBS_INTERROGATE:
2354                                switch (SSreq)
2355                                {
2356                                case S_INTERROGATE_NUMBERS:
2357                                        if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2358                                        {
2359                                                dbug(0, dprintf("format wrong"));
2360                                                Info = _WRONG_MESSAGE_FORMAT;
2361                                        }
2362                                        break;
2363                                case S_CCBS_REQUEST:
2364                                case S_CCBS_DEACTIVATE:
2365                                        if (api_parse(&parms->info[1], (word)parms->length, "wbdw", ss_parms))
2366                                        {
2367                                                dbug(0, dprintf("format wrong"));
2368                                                Info = _WRONG_MESSAGE_FORMAT;
2369                                        }
2370                                        break;
2371                                case S_CCBS_INTERROGATE:
2372                                        if (api_parse(&parms->info[1], (word)parms->length, "wbdws", ss_parms))
2373                                        {
2374                                                dbug(0, dprintf("format wrong"));
2375                                                Info = _WRONG_MESSAGE_FORMAT;
2376                                        }
2377                                        break;
2378                                default:
2379                                        if (api_parse(&parms->info[1], (word)parms->length, "wbdwws", ss_parms))
2380                                        {
2381                                                dbug(0, dprintf("format wrong"));
2382                                                Info = _WRONG_MESSAGE_FORMAT;
2383                                                break;
2384                                        }
2385                                        break;
2386                                }
2387
2388                                if (Info) break;
2389                                if ((i = get_plci(a)))
2390                                {
2391                                        rplci = &a->plci[i - 1];
2392                                        switch (SSreq)
2393                                        {
2394                                        case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2395                                                cai[1] = 0x60 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2396                                                rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2397                                                break;
2398                                        case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2399                                                cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2400                                                rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2401                                                break;
2402                                        case S_CALL_FORWARDING_STOP:
2403                                                rplci->internal_command = CF_STOP_PEND;
2404                                                cai[1] = 0x80 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2405                                                break;
2406                                        case S_CCBS_REQUEST:
2407                                                cai[1] = CCBS_REQUEST;
2408                                                rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2409                                                break;
2410                                        case S_CCBS_DEACTIVATE:
2411                                                cai[1] = CCBS_DEACTIVATE;
2412                                                rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2413                                                break;
2414                                        case S_CCBS_INTERROGATE:
2415                                                cai[1] = CCBS_INTERROGATE;
2416                                                rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2417                                                break;
2418                                        default:
2419                                                cai[1] = 0;
2420                                                break;
2421                                        }
2422                                        rplci->appl = appl;
2423                                        rplci->number = Number;
2424                                        add_p(rplci, CAI, "\x01\x80");
2425                                        add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2426                                        sig_req(rplci, ASSIGN, DSIG_ID);
2427                                        send_req(rplci);
2428                                }
2429                                else
2430                                {
2431                                        Info = _OUT_OF_PLCI;
2432                                        break;
2433                                }
2434
2435                                appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2436                                switch (SSreq)
2437                                {
2438                                case S_INTERROGATE_NUMBERS:
2439                                        cai[0] = 1;
2440                                        add_p(rplci, CAI, cai);
2441                                        break;
2442                                case S_CCBS_REQUEST:
2443                                case S_CCBS_DEACTIVATE:
2444                                        cai[0] = 3;
2445                                        PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2446                                        add_p(rplci, CAI, cai);
2447                                        break;
2448                                case S_CCBS_INTERROGATE:
2449                                        cai[0] = 3;
2450                                        PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2451                                        add_p(rplci, CAI, cai);
2452                                        add_p(rplci, OAD, ss_parms[4].info);
2453                                        break;
2454                                default:
2455                                        cai[0] = 2;
2456                                        cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2457                                        add_p(rplci, CAI, cai);
2458                                        add_p(rplci, OAD, ss_parms[5].info);
2459                                        break;
2460                                }
2461
2462                                sig_req(rplci, S_SERVICE, 0);
2463                                send_req(rplci);
2464                                return false;
2465                                break;
2466
2467                        case S_MWI_ACTIVATE:
2468                                if (api_parse(&parms->info[1], (word)parms->length, "wbwdwwwssss", ss_parms))
2469                                {
2470                                        dbug(1, dprintf("format wrong"));
2471                                        Info = _WRONG_MESSAGE_FORMAT;
2472                                        break;
2473                                }
2474                                if (!plci)
2475                                {
2476                                        if ((i = get_plci(a)))
2477                                        {
2478                                                rplci = &a->plci[i - 1];
2479                                                rplci->appl = appl;
2480                                                rplci->cr_enquiry = true;
2481                                                add_p(rplci, CAI, "\x01\x80");
2482                                                add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2483                                                sig_req(rplci, ASSIGN, DSIG_ID);
2484                                                send_req(rplci);
2485                                        }
2486                                        else
2487                                        {
2488                                                Info = _OUT_OF_PLCI;
2489                                                break;
2490                                        }
2491                                }
2492                                else
2493                                {
2494                                        rplci = plci;
2495                                        rplci->cr_enquiry = false;
2496                                }
2497
2498                                rplci->command = 0;
2499                                rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2500                                rplci->appl = appl;
2501                                rplci->number = Number;
2502
2503                                cai[0] = 13;
2504                                cai[1] = ACTIVATION_MWI; /* Function */
2505                                PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2506                                PUT_DWORD(&cai[4], GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2507                                PUT_WORD(&cai[8], GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2508                                PUT_WORD(&cai[10], GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2509                                PUT_WORD(&cai[12], GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2510                                add_p(rplci, CAI, cai);
2511                                add_p(rplci, CPN, ss_parms[7].info); /* Receiving User Number */
2512                                add_p(rplci, OAD, ss_parms[8].info); /* Controlling User Number */
2513                                add_p(rplci, OSA, ss_parms[9].info); /* Controlling User Provided Number */
2514                                add_p(rplci, UID, ss_parms[10].info); /* Time */
2515                                sig_req(rplci, S_SERVICE, 0);
2516                                send_req(rplci);
2517                                return false;
2518
2519                        case S_MWI_DEACTIVATE:
2520                                if (api_parse(&parms->info[1], (word)parms->length, "wbwwss", ss_parms))
2521                                {
2522                                        dbug(1, dprintf("format wrong"));
2523                                        Info = _WRONG_MESSAGE_FORMAT;
2524                                        break;
2525                                }
2526                                if (!plci)
2527                                {
2528                                        if ((i = get_plci(a)))
2529                                        {
2530                                                rplci = &a->plci[i - 1];
2531                                                rplci->appl = appl;
2532                                                rplci->cr_enquiry = true;
2533                                                add_p(rplci, CAI, "\x01\x80");
2534                                                add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2535                                                sig_req(rplci, ASSIGN, DSIG_ID);
2536                                                send_req(rplci);
2537                                        }
2538                                        else
2539                                        {
2540                                                Info = _OUT_OF_PLCI;
2541                                                break;
2542                                        }
2543                                }
2544                                else
2545                                {
2546                                        rplci = plci;
2547                                        rplci->cr_enquiry = false;
2548                                }
2549
2550                                rplci->command = 0;
2551                                rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2552                                rplci->appl = appl;
2553                                rplci->number = Number;
2554
2555                                cai[0] = 5;
2556                                cai[1] = DEACTIVATION_MWI; /* Function */
2557                                PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2558                                PUT_WORD(&cai[4], GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2559                                add_p(rplci, CAI, cai);
2560                                add_p(rplci, CPN, ss_parms[4].info); /* Receiving User Number */
2561                                add_p(rplci, OAD, ss_parms[5].info); /* Controlling User Number */
2562                                sig_req(rplci, S_SERVICE, 0);
2563                                send_req(rplci);
2564                                return false;
2565
2566                        default:
2567                                Info = 0x300E;  /* not supported */
2568                                break;
2569                        }
2570                        break; /* case SELECTOR_SU_SERV: end */
2571
2572
2573                case SELECTOR_DTMF:
2574                        return (dtmf_request(Id, Number, a, plci, appl, msg));
2575
2576
2577
2578                case SELECTOR_LINE_INTERCONNECT:
2579                        return (mixer_request(Id, Number, a, plci, appl, msg));
2580
2581
2582
2583                case PRIV_SELECTOR_ECHO_CANCELLER:
2584                        appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2585                        return (ec_request(Id, Number, a, plci, appl, msg));
2586
2587                case SELECTOR_ECHO_CANCELLER:
2588                        appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2589                        return (ec_request(Id, Number, a, plci, appl, msg));
2590
2591
2592                case SELECTOR_V42BIS:
2593                default:
2594                        Info = _FACILITY_NOT_SUPPORTED;
2595                        break;
2596                } /* end of switch (selector) */
2597        }
2598
2599        dbug(1, dprintf("SendFacRc"));
2600        sendf(appl,
2601              _FACILITY_R | CONFIRM,
2602              Id,
2603              Number,
2604              "wws", Info, selector, SSparms);
2605        return false;
2606}
2607
2608static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2609                         PLCI *plci, APPL *appl, API_PARSE *msg)
2610{
2611        dbug(1, dprintf("facility_res"));
2612        return false;
2613}
2614
2615static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2616                           PLCI *plci, APPL *appl, API_PARSE *parms)
2617{
2618        word Info = 0;
2619        byte req;
2620        byte len;
2621        word w;
2622        word fax_control_bits, fax_feature_bits, fax_info_change;
2623        API_PARSE *ncpi;
2624        byte pvc[2];
2625
2626        API_PARSE fax_parms[9];
2627        word i;
2628
2629
2630        dbug(1, dprintf("connect_b3_req"));
2631        if (plci)
2632        {
2633                if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2634                    || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2635                {
2636                        Info = _WRONG_STATE;
2637                }
2638                else
2639                {
2640                        /* local reply if assign unsuccessful
2641                           or B3 protocol allows only one layer 3 connection
2642                           and already connected
2643                           or B2 protocol not any LAPD
2644                           and connect_b3_req contradicts originate/answer direction */
2645                        if (!plci->NL.Id
2646                            || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2647                                && ((plci->channels != 0)
2648                                    || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2649                                        && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2650                        {
2651                                dbug(1, dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2652                                                plci->channels, plci->NL.Id, plci->call_dir, plci->SuppState));
2653                                Info = _WRONG_STATE;
2654                                sendf(appl,
2655                                      _CONNECT_B3_R | CONFIRM,
2656                                      Id,
2657                                      Number,
2658                                      "w", Info);
2659                                return false;
2660                        }
2661                        plci->requested_options_conn = 0;
2662
2663                        req = N_CONNECT;
2664                        ncpi = &parms[0];
2665                        if (plci->B3_prot == 2 || plci->B3_prot == 3)
2666                        {
2667                                if (ncpi->length > 2)
2668                                {
2669                                        /* check for PVC */
2670                                        if (ncpi->info[2] || ncpi->info[3])
2671                                        {
2672                                                pvc[0] = ncpi->info[3];
2673                                                pvc[1] = ncpi->info[2];
2674                                                add_d(plci, 2, pvc);
2675                                                req = N_RESET;
2676                                        }
2677                                        else
2678                                        {
2679                                                if (ncpi->info[1] & 1) req = N_CONNECT | N_D_BIT;
2680                                                add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2681                                        }
2682                                }
2683                        }
2684                        else if (plci->B3_prot == 5)
2685                        {
2686                                if (plci->NL.Id && !plci->nl_remove_id)
2687                                {
2688                                        fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2689                                        fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2690                                        if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2691                                            || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2692                                        {
2693                                                len = offsetof(T30_INFO, universal_6);
2694                                                fax_info_change = false;
2695                                                if (ncpi->length >= 4)
2696                                                {
2697                                                        w = GET_WORD(&ncpi->info[3]);
2698                                                        if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2699                                                        {
2700                                                                ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2701                                                                        (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2702                                                                               ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2703                                                                fax_info_change = true;
2704                                                        }
2705                                                        fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2706                                                        if (w & 0x0002)  /* Fax-polling request */
2707                                                                fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2708                                                        if ((w & 0x0004) /* Request to send / poll another document */
2709                                                            && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2710                                                        {
2711                                                                fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2712                                                        }
2713                                                        if (ncpi->length >= 6)
2714                                                        {
2715                                                                w = GET_WORD(&ncpi->info[5]);
2716                                                                if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2717                                                                {
2718                                                                        ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2719                                                                        fax_info_change = true;
2720                                                                }
2721
2722                                                                if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2723                                                                    && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2724                                                                {
2725                                                                        plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2726                                                                }
2727                                                                if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2728                                                                    && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2729                                                                {
2730                                                                        plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2731                                                                }
2732                                                                fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2733                                                                                      T30_CONTROL_BIT_ACCEPT_PASSWORD);
2734                                                                if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2735                                                                    & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2736                                                                {
2737                                                                        if (api_parse(&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2738                                                                                Info = _WRONG_MESSAGE_FORMAT;
2739                                                                        else
2740                                                                        {
2741                                                                                if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2742                                                                                    & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2743                                                                                {
2744                                                                                        fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2745                                                                                        if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2746                                                                                                fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2747                                                                                }
2748                                                                                w = fax_parms[4].length;
2749                                                                                if (w > 20)
2750                                                                                        w = 20;
2751                                                                                ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2752                                                                                for (i = 0; i < w; i++)
2753                                                                                        ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1 + i];
2754                                                                                ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2755                                                                                len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2756                                                                                w = fax_parms[5].length;
2757                                                                                if (w > 20)
2758                                                                                        w = 20;
2759                                                                                plci->fax_connect_info_buffer[len++] = (byte) w;
2760                                                                                for (i = 0; i < w; i++)
2761                                                                                        plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1 + i];
2762                                                                                w = fax_parms[6].length;
2763                                                                                if (w > 20)
2764                                                                                        w = 20;
2765                                                                                plci->fax_connect_info_buffer[len++] = (byte) w;
2766                                                                                for (i = 0; i < w; i++)
2767                                                                                        plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1 + i];
2768                                                                                if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2769                                                                                    & (1L << PRIVATE_FAX_NONSTANDARD))
2770                                                                                {
2771                                                                                        if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2772                                                                                        {
2773                                                                                                dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2774                                                                                                plci->fax_connect_info_buffer[len++] = 0;
2775                                                                                        }
2776                                                                                        else
2777                                                                                        {
2778                                                                                                if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2779                                                                                                        plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2780                                                                                                plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2781                                                                                                for (i = 0; i < fax_parms[7].length; i++)
2782                                                                                                        plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2783                                                                                        }
2784                                                                                }
2785                                                                        }
2786                                                                }
2787                                                                else
2788                                                                {
2789                                                                        len = offsetof(T30_INFO, universal_6);
2790                                                                }
2791                                                                fax_info_change = true;
2792
2793                                                        }
2794                                                        if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2795                                                        {
2796                                                                PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2797                                                                fax_info_change = true;
2798                                                        }
2799                                                }
2800                                                if (Info == GOOD)
2801                                                {
2802                                                        plci->fax_connect_info_length = len;
2803                                                        if (fax_info_change)
2804                                                        {
2805                                                                if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2806                                                                {
2807                                                                        start_internal_command(Id, plci, fax_connect_info_command);
2808                                                                        return false;
2809                                                                }
2810                                                                else
2811                                                                {
2812                                                                        start_internal_command(Id, plci, fax_adjust_b23_command);
2813                                                                        return false;
2814                                                                }
2815                                                        }
2816                                                }
2817                                        }
2818                                        else  Info = _WRONG_STATE;
2819                                }
2820                                else  Info = _WRONG_STATE;
2821                        }
2822
2823                        else if (plci->B3_prot == B3_RTP)
2824                        {
2825                                plci->internal_req_buffer[0] = ncpi->length + 1;
2826                                plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2827                                for (w = 0; w < ncpi->length; w++)
2828                                        plci->internal_req_buffer[2 + w] = ncpi->info[1 + w];
2829                                start_internal_command(Id, plci, rtp_connect_b3_req_command);
2830                                return false;
2831                        }
2832
2833                        if (!Info)
2834                        {
2835                                nl_req_ncci(plci, req, 0);
2836                                return 1;
2837                        }
2838                }
2839        }
2840        else Info = _WRONG_IDENTIFIER;
2841
2842        sendf(appl,
2843              _CONNECT_B3_R | CONFIRM,
2844              Id,
2845              Number,
2846              "w", Info);
2847        return false;
2848}
2849
2850static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2851                           PLCI *plci, APPL *appl, API_PARSE *parms)
2852{
2853        word ncci;
2854        API_PARSE *ncpi;
2855        byte req;
2856
2857        word w;
2858
2859
2860        API_PARSE fax_parms[9];
2861        word i;
2862        byte len;
2863
2864
2865        dbug(1, dprintf("connect_b3_res"));
2866
2867        ncci = (word)(Id >> 16);
2868        if (plci && ncci) {
2869                if (a->ncci_state[ncci] == INC_CON_PENDING) {
2870                        if (GET_WORD(&parms[0].info[0]) != 0)
2871                        {
2872                                a->ncci_state[ncci] = OUTG_REJ_PENDING;
2873                                channel_request_xon(plci, a->ncci_ch[ncci]);
2874                                channel_xmit_xon(plci);
2875                                cleanup_ncci_data(plci, ncci);
2876                                nl_req_ncci(plci, N_DISC, (byte)ncci);
2877                                return 1;
2878                        }
2879                        a->ncci_state[ncci] = INC_ACT_PENDING;
2880
2881                        req = N_CONNECT_ACK;
2882                        ncpi = &parms[1];
2883                        if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2884                        {
2885
2886                                if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
2887                                    & (1L << PRIVATE_FAX_NONSTANDARD))
2888                                {
2889                                        if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2890                                            && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2891                                            && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2892                                        {
2893                                                len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2894                                                if (plci->fax_connect_info_length < len)
2895                                                {
2896                                                        ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2897                                                        ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2898                                                }
2899                                                if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2900                                                {
2901                                                        dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2902                                                }
2903                                                else
2904                                                {
2905                                                        if (plci->fax_connect_info_length <= len)
2906                                                                plci->fax_connect_info_buffer[len] = 0;
2907                                                        len += 1 + plci->fax_connect_info_buffer[len];
2908                                                        if (plci->fax_connect_info_length <= len)
2909                                                                plci->fax_connect_info_buffer[len] = 0;
2910                                                        len += 1 + plci->fax_connect_info_buffer[len];
2911                                                        if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2912                                                                plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2913                                                        plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2914                                                        for (i = 0; i < fax_parms[7].length; i++)
2915                                                                plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2916                                                }
2917                                                plci->fax_connect_info_length = len;
2918                                                ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2919                                                start_internal_command(Id, plci, fax_connect_ack_command);
2920                                                return false;
2921                                        }
2922                                }
2923
2924                                nl_req_ncci(plci, req, (byte)ncci);
2925                                if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2926                                    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2927                                {
2928                                        if (plci->B3_prot == 4)
2929                                                sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2930                                        else
2931                                                sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
2932                                        plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2933                                }
2934                        }
2935
2936                        else if (plci->B3_prot == B3_RTP)
2937                        {
2938                                plci->internal_req_buffer[0] = ncpi->length + 1;
2939                                plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2940                                for (w = 0; w < ncpi->length; w++)
2941                                        plci->internal_req_buffer[2 + w] = ncpi->info[1+w];
2942                                start_internal_command(Id, plci, rtp_connect_b3_res_command);
2943                                return false;
2944                        }
2945
2946                        else
2947                        {
2948                                if (ncpi->length > 2) {
2949                                        if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
2950                                        add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2951                                }
2952                                nl_req_ncci(plci, req, (byte)ncci);
2953                                sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2954                                if (plci->adjust_b_restore)
2955                                {
2956                                        plci->adjust_b_restore = false;
2957                                        start_internal_command(Id, plci, adjust_b_restore);
2958                                }
2959                        }
2960                        return 1;
2961                }
2962        }
2963        return false;
2964}
2965
2966static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2967                             PLCI *plci, APPL *appl, API_PARSE *parms)
2968{
2969        word ncci;
2970
2971        ncci = (word)(Id >> 16);
2972        dbug(1, dprintf("connect_b3_a_res(ncci=0x%x)", ncci));
2973
2974        if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2975            && (plci->State != OUTG_DIS_PENDING))
2976        {
2977                if (a->ncci_state[ncci] == INC_ACT_PENDING) {
2978                        a->ncci_state[ncci] = CONNECTED;
2979                        if (plci->State != INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2980                        channel_request_xon(plci, a->ncci_ch[ncci]);
2981                        channel_xmit_xon(plci);
2982                }
2983        }
2984        return false;
2985}
2986
2987static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2988                              PLCI *plci, APPL *appl, API_PARSE *parms)
2989{
2990        word Info;
2991        word ncci;
2992        API_PARSE *ncpi;
2993
2994        dbug(1, dprintf("disconnect_b3_req"));
2995
2996        Info = _WRONG_IDENTIFIER;
2997        ncci = (word)(Id >> 16);
2998        if (plci && ncci)
2999        {
3000                Info = _WRONG_STATE;
3001                if ((a->ncci_state[ncci] == CONNECTED)
3002                    || (a->ncci_state[ncci] == OUTG_CON_PENDING)
3003                    || (a->ncci_state[ncci] == INC_CON_PENDING)
3004                    || (a->ncci_state[ncci] == INC_ACT_PENDING))
3005                {
3006                        a->ncci_state[ncci] = OUTG_DIS_PENDING;
3007                        channel_request_xon(plci, a->ncci_ch[ncci]);
3008                        channel_xmit_xon(plci);
3009
3010                        if (a->ncci[ncci].data_pending
3011                            && ((plci->B3_prot == B3_TRANSPARENT)
3012                                || (plci->B3_prot == B3_T30)
3013                                || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3014                        {
3015                                plci->send_disc = (byte)ncci;
3016                                plci->command = 0;
3017                                return false;
3018                        }
3019                        else
3020                        {
3021                                cleanup_ncci_data(plci, ncci);
3022
3023                                if (plci->B3_prot == 2 || plci->B3_prot == 3)
3024                                {
3025                                        ncpi = &parms[0];
3026                                        if (ncpi->length > 3)
3027                                        {
3028                                                add_d(plci, (word)(ncpi->length - 3), (byte *)&(ncpi->info[4]));
3029                                        }
3030                                }
3031                                nl_req_ncci(plci, N_DISC, (byte)ncci);
3032                        }
3033                        return 1;
3034                }
3035        }
3036        sendf(appl,
3037              _DISCONNECT_B3_R | CONFIRM,
3038              Id,
3039              Number,
3040              "w", Info);
3041        return false;
3042}
3043
3044static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3045                              PLCI *plci, APPL *appl, API_PARSE *parms)
3046{
3047        word ncci;
3048        word i;
3049
3050        ncci = (word)(Id >> 16);
3051        dbug(1, dprintf("disconnect_b3_res(ncci=0x%x", ncci));
3052        if (plci && ncci) {
3053                plci->requested_options_conn = 0;
3054                plci->fax_connect_info_length = 0;
3055                plci->ncpi_state = 0x00;
3056                if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3057                    && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3058                {
3059                        plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3060                }
3061                for (i = 0; i < MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i] != (byte)ncci; i++);
3062                if (i < MAX_CHANNELS_PER_PLCI) {
3063                        if (plci->channels)plci->channels--;
3064                        for (; i < MAX_CHANNELS_PER_PLCI - 1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i + 1];
3065                        plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI - 1] = 0;
3066
3067                        ncci_free_receive_buffers(plci, ncci);
3068
3069                        if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
3070                                if (plci->State == SUSPENDING) {
3071                                        sendf(plci->appl,
3072                                              _FACILITY_I,
3073                                              Id & 0xffffL,
3074                                              0,
3075                                              "ws", (word)3, "\x03\x04\x00\x00");
3076                                        sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3077                                }
3078                                plci_remove(plci);
3079                                plci->State = IDLE;
3080                        }
3081                }
3082                else
3083                {
3084                        if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3085                            && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3086                            && (a->ncci_state[ncci] == INC_DIS_PENDING))
3087                        {
3088                                ncci_free_receive_buffers(plci, ncci);
3089
3090                                nl_req_ncci(plci, N_EDATA, (byte)ncci);
3091
3092                                plci->adapter->ncci_state[ncci] = IDLE;
3093                                start_internal_command(Id, plci, fax_disconnect_command);
3094                                return 1;
3095                        }
3096                }
3097        }
3098        return false;
3099}
3100
3101static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3102                        PLCI *plci, APPL *appl, API_PARSE *parms)
3103{
3104        NCCI *ncci_ptr;
3105        DATA_B3_DESC *data;
3106        word Info;
3107        word ncci;
3108        word i;
3109
3110        dbug(1, dprintf("data_b3_req"));
3111
3112        Info = _WRONG_IDENTIFIER;
3113        ncci = (word)(Id >> 16);
3114        dbug(1, dprintf("ncci=0x%x, plci=0x%x", ncci, plci));
3115
3116        if (plci && ncci)
3117        {
3118                Info = _WRONG_STATE;
3119                if ((a->ncci_state[ncci] == CONNECTED)
3120                    || (a->ncci_state[ncci] == INC_ACT_PENDING))
3121                {
3122                        /* queue data */
3123                        ncci_ptr = &(a->ncci[ncci]);
3124                        i = ncci_ptr->data_out + ncci_ptr->data_pending;
3125                        if (i >= MAX_DATA_B3)
3126                                i -= MAX_DATA_B3;
3127                        data = &(ncci_ptr->DBuffer[i]);
3128                        data->Number = Number;
3129                        if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3130                            && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3131                        {
3132
3133                                data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3134
3135                        }
3136                        else
3137                                data->P = TransmitBufferSet(appl, *(dword *)parms[0].info);
3138                        data->Length = GET_WORD(parms[1].info);
3139                        data->Handle = GET_WORD(parms[2].info);
3140                        data->Flags = GET_WORD(parms[3].info);
3141                        (ncci_ptr->data_pending)++;
3142
3143                        /* check for delivery confirmation */
3144                        if (data->Flags & 0x0004)
3145                        {
3146                                i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3147                                if (i >= MAX_DATA_ACK)
3148                                        i -= MAX_DATA_ACK;
3149                                ncci_ptr->DataAck[i].Number = data->Number;
3150                                ncci_ptr->DataAck[i].Handle = data->Handle;
3151                                (ncci_ptr->data_ack_pending)++;
3152                        }
3153
3154                        send_data(plci);
3155                        return false;
3156                }
3157        }
3158        if (appl)
3159        {
3160                if (plci)
3161                {
3162                        if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3163                            && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3164                        {
3165
3166                                TransmitBufferFree(appl, (byte *)(long)(*((dword *)(parms[0].info))));
3167
3168                        }
3169                }
3170                sendf(appl,
3171                      _DATA_B3_R | CONFIRM,
3172                      Id,
3173                      Number,
3174                      "ww", GET_WORD(parms[2].info), Info);
3175        }
3176        return false;
3177}
3178
3179static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3180                        PLCI *plci, APPL *appl, API_PARSE *parms)
3181{
3182        word n;
3183        word ncci;
3184        word NCCIcode;
3185
3186        dbug(1, dprintf("data_b3_res"));
3187
3188        ncci = (word)(Id >> 16);
3189        if (plci && ncci) {
3190                n = GET_WORD(parms[0].info);
3191                dbug(1, dprintf("free(%d)", n));
3192                NCCIcode = ncci | (((word) a->Id) << 8);
3193                if (n < appl->MaxBuffer &&
3194                    appl->DataNCCI[n] == NCCIcode &&
3195                    (byte)(appl->DataFlags[n] >> 8) == plci->Id) {
3196                        dbug(1, dprintf("found"));
3197                        appl->DataNCCI[n] = 0;
3198
3199                        if (channel_can_xon(plci, a->ncci_ch[ncci])) {
3200                                channel_request_xon(plci, a->ncci_ch[ncci]);
3201                        }
3202                        channel_xmit_xon(plci);
3203
3204                        if (appl->DataFlags[n] & 4) {
3205                                nl_req_ncci(plci, N_DATA_ACK, (byte)ncci);
3206                                return 1;
3207                        }
3208                }
3209        }
3210        return false;
3211}
3212
3213static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3214                         PLCI *plci, APPL *appl, API_PARSE *parms)
3215{
3216        word Info;
3217        word ncci;
3218
3219        dbug(1, dprintf("reset_b3_req"));
3220
3221        Info = _WRONG_IDENTIFIER;
3222        ncci = (word)(Id >> 16);
3223        if (plci && ncci)
3224        {
3225                Info = _WRONG_STATE;
3226                switch (plci->B3_prot)
3227                {
3228                case B3_ISO8208:
3229                case B3_X25_DCE:
3230                        if (a->ncci_state[ncci] == CONNECTED)
3231                        {
3232                                nl_req_ncci(plci, N_RESET, (byte)ncci);
3233                                send_req(plci);
3234                                Info = GOOD;
3235                        }
3236                        break;
3237                case B3_TRANSPARENT:
3238                        if (a->ncci_state[ncci] == CONNECTED)
3239                        {
3240                                start_internal_command(Id, plci, reset_b3_command);
3241                                Info = GOOD;
3242                        }
3243                        break;
3244                }
3245        }
3246        /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3247        sendf(appl,
3248              _RESET_B3_R | CONFIRM,
3249              Id,
3250              Number,
3251              "w", Info);
3252        return false;
3253}
3254
3255static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3256                         PLCI *plci, APPL *appl, API_PARSE *parms)
3257{
3258        word ncci;
3259
3260        dbug(1, dprintf("reset_b3_res"));
3261
3262        ncci = (word)(Id >> 16);
3263        if (plci && ncci) {
3264                switch (plci->B3_prot)
3265                {
3266                case B3_ISO8208:
3267                case B3_X25_DCE:
3268                        if (a->ncci_state[ncci] == INC_RES_PENDING)
3269                        {
3270                                a->ncci_state[ncci] = CONNECTED;
3271                                nl_req_ncci(plci, N_RESET_ACK, (byte)ncci);
3272                                return true;
3273                        }
3274                        break;
3275                }
3276        }
3277        return false;
3278}
3279
3280static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3281                                 PLCI *plci, APPL *appl, API_PARSE *parms)
3282{
3283        word ncci;
3284        API_PARSE *ncpi;
3285        byte req;
3286
3287        dbug(1, dprintf("connect_b3_t90_a_res"));
3288
3289        ncci = (word)(Id >> 16);
3290        if (plci && ncci) {
3291                if (a->ncci_state[ncci] == INC_ACT_PENDING) {
3292                        a->ncci_state[ncci] = CONNECTED;
3293                }
3294                else if (a->ncci_state[ncci] == INC_CON_PENDING) {
3295                        a->ncci_state[ncci] = CONNECTED;
3296
3297                        req = N_CONNECT_ACK;
3298
3299                        /* parms[0]==0 for CAPI original message definition! */
3300                        if (parms[0].info) {
3301                                ncpi = &parms[1];
3302                                if (ncpi->length > 2) {
3303                                        if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
3304                                        add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
3305                                }
3306                        }
3307                        nl_req_ncci(plci, req, (byte)ncci);
3308                        return 1;
3309                }
3310        }
3311        return false;
3312}
3313
3314
3315static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3316                         PLCI *plci, APPL *appl, API_PARSE *msg)
3317{
3318        word Info = 0;
3319        word i;
3320        byte tel;
3321        API_PARSE bp_parms[7];
3322
3323        if (!plci || !msg)
3324        {
3325                Info = _WRONG_IDENTIFIER;
3326        }
3327        else
3328        {
3329                dbug(1, dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3330                                msg->length, plci->Id, plci->tel, plci->NL.Id, plci->appl, plci->SuppState));
3331                dbug(1, dprintf("PlciState=0x%x", plci->State));
3332                for (i = 0; i < 7; i++) bp_parms[i].length = 0;
3333
3334                /* check if no channel is open, no B3 connected only */
3335                if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3336                    || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3337                {
3338                        Info = _WRONG_STATE;
3339                }
3340                /* check message format and fill bp_parms pointer */
3341                else if (msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3342                {
3343                        Info = _WRONG_MESSAGE_FORMAT;
3344                }
3345                else
3346                {
3347                        if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT)) /* send alert tone inband to the network, */
3348                        {                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3349                                if (Id & EXT_CONTROLLER)
3350                                {
3351                                        sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3352                                        return 0;
3353                                }
3354                                plci->State = INC_CON_CONNECTED_ALERT;
3355                                plci->appl = appl;
3356                                clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
3357                                dump_c_ind_mask(plci);
3358                                for (i = 0; i < max_appl; i++) /* disconnect the other appls */
3359                                {                         /* its quasi a connect        */
3360                                        if (test_c_ind_mask_bit(plci, i))
3361                                                sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3362                                }
3363                        }
3364
3365                        api_save_msg(msg, "s", &plci->saved_msg);
3366                        tel = plci->tel;
3367                        if (Id & EXT_CONTROLLER)
3368                        {
3369                                if (tel) /* external controller in use by this PLCI */
3370                                {
3371                                        if (a->AdvSignalAppl && a->AdvSignalAppl != appl)
3372                                        {
3373                                                dbug(1, dprintf("Ext_Ctrl in use 1"));
3374                                                Info = _WRONG_STATE;
3375                                        }
3376                                }
3377                                else  /* external controller NOT in use by this PLCI ? */
3378                                {
3379                                        if (a->AdvSignalPLCI)
3380                                        {
3381                                                dbug(1, dprintf("Ext_Ctrl in use 2"));
3382                                                Info = _WRONG_STATE;
3383                                        }
3384                                        else /* activate the codec */
3385                                        {
3386                                                dbug(1, dprintf("Ext_Ctrl start"));
3387                                                if (AdvCodecSupport(a, plci, appl, 0))
3388                                                {
3389                                                        dbug(1, dprintf("Error in codec procedures"));
3390                                                        Info = _WRONG_STATE;
3391                                                }
3392                                                else if (plci->spoofed_msg == SPOOFING_REQUIRED) /* wait until codec is active */
3393                                                {
3394                                                        plci->spoofed_msg = AWAITING_SELECT_B;
3395                                                        plci->internal_command = BLOCK_PLCI; /* lock other commands */
3396                                                        plci->command = 0;
3397                                                        dbug(1, dprintf("continue if codec loaded"));
3398                                                        return false;
3399                                                }
3400                                        }
3401                                }
3402                        }
3403                        else /* external controller bit is OFF */
3404                        {
3405                                if (tel) /* external controller in use, need to switch off */
3406                                {
3407                                        if (a->AdvSignalAppl == appl)
3408                                        {
3409                                                CodecIdCheck(a, plci);
3410                                                plci->tel = 0;
3411                                                plci->adv_nl = 0;
3412                                                dbug(1, dprintf("Ext_Ctrl disable"));
3413                                        }
3414                                        else
3415                                        {
3416                                                dbug(1, dprintf("Ext_Ctrl not requested"));
3417                                        }
3418                                }
3419                        }
3420                        if (!Info)
3421                        {
3422                                if (plci->call_dir & CALL_DIR_OUT)
3423                                        plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3424                                else if (plci->call_dir & CALL_DIR_IN)
3425                                        plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3426                                start_internal_command(Id, plci, select_b_command);
3427                                return false;
3428                        }
3429                }
3430        }
3431        sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", Info);
3432        return false;
3433}
3434
3435static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3436                             PLCI *plci, APPL *appl, API_PARSE *parms)
3437{
3438        word command;
3439        word i;
3440        word ncci;
3441        API_PARSE *m;
3442        API_PARSE m_parms[5];
3443        word codec;
3444        byte req;
3445        byte ch;
3446        byte dir;
3447        static byte chi[2] = {0x01, 0x00};
3448        static byte lli[2] = {0x01, 0x00};
3449        static byte codec_cai[2] = {0x01, 0x01};
3450        static byte null_msg = {0};
3451        static API_PARSE null_parms = { 0, &null_msg };
3452        PLCI *v_plci;
3453        word Info = 0;
3454
3455        dbug(1, dprintf("manufacturer_req"));
3456        for (i = 0; i < 5; i++) m_parms[i].length = 0;
3457
3458        if (GET_DWORD(parms[0].info) != _DI_MANU_ID) {
3459                Info = _WRONG_MESSAGE_FORMAT;
3460        }
3461        command = GET_WORD(parms[1].info);
3462        m = &parms[2];
3463        if (!Info)
3464        {
3465                switch (command) {
3466                case _DI_ASSIGN_PLCI:
3467                        if (api_parse(&m->info[1], (word)m->length, "wbbs", m_parms)) {
3468                                Info = _WRONG_MESSAGE_FORMAT;
3469                                break;
3470                        }
3471                        codec = GET_WORD(m_parms[0].info);
3472                        ch = m_parms[1].info[0];
3473                        dir = m_parms[2].info[0];
3474                        if ((i = get_plci(a))) {
3475                                plci = &a->plci[i - 1];
3476                                plci->appl = appl;
3477                                plci->command = _MANUFACTURER_R;
3478                                plci->m_command = command;
3479                                plci->number = Number;
3480                                plci->State = LOCAL_CONNECT;
3481                                Id = (((word)plci->Id << 8) | plci->adapter->Id | 0x80);
3482                                dbug(1, dprintf("ManCMD,plci=0x%x", Id));
3483
3484                                if ((ch == 1 || ch == 2) && (dir <= 2)) {
3485                                        chi[1] = (byte)(0x80 | ch);
3486                                        lli[1] = 0;
3487                                        plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3488                                        switch (codec)
3489                                        {
3490                                        case 0:
3491                                                Info = add_b1(plci, &m_parms[3], 0, 0);
3492                                                break;
3493                                        case 1:
3494                                                add_p(plci, CAI, codec_cai);
3495                                                break;
3496                                                /* manual 'swich on' to the codec support without signalling */
3497                                                /* first 'assign plci' with this function, then use */
3498                                        case 2:
3499                                                if (AdvCodecSupport(a, plci, appl, 0)) {
3500                                                        Info = _RESOURCE_ERROR;
3501                                                }
3502                                                else {
3503                                                        Info = add_b1(plci, &null_parms, 0, B1_FACILITY_LOCAL);
3504                                                        lli[1] = 0x10; /* local call codec stream */
3505                                                }
3506                                                break;
3507                                        }
3508
3509                                        plci->State = LOCAL_CONNECT;
3510                                        plci->manufacturer = true;
3511                                        plci->command = _MANUFACTURER_R;
3512                                        plci->m_command = command;
3513                                        plci->number = Number;
3514
3515                                        if (!Info)
3516                                        {
3517                                                add_p(plci, LLI, lli);
3518                                                add_p(plci, CHI, chi);
3519                                                add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
3520                                                sig_req(plci, ASSIGN, DSIG_ID);
3521
3522                                                if (!codec)
3523                                                {
3524                                                        Info = add_b23(plci, &m_parms[3]);
3525                                                        if (!Info)
3526                                                        {
3527                                                                nl_req_ncci(plci, ASSIGN, 0);
3528                                                                send_req(plci);
3529                                                        }
3530                                                }
3531                                                if (!Info)
3532                                                {
3533                                                        dbug(1, dprintf("dir=0x%x,spoof=0x%x", dir, plci->spoofed_msg));
3534                                                        if (plci->spoofed_msg == SPOOFING_REQUIRED)
3535                                                        {
3536                                                                api_save_msg(m_parms, "wbbs", &plci->saved_msg);
3537                                                                plci->spoofed_msg = AWAITING_MANUF_CON;
3538                                                                plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3539                                                                plci->command = 0;
3540                                                                send_req(plci);
3541                                                                return false;
3542                                                        }
3543                                                        if (dir == 1) {
3544                                                                sig_req(plci, CALL_REQ, 0);
3545                                                        }
3546                                                        else if (!dir) {
3547                                                                sig_req(plci, LISTEN_REQ, 0);
3548                                                        }
3549                                                        send_req(plci);
3550                                                }
3551                                                else
3552                                                {
3553                                                        sendf(appl,
3554                                                              _MANUFACTURER_R | CONFIRM,
3555                                                              Id,
3556                                                              Number,
3557                                                              "dww", _DI_MANU_ID, command, Info);
3558                                                        return 2;
3559                                                }
3560                                        }
3561                                }
3562                        }
3563                        else  Info = _OUT_OF_PLCI;
3564                        break;
3565
3566                case _DI_IDI_CTRL:
3567                        if (!plci)
3568                        {
3569                                Info = _WRONG_IDENTIFIER;
3570                                break;
3571                        }
3572                        if (api_parse(&m->info[1], (word)m->length, "bs", m_parms)) {
3573                                Info = _WRONG_MESSAGE_FORMAT;
3574                                break;
3575                        }
3576                        req = m_parms[0].info[0];
3577                        plci->command = _MANUFACTURER_R;
3578                        plci->m_command = command;
3579                        plci->number = Number;
3580                        if (req == CALL_REQ)
3581                        {
3582                                plci->b_channel = getChannel(&m_parms[1]);
3583                                mixer_set_bchannel_id_esc(plci, plci->b_channel);
3584                                if (plci->spoofed_msg == SPOOFING_REQUIRED)
3585                                {
3586                                        plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3587                                        plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3588                                        plci->command = 0;
3589                                        break;
3590                                }
3591                        }
3592                        else if (req == LAW_REQ)
3593                        {
3594                                plci->cr_enquiry = true;
3595                        }
3596                        add_ss(plci, FTY, &m_parms[1]);
3597                        sig_req(plci, req, 0);
3598                        send_req(plci);
3599                        if (req == HANGUP)
3600                        {
3601                                if (plci->NL.Id && !plci->nl_remove_id)
3602                                {
3603                                        if (plci->channels)
3604                                        {
3605                                                for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
3606                                                {
3607                                                        if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3608                                                        {
3609                                                                a->ncci_state[ncci] = OUTG_DIS_PENDING;
3610                                                                cleanup_ncci_data(plci, ncci);
3611                                                                nl_req_ncci(plci, N_DISC, (byte)ncci);
3612                                                        }
3613                                                }
3614                                        }
3615                                        mixer_remove(plci);
3616                                        nl_req_ncci(plci, REMOVE, 0);
3617                                        send_req(plci);
3618                                }
3619                        }
3620                        break;
3621
3622                case _DI_SIG_CTRL:
3623                        /* signalling control for loop activation B-channel */
3624                        if (!plci)
3625                        {
3626                                Info = _WRONG_IDENTIFIER;
3627                                break;
3628                        }
3629                        if (m->length) {
3630                                plci->command = _MANUFACTURER_R;
3631                                plci->number = Number;
3632                                add_ss(plci, FTY, m);
3633                                sig_req(plci, SIG_CTRL, 0);
3634                                send_req(plci);
3635                        }
3636                        else Info = _WRONG_MESSAGE_FORMAT;
3637                        break;
3638
3639                case _DI_RXT_CTRL:
3640                        /* activation control for receiver/transmitter B-channel */
3641                        if (!plci)
3642                        {
3643                                Info = _WRONG_IDENTIFIER;
3644                                break;
3645                        }
3646                        if (m->length) {
3647                                plci->command = _MANUFACTURER_R;
3648                                plci->number = Number;
3649                                add_ss(plci, FTY, m);
3650                                sig_req(plci, DSP_CTRL, 0);
3651                                send_req(plci);
3652                        }
3653                        else Info = _WRONG_MESSAGE_FORMAT;
3654                        break;
3655
3656                case _DI_ADV_CODEC:
3657                case _DI_DSP_CTRL:
3658                        /* TEL_CTRL commands to support non standard adjustments: */
3659                        /* Ring on/off, Handset micro volume, external micro vol. */
3660                        /* handset+external speaker volume, receiver+transm. gain,*/
3661                        /* handsfree on (hookinfo off), set mixer command         */
3662
3663                        if (command == _DI_ADV_CODEC)
3664                        {
3665                                if (!a->AdvCodecPLCI) {
3666                                        Info = _WRONG_STATE;
3667                                        break;
3668                                }
3669                                v_plci = a->AdvCodecPLCI;
3670                        }
3671                        else
3672                        {
3673                                if (plci
3674                                    && (m->length >= 3)
3675                                    && (m->info[1] == 0x1c)
3676                                    && (m->info[2] >= 1))
3677                                {
3678                                        if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3679                                        {
3680                                                if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3681                                                {
3682                                                        Info = _WRONG_STATE;
3683                                                        break;
3684                                                }
3685                                                a->adv_voice_coef_length = m->info[2] - 1;
3686                                                if (a->adv_voice_coef_length > m->length - 3)
3687                                                        a->adv_voice_coef_length = (byte)(m->length - 3);
3688                                                if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3689                                                        a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3690                                                for (i = 0; i < a->adv_voice_coef_length; i++)
3691                                                        a->adv_voice_coef_buffer[i] = m->info[4 + i];
3692                                                if (plci->B1_facilities & B1_FACILITY_VOICE)
3693                                                        adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
3694                                                break;
3695                                        }
3696                                        else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3697                                        {
3698                                                if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3699                                                {
3700                                                        Info = _FACILITY_NOT_SUPPORTED;
3701                                                        break;
3702                                                }
3703
3704                                                plci->dtmf_parameter_length = m->info[2] - 1;
3705                                                if (plci->dtmf_parameter_length > m->length - 3)
3706                                                        plci->dtmf_parameter_length = (byte)(m->length - 3);
3707                                                if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3708                                                        plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3709                                                for (i = 0; i < plci->dtmf_parameter_length; i++)
3710                                                        plci->dtmf_parameter_buffer[i] = m->info[4 + i];
3711                                                if (plci->B1_facilities & B1_FACILITY_DTMFR)
3712                                                        dtmf_parameter_write(plci);
3713                                                break;
3714
3715                                        }
3716                                }
3717                                v_plci = plci;
3718                        }
3719
3720                        if (!v_plci)
3721                        {
3722                                Info = _WRONG_IDENTIFIER;
3723                                break;
3724                        }
3725                        if (m->length) {
3726                                add_ss(v_plci, FTY, m);
3727                                sig_req(v_plci, TEL_CTRL, 0);
3728                                send_req(v_plci);
3729                        }
3730                        else Info = _WRONG_MESSAGE_FORMAT;
3731
3732                        break;
3733
3734                case _DI_OPTIONS_REQUEST:
3735                        if (api_parse(&m->info[1], (word)m->length, "d", m_parms)) {
3736                                Info = _WRONG_MESSAGE_FORMAT;
3737                                break;
3738                        }
3739                        if (GET_DWORD(m_parms[0].info) & ~a->man_profile.private_options)
3740                        {
3741                                Info = _FACILITY_NOT_SUPPORTED;
3742                                break;
3743                        }
3744                        a->requested_options_table[appl->Id - 1] = GET_DWORD(m_parms[0].info);
3745                        break;
3746
3747
3748
3749                default:
3750                        Info = _WRONG_MESSAGE_FORMAT;
3751                        break;
3752                }
3753        }
3754
3755        sendf(appl,
3756              _MANUFACTURER_R | CONFIRM,
3757              Id,
3758              Number,
3759              "dww", _DI_MANU_ID, command, Info);
3760        return false;
3761}
3762
3763
3764static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3765                             PLCI *plci, APPL *appl, API_PARSE *msg)
3766{
3767        word indication;
3768
3769        API_PARSE m_parms[3];
3770        API_PARSE *ncpi;
3771        API_PARSE fax_parms[9];
3772        word i;
3773        byte len;
3774
3775
3776        dbug(1, dprintf("manufacturer_res"));
3777
3778        if ((msg[0].length == 0)
3779            || (msg[1].length == 0)
3780            || (GET_DWORD(msg[0].info) != _DI_MANU_ID))
3781        {
3782                return false;
3783        }
3784        indication = GET_WORD(msg[1].info);
3785        switch (indication)
3786        {
3787
3788        case _DI_NEGOTIATE_B3:
3789                if (!plci)
3790                        break;
3791                if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3792                    || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3793                {
3794                        dbug(1, dprintf("wrong state for NEGOTIATE_B3 parameters"));
3795                        break;
3796                }
3797                if (api_parse(&msg[2].info[1], msg[2].length, "ws", m_parms))
3798                {
3799                        dbug(1, dprintf("wrong format in NEGOTIATE_B3 parameters"));
3800                        break;
3801                }
3802                ncpi = &m_parms[1];
3803                len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
3804                if (plci->fax_connect_info_length < len)
3805                {
3806                        ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3807                        ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3808                }
3809                if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3810                {
3811                        dbug(1, dprintf("non-standard facilities info missing or wrong format"));
3812                }
3813                else
3814                {
3815                        if (plci->fax_connect_info_length <= len)
3816                                plci->fax_connect_info_buffer[len] = 0;
3817                        len += 1 + plci->fax_connect_info_buffer[len];
3818                        if (plci->fax_connect_info_length <= len)
3819                                plci->fax_connect_info_buffer[len] = 0;
3820                        len += 1 + plci->fax_connect_info_buffer[len];
3821                        if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3822                                plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3823                        plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3824                        for (i = 0; i < fax_parms[7].length; i++)
3825                                plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
3826                }
3827                plci->fax_connect_info_length = len;
3828                plci->fax_edata_ack_length = plci->fax_connect_info_length;
3829                start_internal_command(Id, plci, fax_edata_ack_command);
3830                break;
3831
3832        }
3833        return false;
3834}
3835
3836/*------------------------------------------------------------------*/
3837/* IDI callback function                                            */
3838/*------------------------------------------------------------------*/
3839
3840void callback(ENTITY *e)
3841{
3842        DIVA_CAPI_ADAPTER *a;
3843        APPL *appl;
3844        PLCI *plci;
3845        CAPI_MSG *m;
3846        word i, j;
3847        byte rc;
3848        byte ch;
3849        byte req;
3850        byte global_req;
3851        int no_cancel_rc;
3852
3853        dbug(1, dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3854                        (e->user[0] + 1) & 0x7fff, e->Id, e->Req, e->Rc, e->Ind));
3855
3856        a = &(adapter[(byte)e->user[0]]);
3857        plci = &(a->plci[e->user[1]]);
3858        no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3859
3860        /*
3861          If new protocol code and new XDI is used then CAPI should work
3862          fully in accordance with IDI cpec an look on callback field instead
3863          of Rc field for return codes.
3864        */
3865        if (((e->complete == 0xff) && no_cancel_rc) ||
3866            (e->Rc && !no_cancel_rc)) {
3867                rc = e->Rc;
3868                ch = e->RcCh;
3869                req = e->Req;
3870                e->Rc = 0;
3871
3872                if (e->user[0] & 0x8000)
3873                {
3874                        /*
3875                          If REMOVE request was sent then we have to wait until
3876                          return code with Id set to zero arrives.
3877                          All other return codes should be ignored.
3878                        */
3879                        if (req == REMOVE)
3880                        {
3881                                if (e->Id)
3882                                {
3883                                        dbug(1, dprintf("cancel RC in REMOVE state"));
3884                                        return;
3885                                }
3886                                channel_flow_control_remove(plci);
3887                                for (i = 0; i < 256; i++)
3888                                {
3889                                        if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3890                                                a->FlowControlIdTable[i] = 0;
3891                                }
3892                                plci->nl_remove_id = 0;
3893                                if (plci->rx_dma_descriptor > 0) {
3894                                        diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3895                                        plci->rx_dma_descriptor = 0;
3896                                }
3897                        }
3898                        if (rc == OK_FC)
3899                        {
3900                                a->FlowControlIdTable[ch] = e->Id;
3901                                a->FlowControlSkipTable[ch] = 0;
3902
3903                                a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3904                                a->ch_flow_plci[ch] = plci->Id;
3905                                plci->nl_req = 0;
3906                        }
3907                        else
3908                        {
3909                                /*
3910                                  Cancel return codes self, if feature was requested
3911                                */
3912                                if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3913                                        a->FlowControlIdTable[ch] = 0;
3914                                        if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3915                                                dbug(3, dprintf("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3916                                                return;
3917                                        }
3918                                }
3919
3920                                if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3921                                {
3922                                        a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3923                                        if (ch == e->ReqCh)
3924                                                plci->nl_req = 0;
3925                                }
3926                                else
3927                                        plci->nl_req = 0;
3928                        }
3929                        if (plci->nl_req)
3930                                control_rc(plci, 0, rc, ch, 0, true);
3931                        else
3932                        {
3933                                if (req == N_XON)
3934                                {
3935                                        channel_x_on(plci, ch);
3936                                        if (plci->internal_command)
3937                                                control_rc(plci, req, rc, ch, 0, true);
3938                                }
3939                                else
3940                                {
3941                                        if (plci->nl_global_req)
3942                                        {
3943                                                global_req = plci->nl_global_req;
3944                                                plci->nl_global_req = 0;
3945                                                if (rc != ASSIGN_OK) {
3946                                                        e->Id = 0;
3947                                                        if (plci->rx_dma_descriptor > 0) {
3948                                                                diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3949                                                                plci->rx_dma_descriptor = 0;
3950                                                        }
3951                                                }
3952                                                channel_xmit_xon(plci);
3953                                                control_rc(plci, 0, rc, ch, global_req, true);
3954                                        }
3955                                        else if (plci->data_sent)
3956                                        {
3957                                                channel_xmit_xon(plci);
3958                                                plci->data_sent = false;
3959                                                plci->NL.XNum = 1;
3960                                                data_rc(plci, ch);
3961                                                if (plci->internal_command)
3962                                                        control_rc(plci, req, rc, ch, 0, true);
3963                                        }
3964                                        else
3965                                        {
3966                                                channel_xmit_xon(plci);
3967                                                control_rc(plci, req, rc, ch, 0, true);
3968                                        }
3969                                }
3970                        }
3971                }
3972                else
3973                {
3974                        /*
3975                          If REMOVE request was sent then we have to wait until
3976                          return code with Id set to zero arrives.
3977                          All other return codes should be ignored.
3978                        */
3979                        if (req == REMOVE)
3980                        {
3981                                if (e->Id)
3982                                {
3983                                        dbug(1, dprintf("cancel RC in REMOVE state"));
3984                                        return;
3985                                }
3986                                plci->sig_remove_id = 0;
3987                        }
3988                        plci->sig_req = 0;
3989                        if (plci->sig_global_req)
3990                        {
3991                                global_req = plci->sig_global_req;
3992                                plci->sig_global_req = 0;
3993                                if (rc != ASSIGN_OK)
3994                                        e->Id = 0;
3995                                channel_xmit_xon(plci);
3996                                control_rc(plci, 0, rc, ch, global_req, false);
3997                        }
3998                        else
3999                        {
4000                                channel_xmit_xon(plci);
4001                                control_rc(plci, req, rc, ch, 0, false);
4002                        }
4003                }
4004                /*
4005                  Again: in accordance with IDI spec Rc and Ind can't be delivered in the
4006                  same callback. Also if new XDI and protocol code used then jump
4007                  direct to finish.
4008                */
4009                if (no_cancel_rc) {
4010                        channel_xmit_xon(plci);
4011                        goto capi_callback_suffix;
4012                }
4013        }
4014
4015        channel_xmit_xon(plci);
4016
4017        if (e->Ind) {
4018                if (e->user[0] & 0x8000) {
4019                        byte Ind = e->Ind & 0x0f;
4020                        byte Ch = e->IndCh;
4021                        if (((Ind == N_DISC) || (Ind == N_DISC_ACK)) &&
4022                            (a->ch_flow_plci[Ch] == plci->Id)) {
4023                                if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4024                                        dbug(3, dprintf("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4025                                }
4026                                a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4027                        }
4028                        nl_ind(plci);
4029                        if ((e->RNR != 1) &&
4030                            (a->ch_flow_plci[Ch] == plci->Id) &&
4031                            (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4032                                a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4033                                dbug(3, dprintf("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4034                        }
4035                } else {
4036                        sig_ind(plci);
4037                }
4038                e->Ind = 0;
4039        }
4040
4041capi_callback_suffix:
4042
4043        while (!plci->req_in
4044               && !plci->internal_command
4045               && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4046        {
4047                j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4048
4049                i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4050
4051                m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4052                appl = *((APPL **)(&((byte *)(plci->msg_in_queue))[j + i]));
4053                dbug(1, dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4054                                m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4055                if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4056                {
4057                        plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4058                        plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4059                }
4060                else
4061                {
4062                        plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4063                }
4064                if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4065                {
4066                        plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4067                        plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4068                }
4069                else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4070                {
4071                        plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4072                        plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4073                }
4074                i = api_put(appl, m);
4075                if (i != 0)
4076                {
4077                        if (m->header.command == _DATA_B3_R)
4078
4079                                TransmitBufferFree(appl, (byte *)(long)(m->info.data_b3_req.Data));
4080
4081                        dbug(1, dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4082                        break;
4083                }
4084
4085                if (plci->li_notify_update)
4086                {
4087                        plci->li_notify_update = false;
4088                        mixer_notify_update(plci, false);
4089                }
4090
4091        }
4092        send_data(plci);
4093        send_req(plci);
4094}
4095
4096
4097static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4098                       byte nl_rc)
4099{
4100        dword Id;
4101        dword rId;
4102        word Number;
4103        word Info = 0;
4104        word i;
4105        word ncci;
4106        DIVA_CAPI_ADAPTER *a;
4107        APPL *appl;
4108        PLCI *rplci;
4109        byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4110        byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4111
4112        if (!plci) {
4113                dbug(0, dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4114                return;
4115        }
4116        dbug(1, dprintf("req0_in/out=%d/%d", plci->req_in, plci->req_out));
4117        if (plci->req_in != plci->req_out)
4118        {
4119                if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4120                {
4121                        dbug(1, dprintf("req_1return"));
4122                        return;
4123                }
4124                /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4125        }
4126        plci->req_in = plci->req_in_start = plci->req_out = 0;
4127        dbug(1, dprintf("control_rc"));
4128
4129        appl = plci->appl;
4130        a = plci->adapter;
4131        ncci = a->ch_ncci[ch];
4132        if (appl)
4133        {
4134                Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4135                if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4136                Number = plci->number;
4137                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));
4138                dbug(1, dprintf("channels=0x%x", plci->channels));
4139                if (plci_remove_check(plci))
4140                        return;
4141                if (req == REMOVE && rc == ASSIGN_OK)
4142                {
4143                        sig_req(plci, HANGUP, 0);
4144                        sig_req(plci, REMOVE, 0);
4145                        send_req(plci);
4146                }
4147                if (plci->command)
4148                {
4149                        switch (plci->command)
4150                        {
4151                        case C_HOLD_REQ:
4152                                dbug(1, dprintf("HoldRC=0x%x", rc));
4153                                SSparms[1] = (byte)S_HOLD;
4154                                if (rc != OK)
4155                                {
4156                                        plci->SuppState = IDLE;
4157                                        Info = 0x2001;
4158                                }
4159                                sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4160                                break;
4161
4162                        case C_RETRIEVE_REQ:
4163                                dbug(1, dprintf("RetrieveRC=0x%x", rc));
4164                                SSparms[1] = (byte)S_RETRIEVE;
4165                                if (rc != OK)
4166                                {
4167                                        plci->SuppState = CALL_HELD;
4168                                        Info = 0x2001;
4169                                }
4170                                sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4171                                break;
4172
4173                        case _INFO_R:
4174                                dbug(1, dprintf("InfoRC=0x%x", rc));
4175                                if (rc != OK) Info = _WRONG_STATE;
4176                                sendf(appl, _INFO_R | CONFIRM, Id, Number, "w", Info);
4177                                break;
4178
4179                        case _CONNECT_R:
4180                                dbug(1, dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x", req, rc, global_req, nl_rc));
4181                                if (plci->State == INC_DIS_PENDING)
4182                                        break;
4183                                if (plci->Sig.Id != 0xff)
4184                                {
4185                                        if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4186                                            || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4187                                        {
4188                                                dbug(1, dprintf("No more IDs/Call_Req failed"));
4189                                                sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4190                                                plci_remove(plci);
4191                                                plci->State = IDLE;
4192                                                break;
4193                                        }
4194                                        if (plci->State != LOCAL_CONNECT) plci->State = OUTG_CON_PENDING;
4195                                        sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4196                                }
4197                                else /* D-ch activation */
4198                                {
4199                                        if (rc != ASSIGN_OK)
4200                                        {
4201                                                dbug(1, dprintf("No more IDs/X.25 Call_Req failed"));
4202                                                sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4203                                                plci_remove(plci);
4204                                                plci->State = IDLE;
4205                                                break;
4206                                        }
4207                                        sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4208                                        sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "sss", "", "", "");
4209                                        plci->State = INC_ACT_PENDING;
4210                                }
4211                                break;
4212
4213                        case _CONNECT_I | RESPONSE:
4214                                if (plci->State != INC_DIS_PENDING)
4215                                        plci->State = INC_CON_ACCEPT;
4216                                break;
4217
4218                        case _DISCONNECT_R:
4219                                if (plci->State == INC_DIS_PENDING)
4220                                        break;
4221                                if (plci->Sig.Id != 0xff)
4222                                {
4223                                        plci->State = OUTG_DIS_PENDING;
4224                                        sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
4225                                }
4226                                break;
4227
4228                        case SUSPEND_REQ:
4229                                break;
4230
4231                        case RESUME_REQ:
4232                                break;
4233
4234                        case _CONNECT_B3_R:
4235                                if (rc != OK)
4236                                {
4237                                        sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
4238                                        break;
4239                                }
4240                                ncci = get_ncci(plci, ch, 0);
4241                                Id = (Id & 0xffff) | (((dword) ncci) << 16);
4242                                plci->channels++;
4243                                if (req == N_RESET)
4244                                {
4245                                        a->ncci_state[ncci] = INC_ACT_PENDING;
4246                                        sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4247                                        sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
4248                                }
4249                                else
4250                                {
4251                                        a->ncci_state[ncci] = OUTG_CON_PENDING;
4252                                        sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4253                                }
4254                                break;
4255
4256                        case _CONNECT_B3_I | RESPONSE:
4257                                break;
4258
4259                        case _RESET_B3_R:
4260/*        sendf(appl, _RESET_B3_R | CONFIRM, Id, Number, "w", 0);*/
4261                                break;
4262
4263                        case _DISCONNECT_B3_R:
4264                                sendf(appl, _DISCONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4265                                break;
4266
4267                        case _MANUFACTURER_R:
4268                                break;
4269
4270                        case PERM_LIST_REQ:
4271                                if (rc != OK)
4272                                {
4273                                        Info = _WRONG_IDENTIFIER;
4274                                        sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4275                                        plci_remove(plci);
4276                                }
4277                                else
4278                                        sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4279                                break;
4280
4281                        default:
4282                                break;
4283                        }
4284                        plci->command = 0;
4285                }
4286                else if (plci->internal_command)
4287                {
4288                        switch (plci->internal_command)
4289                        {
4290                        case BLOCK_PLCI:
4291                                return;
4292
4293                        case GET_MWI_STATE:
4294                                if (rc == OK) /* command supported, wait for indication */
4295                                {
4296                                        return;
4297                                }
4298                                plci_remove(plci);
4299                                break;
4300
4301                                /* Get Supported Services */
4302                        case GETSERV_REQ_PEND:
4303                                if (rc == OK) /* command supported, wait for indication */
4304                                {
4305                                        break;
4306                                }
4307                                PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4308                                sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", 0, 3, SSstruct);
4309                                plci_remove(plci);
4310                                break;
4311
4312                        case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
4313                        case INTERR_NUMBERS_REQ_PEND:
4314                        case CF_START_PEND:                  /* Call Forwarding Start pending */
4315                        case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
4316                        case CCBS_REQUEST_REQ_PEND:
4317                        case CCBS_DEACTIVATE_REQ_PEND:
4318                        case CCBS_INTERROGATE_REQ_PEND:
4319                                switch (plci->internal_command)
4320                                {
4321                                case INTERR_DIVERSION_REQ_PEND:
4322                                        SSparms[1] = S_INTERROGATE_DIVERSION;
4323                                        break;
4324                                case INTERR_NUMBERS_REQ_PEND:
4325                                        SSparms[1] = S_INTERROGATE_NUMBERS;
4326                                        break;
4327                                case CF_START_PEND:
4328                                        SSparms[1] = S_CALL_FORWARDING_START;
4329                                        break;
4330                                case CF_STOP_PEND:
4331                                        SSparms[1] = S_CALL_FORWARDING_STOP;
4332                                        break;
4333                                case CCBS_REQUEST_REQ_PEND:
4334                                        SSparms[1] = S_CCBS_REQUEST;
4335                                        break;
4336                                case CCBS_DEACTIVATE_REQ_PEND:
4337                                        SSparms[1] = S_CCBS_DEACTIVATE;
4338                                        break;
4339                                case CCBS_INTERROGATE_REQ_PEND:
4340                                        SSparms[1] = S_CCBS_INTERROGATE;
4341                                        break;
4342                                }
4343                                if (global_req == ASSIGN)
4344                                {
4345                                        dbug(1, dprintf("AssignDiversion_RC=0x%x/0x%x", req, rc));
4346                                        return;
4347                                }
4348                                if (!plci->appl) break;
4349                                if (rc == ISDN_GUARD_REJ)
4350                                {
4351                                        Info = _CAPI_GUARD_ERROR;
4352                                }
4353                                else if (rc != OK)
4354                                {
4355                                        Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4356                                }
4357                                sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7,
4358                                      plci->number, "wws", Info, (word)3, SSparms);
4359                                if (Info) plci_remove(plci);
4360                                break;
4361
4362                                /* 3pty conference pending */
4363                        case PTY_REQ_PEND:
4364                                if (!plci->relatedPTYPLCI) break;
4365                                rplci = plci->relatedPTYPLCI;
4366                                SSparms[1] = plci->ptyState;
4367                                rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4368                                if (rplci->tel) rId |= EXT_CONTROLLER;
4369                                if (rc != OK)
4370                                {
4371                                        Info = 0x300E; /* not supported */
4372                                        plci->relatedPTYPLCI = NULL;
4373                                        plci->ptyState = 0;
4374                                }
4375                                sendf(rplci->appl,
4376                                      _FACILITY_R | CONFIRM,
4377                                      rId,
4378                                      plci->number,
4379                                      "wws", Info, (word)3, SSparms);
4380                                break;
4381
4382                                /* Explicit Call Transfer pending */
4383                        case ECT_REQ_PEND:
4384                                dbug(1, dprintf("ECT_RC=0x%x/0x%x", req, rc));
4385                                if (!plci->relatedPTYPLCI) break;
4386                                rplci = plci->relatedPTYPLCI;
4387                                SSparms[1] = S_ECT;
4388                                rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4389                                if (rplci->tel) rId |= EXT_CONTROLLER;
4390                                if (rc != OK)
4391                                {
4392                                        Info = 0x300E; /* not supported */
4393                                        plci->relatedPTYPLCI = NULL;
4394                                        plci->ptyState = 0;
4395                                }
4396                                sendf(rplci->appl,
4397                                      _FACILITY_R | CONFIRM,
4398                                      rId,
4399                                      plci->number,
4400                                      "wws", Info, (word)3, SSparms);
4401                                break;
4402
4403                        case _MANUFACTURER_R:
4404                                dbug(1, dprintf("_Manufacturer_R=0x%x/0x%x", req, rc));
4405                                if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4406                                {
4407                                        dbug(1, dprintf("No more IDs"));
4408                                        sendf(appl, _MANUFACTURER_R | CONFIRM, Id, Number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
4409                                        plci_remove(plci);  /* after codec init, internal codec commands pending */
4410                                }
4411                                break;
4412
4413                        case _CONNECT_R:
4414                                dbug(1, dprintf("_Connect_R=0x%x/0x%x", req, rc));
4415                                if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4416                                {
4417                                        dbug(1, dprintf("No more IDs"));
4418                                        sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4419                                        plci_remove(plci);  /* after codec init, internal codec commands pending */
4420                                }
4421                                break;
4422
4423                        case PERM_COD_HOOK:                     /* finished with Hook_Ind */
4424                                return;
4425
4426                        case PERM_COD_CALL:
4427                                dbug(1, dprintf("***Codec Connect_Pending A, Rc = 0x%x", rc));
4428                                plci->internal_command = PERM_COD_CONN_PEND;
4429                                return;
4430
4431                        case PERM_COD_ASSIGN:
4432                                dbug(1, dprintf("***Codec Assign A, Rc = 0x%x", rc));
4433                                if (rc != ASSIGN_OK) break;
4434                                sig_req(plci, CALL_REQ, 0);
4435                                send_req(plci);
4436                                plci->internal_command = PERM_COD_CALL;
4437                                return;
4438
4439                                /* Null Call Reference Request pending */
4440                        case C_NCR_FAC_REQ:
4441                                dbug(1, dprintf("NCR_FAC=0x%x/0x%x", req, rc));
4442                                if (global_req == ASSIGN)
4443                                {
4444                                        if (rc == ASSIGN_OK)
4445                                        {
4446                                                return;
4447                                        }
4448                                        else
4449                                        {
4450                                                sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4451                                                appl->NullCREnable = false;
4452                                                plci_remove(plci);
4453                                        }
4454                                }
4455                                else if (req == NCR_FACILITY)
4456                                {
4457                                        if (rc == OK)
4458                                        {
4459                                                sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", 0);
4460                                        }
4461                                        else
4462                                        {
4463                                                sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4464                                                appl->NullCREnable = false;
4465                                        }
4466                                        plci_remove(plci);
4467                                }
4468                                break;
4469
4470                        case HOOK_ON_REQ:
4471                                if (plci->channels)
4472                                {
4473                                        if (a->ncci_state[ncci] == CONNECTED)
4474                                        {
4475                                                a->ncci_state[ncci] = OUTG_DIS_PENDING;
4476                                                cleanup_ncci_data(plci, ncci);
4477                                                nl_req_ncci(plci, N_DISC, (byte)ncci);
4478                                        }
4479                                        break;
4480                                }
4481                                break;
4482
4483                        case HOOK_OFF_REQ:
4484                                if (plci->State == INC_DIS_PENDING)
4485                                        break;
4486                                sig_req(plci, CALL_REQ, 0);
4487                                send_req(plci);
4488                                plci->State = OUTG_CON_PENDING;
4489                                break;
4490
4491
4492                        case MWI_ACTIVATE_REQ_PEND:
4493                        case MWI_DEACTIVATE_REQ_PEND:
4494                                if (global_req == ASSIGN && rc == ASSIGN_OK)
4495                                {
4496                                        dbug(1, dprintf("MWI_REQ assigned"));
4497                                        return;
4498                                }
4499                                else if (rc != OK)
4500                                {
4501                                        if (rc == WRONG_IE)
4502                                        {
4503                                                Info = 0x2007; /* Illegal message parameter coding */
4504                                                dbug(1, dprintf("MWI_REQ invalid parameter"));
4505                                        }
4506                                        else
4507                                        {
4508                                                Info = 0x300B; /* not supported */
4509                                                dbug(1, dprintf("MWI_REQ not supported"));
4510                                        }
4511                                        /* 0x3010: Request not allowed in this state */
4512                                        PUT_WORD(&SSparms[4], 0x300E); /* SS not supported */
4513
4514                                }
4515                                if (plci->internal_command == MWI_ACTIVATE_REQ_PEND)
4516                                {
4517                                        PUT_WORD(&SSparms[1], S_MWI_ACTIVATE);
4518                                }
4519                                else PUT_WORD(&SSparms[1], S_MWI_DEACTIVATE);
4520
4521                                if (plci->cr_enquiry)
4522                                {
4523                                        sendf(plci->appl,
4524                                              _FACILITY_R | CONFIRM,
4525                                              Id & 0xf,
4526                                              plci->number,
4527                                              "wws", Info, (word)3, SSparms);
4528                                        if (rc != OK) plci_remove(plci);
4529                                }
4530                                else
4531                                {
4532                                        sendf(plci->appl,
4533                                              _FACILITY_R | CONFIRM,
4534                                              Id,
4535                                              plci->number,
4536                                              "wws", Info, (word)3, SSparms);
4537                                }
4538                                break;
4539
4540                        case CONF_BEGIN_REQ_PEND:
4541                        case CONF_ADD_REQ_PEND:
4542                        case CONF_SPLIT_REQ_PEND:
4543                        case CONF_DROP_REQ_PEND:
4544                        case CONF_ISOLATE_REQ_PEND:
4545                        case CONF_REATTACH_REQ_PEND:
4546                                dbug(1, dprintf("CONF_RC=0x%x/0x%x", req, rc));
4547                                if ((plci->internal_command == CONF_ADD_REQ_PEND) && (!plci->relatedPTYPLCI)) break;
4548                                rplci = plci;
4549                                rId = Id;
4550                                switch (plci->internal_command)
4551                                {
4552                                case CONF_BEGIN_REQ_PEND:
4553                                        SSparms[1] = S_CONF_BEGIN;
4554                                        break;
4555                                case CONF_ADD_REQ_PEND:
4556                                        SSparms[1] = S_CONF_ADD;
4557                                        rplci = plci->relatedPTYPLCI;
4558                                        rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4559                                        break;
4560                                case CONF_SPLIT_REQ_PEND:
4561                                        SSparms[1] = S_CONF_SPLIT;
4562                                        break;
4563                                case CONF_DROP_REQ_PEND:
4564                                        SSparms[1] = S_CONF_DROP;
4565                                        break;
4566                                case CONF_ISOLATE_REQ_PEND:
4567                                        SSparms[1] = S_CONF_ISOLATE;
4568                                        break;
4569                                case CONF_REATTACH_REQ_PEND:
4570                                        SSparms[1] = S_CONF_REATTACH;
4571                                        break;
4572                                }
4573
4574                                if (rc != OK)
4575                                {
4576                                        Info = 0x300E; /* not supported */
4577                                        plci->relatedPTYPLCI = NULL;
4578                                        plci->ptyState = 0;
4579                                }
4580                                sendf(rplci->appl,
4581                                      _FACILITY_R | CONFIRM,
4582                                      rId,
4583                                      plci->number,
4584                                      "wws", Info, (word)3, SSparms);
4585                                break;
4586
4587                        case VSWITCH_REQ_PEND:
4588                                if (rc != OK)
4589                                {
4590                                        if (plci->relatedPTYPLCI)
4591                                        {
4592                                                plci->relatedPTYPLCI->vswitchstate = 0;
4593                                                plci->relatedPTYPLCI->vsprot = 0;
4594                                                plci->relatedPTYPLCI->vsprotdialect = 0;
4595                                        }
4596                                        plci->vswitchstate = 0;
4597                                        plci->vsprot = 0;
4598                                        plci->vsprotdialect = 0;
4599                                }
4600                                else
4601                                {
4602                                        if (plci->relatedPTYPLCI &&
4603                                            plci->vswitchstate == 1 &&
4604                                            plci->relatedPTYPLCI->vswitchstate == 3) /* join complete */
4605                                                plci->vswitchstate = 3;
4606                                }
4607                                break;
4608
4609                                /* Call Deflection Request pending (SSCT) */
4610                        case CD_REQ_PEND:
4611                                SSparms[1] = S_CALL_DEFLECTION;
4612                                if (rc != OK)
4613                                {
4614                                        Info = 0x300E; /* not supported */
4615                                        plci->appl->CDEnable = 0;
4616                                }
4617                                sendf(plci->appl, _FACILITY_R | CONFIRM, Id,
4618                                      plci->number, "wws", Info, (word)3, SSparms);
4619                                break;
4620
4621                        case RTP_CONNECT_B3_REQ_COMMAND_2:
4622                                if (rc == OK)
4623                                {
4624                                        ncci = get_ncci(plci, ch, 0);
4625                                        Id = (Id & 0xffff) | (((dword) ncci) << 16);
4626                                        plci->channels++;
4627                                        a->ncci_state[ncci] = OUTG_CON_PENDING;
4628                                }
4629
4630                        default:
4631                                if (plci->internal_command_queue[0])
4632                                {
4633                                        (*(plci->internal_command_queue[0]))(Id, plci, rc);
4634                                        if (plci->internal_command)
4635                                                return;
4636                                }
4637                                break;
4638                        }
4639                        next_internal_command(Id, plci);
4640                }
4641        }
4642        else /* appl==0 */
4643        {
4644                Id = ((word)plci->Id << 8) | plci->adapter->Id;
4645                if (plci->tel) Id |= EXT_CONTROLLER;
4646
4647                switch (plci->internal_command)
4648                {
4649                case BLOCK_PLCI:
4650                        return;
4651
4652                case START_L1_SIG_ASSIGN_PEND:
4653                case REM_L1_SIG_ASSIGN_PEND:
4654                        if (global_req == ASSIGN)
4655                        {
4656                                break;
4657                        }
4658                        else
4659                        {
4660                                dbug(1, dprintf("***L1 Req rem PLCI"));
4661                                plci->internal_command = 0;
4662                                sig_req(plci, REMOVE, 0);
4663                                send_req(plci);
4664                        }
4665                        break;
4666
4667                        /* Call Deflection Request pending, just no appl ptr assigned */
4668                case CD_REQ_PEND:
4669                        SSparms[1] = S_CALL_DEFLECTION;
4670                        if (rc != OK)
4671                        {
4672                                Info = 0x300E; /* not supported */
4673                        }
4674                        for (i = 0; i < max_appl; i++)
4675                        {
4676                                if (application[i].CDEnable)
4677                                {
4678                                        if (!application[i].Id) application[i].CDEnable = 0;
4679                                        else
4680                                        {
4681                                                sendf(&application[i], _FACILITY_R | CONFIRM, Id,
4682                                                      plci->number, "wws", Info, (word)3, SSparms);
4683                                                if (Info) application[i].CDEnable = 0;
4684                                        }
4685                                }
4686                        }
4687                        plci->internal_command = 0;
4688                        break;
4689
4690                case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4691                        return;
4692
4693                case PERM_COD_CALL:
4694                        plci->internal_command = PERM_COD_CONN_PEND;
4695                        dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc));
4696                        return;
4697
4698                case PERM_COD_ASSIGN:
4699                        dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc));
4700                        plci->internal_command = 0;
4701                        if (rc != ASSIGN_OK) break;
4702                        plci->internal_command = PERM_COD_CALL;
4703                        sig_req(plci, CALL_REQ, 0);
4704                        send_req(plci);
4705                        return;
4706
4707                case LISTEN_SIG_ASSIGN_PEND:
4708                        if (rc == ASSIGN_OK)
4709                        {
4710                                plci->internal_command = 0;
4711                                dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci->Sig.Id));
4712                                add_p(plci, ESC, "\x02\x18\x00");             /* support call waiting */
4713                                sig_req(plci, INDICATE_REQ, 0);
4714                                send_req(plci);
4715                        }
4716                        else
4717                        {
4718                                dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc));
4719                                a->listen_active--;
4720                                plci_remove(plci);
4721                                plci->State = IDLE;
4722                        }
4723                        break;
4724
4725                case USELAW_REQ:
4726                        if (global_req == ASSIGN)
4727                        {
4728                                if (rc == ASSIGN_OK)
4729                                {
4730                                        sig_req(plci, LAW_REQ, 0);
4731                                        send_req(plci);
4732                                        dbug(1, dprintf("Auto-Law assigned"));
4733                                }
4734                                else
4735                                {
4736                                        dbug(1, dprintf("Auto-Law assign failed"));
4737                                        a->automatic_law = 3;
4738                                        plci->internal_command = 0;
4739                                        a->automatic_lawPLCI = NULL;
4740                                }
4741                                break;
4742                        }
4743                        else if (req == LAW_REQ && rc == OK)
4744                        {
4745                                dbug(1, dprintf("Auto-Law initiated"));
4746                                a->automatic_law = 2;
4747                                plci->internal_command = 0;
4748                        }
4749                        else
4750                        {
4751                                dbug(1, dprintf("Auto-Law not supported"));
4752                                a->automatic_law = 3;
4753                                plci->internal_command = 0;
4754                                sig_req(plci, REMOVE, 0);
4755                                send_req(plci);
4756                                a->automatic_lawPLCI = NULL;
4757                        }
4758                        break;
4759                }
4760                plci_remove_check(plci);
4761        }
4762}
4763
4764static void data_rc(PLCI *plci, byte ch)
4765{
4766        dword Id;
4767        DIVA_CAPI_ADAPTER *a;
4768        NCCI *ncci_ptr;
4769        DATA_B3_DESC *data;
4770        word ncci;
4771
4772        if (plci->appl)
4773        {
4774                TransmitBufferFree(plci->appl, plci->data_sent_ptr);
4775                a = plci->adapter;
4776                ncci = a->ch_ncci[ch];
4777                if (ncci && (a->ncci_plci[ncci] == plci->Id))
4778                {
4779                        ncci_ptr = &(a->ncci[ncci]);
4780                        dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr->data_out, ncci_ptr->data_pending));
4781                        if (ncci_ptr->data_pending)
4782                        {
4783                                data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4784                                if (!(data->Flags & 4) && a->ncci_state[ncci])
4785                                {
4786                                        Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4787                                        if (plci->tel) Id |= EXT_CONTROLLER;
4788                                        sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, data->Number,
4789                                              "ww", data->Handle, 0);
4790                                }
4791                                (ncci_ptr->data_out)++;
4792                                if (ncci_ptr->data_out == MAX_DATA_B3)
4793                                        ncci_ptr->data_out = 0;
4794                                (ncci_ptr->data_pending)--;
4795                        }
4796                }
4797        }
4798}
4799
4800static void data_ack(PLCI *plci, byte ch)
4801{
4802        dword Id;
4803        DIVA_CAPI_ADAPTER *a;
4804        NCCI *ncci_ptr;
4805        word ncci;
4806
4807        a = plci->adapter;
4808        ncci = a->ch_ncci[ch];
4809        ncci_ptr = &(a->ncci[ncci]);
4810        if (ncci_ptr->data_ack_pending)
4811        {
4812                if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4813                {
4814                        Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4815                        if (plci->tel) Id |= EXT_CONTROLLER;
4816                        sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4817                              "ww", ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle, 0);
4818                }
4819                (ncci_ptr->data_ack_out)++;
4820                if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4821                        ncci_ptr->data_ack_out = 0;
4822                (ncci_ptr->data_ack_pending)--;
4823        }
4824}
4825
4826static void sig_ind(PLCI *plci)
4827{
4828        dword x_Id;
4829        dword Id;
4830        dword rId;
4831        word i;
4832        word cip;
4833        dword cip_mask;
4834        byte *ie;
4835        DIVA_CAPI_ADAPTER *a;
4836        API_PARSE saved_parms[MAX_MSG_PARMS + 1];
4837#define MAXPARMSIDS 31
4838        byte *parms[MAXPARMSIDS];
4839        byte *add_i[4];
4840        byte *multi_fac_parms[MAX_MULTI_IE];
4841        byte *multi_pi_parms[MAX_MULTI_IE];
4842        byte *multi_ssext_parms[MAX_MULTI_IE];
4843        byte *multi_CiPN_parms[MAX_MULTI_IE];
4844
4845        byte *multi_vswitch_parms[MAX_MULTI_IE];
4846
4847        byte ai_len;
4848        byte *esc_chi = "";
4849        byte *esc_law = "";
4850        byte *pty_cai = "";
4851        byte *esc_cr  = "";
4852        byte *esc_profile = "";
4853
4854        byte facility[256];
4855        PLCI *tplci = NULL;
4856        byte chi[] = "\x02\x18\x01";
4857        byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4858        byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4859        /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4860        /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4861        /* SMSG is situated at the end because its 0 (for compatibility reasons */
4862        /* (see Info_Mask Bit 4, first IE. then the message type)           */
4863        word parms_id[] =
4864                {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4865                 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4866                 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4867                 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4868        /* 14 FTY repl by ESC_CHI */
4869        /* 18 PI  repl by ESC_LAW */
4870        /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4871        word multi_fac_id[] = {1, FTY};
4872        word multi_pi_id[]  = {1, PI};
4873        word multi_CiPN_id[]  = {1, OAD};
4874        word multi_ssext_id[]  = {1, ESC_SSEXT};
4875
4876        word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4877
4878        byte *cau;
4879        word ncci;
4880        byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4881        byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4882        byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4883        byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\x00\x00\x00\x00";
4884        byte force_mt_info = false;
4885        byte dir;
4886        dword d;
4887        word w;
4888
4889        a = plci->adapter;
4890        Id = ((word)plci->Id << 8) | a->Id;
4891        PUT_WORD(&SS_Ind[4], 0x0000);
4892
4893        if (plci->sig_remove_id)
4894        {
4895                plci->Sig.RNR = 2; /* discard */
4896                dbug(1, dprintf("SIG discard while remove pending"));
4897                return;
4898        }
4899        if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4900        dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4901                        Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4902        if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4903        {
4904                plci->Sig.RNR = 1;
4905                return;
4906        }
4907        if (plci->Sig.Ind == HANGUP && plci->channels)
4908        {
4909                plci->Sig.RNR = 1;
4910                plci->hangup_flow_ctrl_timer++;
4911                /* recover the network layer after timeout */
4912                if (plci->hangup_flow_ctrl_timer == 100)
4913                {
4914                        dbug(1, dprintf("Exceptional disc"));
4915                        plci->Sig.RNR = 0;
4916                        plci->hangup_flow_ctrl_timer = 0;
4917                        for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4918                        {
4919                                if (a->ncci_plci[ncci] == plci->Id)
4920                                {
4921                                        cleanup_ncci_data(plci, ncci);
4922                                        if (plci->channels)plci->channels--;
4923                                        if (plci->appl)
4924                                                sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4925                                }
4926                        }
4927                        if (plci->appl)
4928                                sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4929                        plci_remove(plci);
4930                        plci->State = IDLE;
4931                }
4932                return;
4933        }
4934
4935        /* do first parse the info with no OAD in, because OAD will be converted */
4936        /* first the multiple facility IE, then mult. progress ind.              */
4937        /* then the parameters for the info_ind + conn_ind                       */
4938        IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4939        IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4940        IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4941
4942        IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4943
4944        IndParse(plci, parms_id, parms, 0);
4945        IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4946        esc_chi  = parms[14];
4947        esc_law  = parms[18];
4948        pty_cai  = parms[24];
4949        esc_cr   = parms[25];
4950        esc_profile = parms[27];
4951        if (esc_cr[0] && plci)
4952        {
4953                if (plci->cr_enquiry && plci->appl)
4954                {
4955                        plci->cr_enquiry = false;
4956                        /* d = MANU_ID            */
4957                        /* w = m_command          */
4958                        /* b = total length       */
4959                        /* b = indication type    */
4960                        /* b = length of all IEs  */
4961                        /* b = IE1                */
4962                        /* S = IE1 length + cont. */
4963                        /* b = IE2                */
4964                        /* S = IE2 length + cont. */
4965                        sendf(plci->appl,
4966                              _MANUFACTURER_I,
4967                              Id,
4968                              0,
4969                              "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4970                              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);
4971                }
4972        }
4973        /* create the additional info structure                                  */
4974        add_i[1] = parms[15]; /* KEY of additional info */
4975        add_i[2] = parms[11]; /* UUI of additional info */
4976        ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4977
4978        /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4979        /* indication returns by the card if requested by the function           */
4980        /* AutomaticLaw() after driver init                                      */
4981        if (a->automatic_law < 4)
4982        {
4983                if (esc_law[0]) {
4984                        if (esc_law[2]) {
4985                                dbug(0, dprintf("u-Law selected"));
4986                                a->u_law = 1;
4987                        }
4988                        else {
4989                                dbug(0, dprintf("a-Law selected"));
4990                                a->u_law = 0;
4991                        }
4992                        a->automatic_law = 4;
4993                        if (plci == a->automatic_lawPLCI) {
4994                                plci->internal_command = 0;
4995                                sig_req(plci, REMOVE, 0);
4996                                send_req(plci);
4997                                a->automatic_lawPLCI = NULL;
4998                        }
4999                }
5000                if (esc_profile[0])
5001                {
5002                        dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
5003                                        UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
5004                                        GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
5005                                        GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
5006
5007                        a->profile.Global_Options &= 0x000000ffL;
5008                        a->profile.B1_Protocols &= 0x000003ffL;
5009                        a->profile.B2_Protocols &= 0x00001fdfL;
5010                        a->profile.B3_Protocols &= 0x000000b7L;
5011
5012                        a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
5013                                GL_BCHANNEL_OPERATION_SUPPORTED;
5014                        a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
5015                        a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
5016                        a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
5017                        a->manufacturer_features = GET_DWORD(&esc_profile[46]);
5018                        a->man_profile.private_options = 0;
5019
5020                        if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5021                        {
5022                                a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5023                                a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5024                        }
5025
5026
5027                        if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5028                                a->man_profile.private_options |= 1L << PRIVATE_RTP;
5029                        a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
5030                        a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
5031
5032
5033                        if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5034                                a->man_profile.private_options |= 1L << PRIVATE_T38;
5035
5036
5037                        if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5038                                a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5039
5040
5041                        if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5042                                a->man_profile.private_options |= 1L << PRIVATE_V18;
5043
5044
5045                        if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5046                                a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5047
5048
5049                        if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5050                                a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5051
5052
5053                        if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5054                                a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5055
5056
5057                        if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5058                                a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5059
5060
5061                        if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5062                                a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5063
5064                }
5065                else
5066                {
5067                        a->profile.Global_Options &= 0x0000007fL;
5068                        a->profile.B1_Protocols &= 0x000003dfL;
5069                        a->profile.B2_Protocols &= 0x00001adfL;
5070                        a->profile.B3_Protocols &= 0x000000b7L;
5071                        a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5072                }
5073                if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5074                                                MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5075                {
5076                        a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5077                }
5078                a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5079                dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
5080                                UnMapController(a->Id), a->profile.Global_Options,
5081                                a->profile.B1_Protocols, a->profile.B2_Protocols,
5082                                a->profile.B3_Protocols, a->manufacturer_features));
5083        }
5084        /* codec plci for the handset/hook state support is just an internal id  */
5085        if (plci != a->AdvCodecPLCI)
5086        {
5087                force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
5088                force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
5089                SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5090                SendInfo(plci, Id, parms, force_mt_info);
5091
5092                VSwitchReqInd(plci, Id, multi_vswitch_parms);
5093
5094        }
5095
5096        /* switch the codec to the b-channel                                     */
5097        if (esc_chi[0] && plci && !plci->SuppState) {
5098                plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5099                mixer_set_bchannel_id_esc(plci, plci->b_channel);
5100                dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
5101                if (plci->tel == ADV_VOICE && plci->appl) {
5102                        SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5103                }
5104        }
5105
5106        if (plci->appl) plci->appl->Number++;
5107
5108        switch (plci->Sig.Ind) {
5109                /* Response to Get_Supported_Services request */
5110        case S_SUPPORTED:
5111                dbug(1, dprintf("S_Supported"));
5112                if (!plci->appl) break;
5113                if (pty_cai[0] == 4)
5114                {
5115                        PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
5116                }
5117                else
5118                {
5119                        PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5120                }
5121                PUT_WORD(&CF_Ind[1], 0);
5122                PUT_WORD(&CF_Ind[4], 0);
5123                sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
5124                plci_remove(plci);
5125                break;
5126
5127                /* Supplementary Service rejected */
5128        case S_SERVICE_REJ:
5129                dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5130                if (!pty_cai[0]) break;
5131                switch (pty_cai[5])
5132                {
5133                case ECT_EXECUTE:
5134                case THREE_PTY_END:
5135                case THREE_PTY_BEGIN:
5136                        if (!plci->relatedPTYPLCI) break;
5137                        tplci = plci->relatedPTYPLCI;
5138                        rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5139                        if (tplci->tel) rId |= EXT_CONTROLLER;
5140                        if (pty_cai[5] == ECT_EXECUTE)
5141                        {
5142                                PUT_WORD(&SS_Ind[1], S_ECT);
5143
5144                                plci->vswitchstate = 0;
5145                                plci->relatedPTYPLCI->vswitchstate = 0;
5146
5147                        }
5148                        else
5149                        {
5150                                PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5151                        }
5152                        if (pty_cai[2] != 0xff)
5153                        {
5154                                PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5155                        }
5156                        else
5157                        {
5158                                PUT_WORD(&SS_Ind[4], 0x300E);
5159                        }
5160                        plci->relatedPTYPLCI = NULL;
5161                        plci->ptyState = 0;
5162                        sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5163                        break;
5164
5165                case CALL_DEFLECTION:
5166                        if (pty_cai[2] != 0xff)
5167                        {
5168                                PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5169                        }
5170                        else
5171                        {
5172                                PUT_WORD(&SS_Ind[4], 0x300E);
5173                        }
5174                        PUT_WORD(&SS_Ind[1], pty_cai[5]);
5175                        for (i = 0; i < max_appl; i++)
5176                        {
5177                                if (application[i].CDEnable)
5178                                {
5179                                        if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5180                                        application[i].CDEnable = false;
5181                                }
5182                        }
5183                        break;
5184
5185                case DEACTIVATION_DIVERSION:
5186                case ACTIVATION_DIVERSION:
5187                case DIVERSION_INTERROGATE_CFU:
5188                case DIVERSION_INTERROGATE_CFB:
5189                case DIVERSION_INTERROGATE_CFNR:
5190                case DIVERSION_INTERROGATE_NUM:
5191                case CCBS_REQUEST:
5192                case CCBS_DEACTIVATE:
5193                case CCBS_INTERROGATE:
5194                        if (!plci->appl) break;
5195                        if (pty_cai[2] != 0xff)
5196                        {
5197                                PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5198                        }
5199                        else
5200                        {
5201                                PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5202                        }
5203                        switch (pty_cai[5])
5204                        {
5205                        case DEACTIVATION_DIVERSION:
5206                                dbug(1, dprintf("Deact_Div"));
5207                                Interr_Err_Ind[0] = 0x9;
5208                                Interr_Err_Ind[3] = 0x6;
5209                                PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5210                                break;
5211                        case ACTIVATION_DIVERSION:
5212                                dbug(1, dprintf("Act_Div"));
5213                                Interr_Err_Ind[0] = 0x9;
5214                                Interr_Err_Ind[3] = 0x6;
5215                                PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5216                                break;
5217                        case DIVERSION_INTERROGATE_CFU:
5218                        case DIVERSION_INTERROGATE_CFB:
5219                        case DIVERSION_INTERROGATE_CFNR:
5220                                dbug(1, dprintf("Interr_Div"));
5221                                Interr_Err_Ind[0] = 0xa;
5222                                Interr_Err_Ind[3] = 0x7;
5223                                PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5224                                break;
5225                        case DIVERSION_INTERROGATE_NUM:
5226                                dbug(1, dprintf("Interr_Num"));
5227                                Interr_Err_Ind[0] = 0xa;
5228                                Interr_Err_Ind[3] = 0x7;
5229                                PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5230                                break;
5231                        case CCBS_REQUEST:
5232                                dbug(1, dprintf("CCBS Request"));
5233                                Interr_Err_Ind[0] = 0xd;
5234                                Interr_Err_Ind[3] = 0xa;
5235                                PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5236                                break;
5237                        case CCBS_DEACTIVATE:
5238                                dbug(1, dprintf("CCBS Deactivate"));
5239                                Interr_Err_Ind[0] = 0x9;
5240                                Interr_Err_Ind[3] = 0x6;
5241                                PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5242                                break;
5243                        case CCBS_INTERROGATE:
5244                                dbug(1, dprintf("CCBS Interrogate"));
5245                                Interr_Err_Ind[0] = 0xb;
5246                                Interr_Err_Ind[3] = 0x8;
5247                                PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5248                                break;
5249                        }
5250                        PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5251                        sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5252                        plci_remove(plci);
5253                        break;
5254                case ACTIVATION_MWI:
5255                case DEACTIVATION_MWI:
5256                        if (pty_cai[5] == ACTIVATION_MWI)
5257                        {
5258                                PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5259                        }
5260                        else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5261
5262                        if (pty_cai[2] != 0xff)
5263                        {
5264                                PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5265                        }
5266                        else
5267                        {
5268                                PUT_WORD(&SS_Ind[4], 0x300E);
5269                        }
5270
5271                        if (plci->cr_enquiry)
5272                        {
5273                                sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5274                                plci_remove(plci);
5275                        }
5276                        else
5277                        {
5278                                sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5279                        }
5280                        break;
5281                case CONF_ADD: /* ERROR */
5282                case CONF_BEGIN:
5283                case CONF_DROP:
5284                case CONF_ISOLATE:
5285                case CONF_REATTACH:
5286                        CONF_Ind[0] = 9;
5287                        CONF_Ind[3] = 6;
5288                        switch (pty_cai[5])
5289                        {
5290                        case CONF_BEGIN:
5291                                PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5292                                plci->ptyState = 0;
5293                                break;
5294                        case CONF_DROP:
5295                                CONF_Ind[0] = 5;
5296                                CONF_Ind[3] = 2;
5297                                PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5298                                plci->ptyState = CONNECTED;
5299                                break;
5300                        case CONF_ISOLATE:
5301                                CONF_Ind[0] = 5;
5302                                CONF_Ind[3] = 2;
5303                                PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5304                                plci->ptyState = CONNECTED;
5305                                break;
5306                        case CONF_REATTACH:
5307                                CONF_Ind[0] = 5;
5308                                CONF_Ind[3] = 2;
5309                                PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5310                                plci->ptyState = CONNECTED;
5311                                break;
5312                        case CONF_ADD:
5313                                PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5314                                plci->relatedPTYPLCI = NULL;
5315                                tplci = plci->relatedPTYPLCI;
5316                                if (tplci) tplci->ptyState = CONNECTED;
5317                                plci->ptyState = CONNECTED;
5318                                break;
5319                        }
5320
5321                        if (pty_cai[2] != 0xff)
5322                        {
5323                                PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5324                        }
5325                        else
5326                        {
5327                                PUT_WORD(&CONF_Ind[4], 0x3303); /* Time-out: network did not respond
5328                                                                  within the required time */
5329                        }
5330
5331                        PUT_DWORD(&CONF_Ind[6], 0x0);
5332                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5333                        break;
5334                }
5335                break;
5336
5337                /* Supplementary Service indicates success */
5338        case S_SERVICE:
5339                dbug(1, dprintf("Service_Ind"));
5340                PUT_WORD(&CF_Ind[4], 0);
5341                switch (pty_cai[5])
5342                {
5343                case THREE_PTY_END:
5344                case THREE_PTY_BEGIN:
5345                case ECT_EXECUTE:
5346                        if (!plci->relatedPTYPLCI) break;
5347                        tplci = plci->relatedPTYPLCI;
5348                        rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5349                        if (tplci->tel) rId |= EXT_CONTROLLER;
5350                        if (pty_cai[5] == ECT_EXECUTE)
5351                        {
5352                                PUT_WORD(&SS_Ind[1], S_ECT);
5353
5354                                if (plci->vswitchstate != 3)
5355                                {
5356
5357                                        plci->ptyState = IDLE;
5358                                        plci->relatedPTYPLCI = NULL;
5359                                        plci->ptyState = 0;
5360
5361                                }
5362
5363                                dbug(1, dprintf("ECT OK"));
5364                                sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5365
5366
5367
5368                        }
5369                        else
5370                        {
5371                                switch (plci->ptyState)
5372                                {
5373                                case S_3PTY_BEGIN:
5374                                        plci->ptyState = CONNECTED;
5375                                        dbug(1, dprintf("3PTY ON"));
5376                                        break;
5377
5378                                case S_3PTY_END:
5379                                        plci->ptyState = IDLE;
5380                                        plci->relatedPTYPLCI = NULL;
5381                                        plci->ptyState = 0;
5382                                        dbug(1, dprintf("3PTY OFF"));
5383                                        break;
5384                                }
5385                                PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5386                                sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5387                        }
5388                        break;
5389
5390                case CALL_DEFLECTION:
5391                        PUT_WORD(&SS_Ind[1], pty_cai[5]);
5392                        for (i = 0; i < max_appl; i++)
5393                        {
5394                                if (application[i].CDEnable)
5395                                {
5396                                        if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5397                                        application[i].CDEnable = false;
5398                                }
5399                        }
5400                        break;
5401
5402                case DEACTIVATION_DIVERSION:
5403                case ACTIVATION_DIVERSION:
5404                        if (!plci->appl) break;
5405                        PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5406                        PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5407                        sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5408                        plci_remove(plci);
5409                        break;
5410
5411                case DIVERSION_INTERROGATE_CFU:
5412                case DIVERSION_INTERROGATE_CFB:
5413                case DIVERSION_INTERROGATE_CFNR:
5414                case DIVERSION_INTERROGATE_NUM:
5415                case CCBS_REQUEST:
5416                case CCBS_DEACTIVATE:
5417                case CCBS_INTERROGATE:
5418                        if (!plci->appl) break;
5419                        switch (pty_cai[5])
5420                        {
5421                        case DIVERSION_INTERROGATE_CFU:
5422                        case DIVERSION_INTERROGATE_CFB:
5423                        case DIVERSION_INTERROGATE_CFNR:
5424                                dbug(1, dprintf("Interr_Div"));
5425                                PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5426                                pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5427                                break;
5428                        case DIVERSION_INTERROGATE_NUM:
5429                                dbug(1, dprintf("Interr_Num"));
5430                                PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5431                                pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5432                                break;
5433                        case CCBS_REQUEST:
5434                                dbug(1, dprintf("CCBS Request"));
5435                                PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5436                                pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5437                                break;
5438                        case CCBS_DEACTIVATE:
5439                                dbug(1, dprintf("CCBS Deactivate"));
5440                                PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5441                                pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5442                                break;
5443                        case CCBS_INTERROGATE:
5444                                dbug(1, dprintf("CCBS Interrogate"));
5445                                PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5446                                pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5447                                break;
5448                        }
5449                        PUT_WORD(&pty_cai[4], 0); /* Supplementary Service Reason */
5450                        PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5451                        sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5452                        plci_remove(plci);
5453                        break;
5454
5455                case ACTIVATION_MWI:
5456                case DEACTIVATION_MWI:
5457                        if (pty_cai[5] == ACTIVATION_MWI)
5458                        {
5459                                PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5460                        }
5461                        else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5462                        if (plci->cr_enquiry)
5463                        {
5464                                sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5465                                plci_remove(plci);
5466                        }
5467                        else
5468                        {
5469                                sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5470                        }
5471                        break;
5472                case MWI_INDICATION:
5473                        if (pty_cai[0] >= 0x12)
5474                        {
5475                                PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5476                                pty_cai[2] = pty_cai[0] - 2; /* len Parameter */
5477                                pty_cai[5] = pty_cai[0] - 5; /* Supplementary Service-specific parameter len */
5478                                if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5479                                {
5480                                        if (plci->internal_command == GET_MWI_STATE) /* result on Message Waiting Listen */
5481                                        {
5482                                                sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5483                                                plci_remove(plci);
5484                                                return;
5485                                        }
5486                                        else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5487                                        pty_cai[0] = 0;
5488                                }
5489                                else
5490                                {
5491                                        for (i = 0; i < max_appl; i++)
5492                                        {
5493                                                if (a->Notification_Mask[i]&SMASK_MWI)
5494                                                {
5495                                                        sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5496                                                        pty_cai[0] = 0;
5497                                                }
5498                                        }
5499                                }
5500
5501                                if (!pty_cai[0])
5502                                { /* acknowledge */
5503                                        facility[2] = 0; /* returncode */
5504                                }
5505                                else facility[2] = 0xff;
5506                        }
5507                        else
5508                        {
5509                                /* reject */
5510                                facility[2] = 0xff; /* returncode */
5511                        }
5512                        facility[0] = 2;
5513                        facility[1] = MWI_RESPONSE; /* Function */
5514                        add_p(plci, CAI, facility);
5515                        add_p(plci, ESC, multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5516                        sig_req(plci, S_SERVICE, 0);
5517                        send_req(plci);
5518                        plci->command = 0;
5519                        next_internal_command(Id, plci);
5520                        break;
5521                case CONF_ADD: /* OK */
5522                case CONF_BEGIN:
5523                case CONF_DROP:
5524                case CONF_ISOLATE:
5525                case CONF_REATTACH:
5526                case CONF_PARTYDISC:
5527                        CONF_Ind[0] = 9;
5528                        CONF_Ind[3] = 6;
5529                        switch (pty_cai[5])
5530                        {
5531                        case CONF_BEGIN:
5532                                PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5533                                if (pty_cai[0] == 6)
5534                                {
5535                                        d = pty_cai[6];
5536                                        PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5537                                }
5538                                else
5539                                {
5540                                        PUT_DWORD(&CONF_Ind[6], 0x0);
5541                                }
5542                                break;
5543                        case CONF_ISOLATE:
5544                                PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5545                                CONF_Ind[0] = 5;
5546                                CONF_Ind[3] = 2;
5547                                break;
5548                        case CONF_REATTACH:
5549                                PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5550                                CONF_Ind[0] = 5;
5551                                CONF_Ind[3] = 2;
5552                                break;
5553                        case CONF_DROP:
5554                                PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5555                                CONF_Ind[0] = 5;
5556                                CONF_Ind[3] = 2;
5557                                break;
5558                        case CONF_ADD:
5559                                PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5560                                d = pty_cai[6];
5561                                PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5562                                tplci = plci->relatedPTYPLCI;
5563                                if (tplci) tplci->ptyState = CONNECTED;
5564                                break;
5565                        case CONF_PARTYDISC:
5566                                CONF_Ind[0] = 7;
5567                                CONF_Ind[3] = 4;
5568                                PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5569                                d = pty_cai[6];
5570                                PUT_DWORD(&CONF_Ind[4], d); /* PartyID */
5571                                break;
5572                        }
5573                        plci->ptyState = CONNECTED;
5574                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5575                        break;
5576                case CCBS_INFO_RETAIN:
5577                case CCBS_ERASECALLLINKAGEID:
5578                case CCBS_STOP_ALERTING:
5579                        CONF_Ind[0] = 5;
5580                        CONF_Ind[3] = 2;
5581                        switch (pty_cai[5])
5582                        {
5583                        case CCBS_INFO_RETAIN:
5584                                PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5585                                break;
5586                        case CCBS_STOP_ALERTING:
5587                                PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5588                                break;
5589                        case CCBS_ERASECALLLINKAGEID:
5590                                PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5591                                CONF_Ind[0] = 7;
5592                                CONF_Ind[3] = 4;
5593                                CONF_Ind[6] = 0;
5594                                CONF_Ind[7] = 0;
5595                                break;
5596                        }
5597                        w = pty_cai[6];
5598                        PUT_WORD(&CONF_Ind[4], w); /* PartyID */
5599
5600                        if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5601                        {
5602                                sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5603                        }
5604                        else
5605                        {
5606                                for (i = 0; i < max_appl; i++)
5607                                        if (a->Notification_Mask[i] & SMASK_CCBS)
5608                                                sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5609                        }
5610                        break;
5611                }
5612                break;
5613        case CALL_HOLD_REJ:
5614                cau = parms[7];
5615                if (cau)
5616                {
5617                        i = _L3_CAUSE | cau[2];
5618                        if (cau[2] == 0) i = 0x3603;
5619                }
5620                else
5621                {
5622                        i = 0x3603;
5623                }
5624                PUT_WORD(&SS_Ind[1], S_HOLD);
5625                PUT_WORD(&SS_Ind[4], i);
5626                if (plci->SuppState == HOLD_REQUEST)
5627                {
5628                        plci->SuppState = IDLE;
5629                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5630                }
5631                break;
5632
5633        case CALL_HOLD_ACK:
5634                if (plci->SuppState == HOLD_REQUEST)
5635                {
5636                        plci->SuppState = CALL_HELD;
5637                        CodecIdCheck(a, plci);
5638                        start_internal_command(Id, plci, hold_save_command);
5639                }
5640                break;
5641
5642        case CALL_RETRIEVE_REJ:
5643                cau = parms[7];
5644                if (cau)
5645                {
5646                        i = _L3_CAUSE | cau[2];
5647                        if (cau[2] == 0) i = 0x3603;
5648                }
5649                else
5650                {
5651                        i = 0x3603;
5652                }
5653                PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5654                PUT_WORD(&SS_Ind[4], i);
5655                if (plci->SuppState == RETRIEVE_REQUEST)
5656                {
5657                        plci->SuppState = CALL_HELD;
5658                        CodecIdCheck(a, plci);
5659                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5660                }
5661                break;
5662
5663        case CALL_RETRIEVE_ACK:
5664                PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5665                if (plci->SuppState == RETRIEVE_REQUEST)
5666                {
5667                        plci->SuppState = IDLE;
5668                        plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5669                        plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5670                        if (plci->tel)
5671                        {
5672                                mixer_set_bchannel_id_esc(plci, plci->b_channel);
5673                                dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5674                                SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5675                                if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5676                                {
5677                                        dbug(1, dprintf("Get B-ch"));
5678                                        start_internal_command(Id, plci, retrieve_restore_command);
5679                                }
5680                                else
5681                                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5682                        }
5683                        else
5684                                start_internal_command(Id, plci, retrieve_restore_command);
5685                }
5686                break;
5687
5688        case INDICATE_IND:
5689                if (plci->State != LISTENING) {
5690                        sig_req(plci, HANGUP, 0);
5691                        send_req(plci);
5692                        break;
5693                }
5694                cip = find_cip(a, parms[4], parms[6]);
5695                cip_mask = 1L << cip;
5696                dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5697                clear_c_ind_mask(plci);
5698                if (!remove_started && !a->adapter_disabled)
5699                {
5700                        set_c_ind_mask_bit(plci, MAX_APPL);
5701                        group_optimization(a, plci);
5702                        for (i = 0; i < max_appl; i++) {
5703                                if (application[i].Id
5704                                    && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5705                                    && CPN_filter_ok(parms[0], a, i)
5706                                    && test_group_ind_mask_bit(plci, i)) {
5707                                        dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5708                                        set_c_ind_mask_bit(plci, i);
5709                                        dump_c_ind_mask(plci);
5710                                        plci->State = INC_CON_PENDING;
5711                                        plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5712                                                CALL_DIR_IN | CALL_DIR_ANSWER;
5713                                        if (esc_chi[0]) {
5714                                                plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5715                                                mixer_set_bchannel_id_esc(plci, plci->b_channel);
5716                                        }
5717                                        /* if a listen on the ext controller is done, check if hook states */
5718                                        /* are supported or if just a on board codec must be activated     */
5719                                        if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5720                                                if (a->profile.Global_Options & HANDSET)
5721                                                        plci->tel = ADV_VOICE;
5722                                                else if (a->profile.Global_Options & ON_BOARD_CODEC)
5723                                                        plci->tel = CODEC;
5724                                                if (plci->tel) Id |= EXT_CONTROLLER;
5725                                                a->codec_listen[i] = plci;
5726                                        }
5727
5728                                        sendf(&application[i], _CONNECT_I, Id, 0,
5729                                              "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5730                                              parms[0],    /* CalledPartyNumber   */
5731                                              multi_CiPN_parms[0],    /* CallingPartyNumber  */
5732                                              parms[2],    /* CalledPartySubad    */
5733                                              parms[3],    /* CallingPartySubad   */
5734                                              parms[4],    /* BearerCapability    */
5735                                              parms[5],    /* LowLC               */
5736                                              parms[6],    /* HighLC              */
5737                                              ai_len,      /* nested struct add_i */
5738                                              add_i[0],    /* B channel info    */
5739                                              add_i[1],    /* keypad facility   */
5740                                              add_i[2],    /* user user data    */
5741                                              add_i[3],    /* nested facility   */
5742                                              multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5743                                                );
5744                                        SendSSExtInd(&application[i],
5745                                                     plci,
5746                                                     Id,
5747                                                     multi_ssext_parms);
5748                                        SendSetupInfo(&application[i],
5749                                                      plci,
5750                                                      Id,
5751                                                      parms,
5752                                                      SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5753                                }
5754                        }
5755                        clear_c_ind_mask_bit(plci, MAX_APPL);
5756                        dump_c_ind_mask(plci);
5757                }
5758                if (c_ind_mask_empty(plci)) {
5759                        sig_req(plci, HANGUP, 0);
5760                        send_req(plci);
5761                        plci->State = IDLE;
5762                }
5763                plci->notifiedcall = 0;
5764                a->listen_active--;
5765                listen_check(a);
5766                break;
5767
5768        case CALL_PEND_NOTIFY:
5769                plci->notifiedcall = 1;
5770                listen_check(a);
5771                break;
5772
5773        case CALL_IND:
5774        case CALL_CON:
5775                if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5776                {
5777                        if (plci->internal_command == PERM_COD_CONN_PEND)
5778                        {
5779                                if (plci->State == ADVANCED_VOICE_NOSIG)
5780                                {
5781                                        dbug(1, dprintf("***Codec OK"));
5782                                        if (a->AdvSignalPLCI)
5783                                        {
5784                                                tplci = a->AdvSignalPLCI;
5785                                                if (tplci->spoofed_msg)
5786                                                {
5787                                                        dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5788                                                        tplci->command = 0;
5789                                                        tplci->internal_command = 0;
5790                                                        x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5791                                                        switch (tplci->spoofed_msg)
5792                                                        {
5793                                                        case CALL_RES:
5794                                                                tplci->command = _CONNECT_I | RESPONSE;
5795                                                                api_load_msg(&tplci->saved_msg, saved_parms);
5796                                                                add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5797                                                                if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5798                                                                {
5799                                                                        /* early B3 connect (CIP mask bit 9) no release after a disc */
5800                                                                        add_p(tplci, LLI, "\x01\x01");
5801                                                                }
5802                                                                add_s(tplci, CONN_NR, &saved_parms[2]);
5803                                                                add_s(tplci, LLC, &saved_parms[4]);
5804                                                                add_ai(tplci, &saved_parms[5]);
5805                                                                tplci->State = INC_CON_ACCEPT;
5806                                                                sig_req(tplci, CALL_RES, 0);
5807                                                                send_req(tplci);
5808                                                                break;
5809
5810                                                        case AWAITING_SELECT_B:
5811                                                                dbug(1, dprintf("Select_B continue"));
5812                                                                start_internal_command(x_Id, tplci, select_b_command);
5813                                                                break;
5814
5815                                                        case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5816                                                                if (!tplci->Sig.Id)
5817                                                                {
5818                                                                        dbug(1, dprintf("No SigID!"));
5819                                                                        sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5820                                                                        plci_remove(tplci);
5821                                                                        break;
5822                                                                }
5823                                                                tplci->command = _MANUFACTURER_R;
5824                                                                api_load_msg(&tplci->saved_msg, saved_parms);
5825                                                                dir = saved_parms[2].info[0];
5826                                                                if (dir == 1) {
5827                                                                        sig_req(tplci, CALL_REQ, 0);
5828                                                                }
5829                                                                else if (!dir) {
5830                                                                        sig_req(tplci, LISTEN_REQ, 0);
5831                                                                }
5832                                                                send_req(tplci);
5833                                                                sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5834                                                                break;
5835
5836                                                        case (CALL_REQ | AWAITING_MANUF_CON):
5837                                                                sig_req(tplci, CALL_REQ, 0);
5838                                                                send_req(tplci);
5839                                                                break;
5840
5841                                                        case CALL_REQ:
5842                                                                if (!tplci->Sig.Id)
5843                                                                {
5844                                                                        dbug(1, dprintf("No SigID!"));
5845                                                                        sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5846                                                                        plci_remove(tplci);
5847                                                                        break;
5848                                                                }
5849                                                                tplci->command = _CONNECT_R;
5850                                                                api_load_msg(&tplci->saved_msg, saved_parms);
5851                                                                add_s(tplci, CPN, &saved_parms[1]);
5852                                                                add_s(tplci, DSA, &saved_parms[3]);
5853                                                                add_ai(tplci, &saved_parms[9]);
5854                                                                sig_req(tplci, CALL_REQ, 0);
5855                                                                send_req(tplci);
5856                                                                break;
5857
5858                                                        case CALL_RETRIEVE:
5859                                                                tplci->command = C_RETRIEVE_REQ;
5860                                                                sig_req(tplci, CALL_RETRIEVE, 0);
5861                                                                send_req(tplci);
5862                                                                break;
5863                                                        }
5864                                                        tplci->spoofed_msg = 0;
5865                                                        if (tplci->internal_command == 0)
5866                                                                next_internal_command(x_Id, tplci);
5867                                                }
5868                                        }
5869                                        next_internal_command(Id, plci);
5870                                        break;
5871                                }
5872                                dbug(1, dprintf("***Codec Hook Init Req"));
5873                                plci->internal_command = PERM_COD_HOOK;
5874                                add_p(plci, FTY, "\x01\x09");             /* Get Hook State*/
5875                                sig_req(plci, TEL_CTRL, 0);
5876                                send_req(plci);
5877                        }
5878                }
5879                else if (plci->command != _MANUFACTURER_R  /* old style permanent connect */
5880                         && plci->State != INC_ACT_PENDING)
5881                {
5882                        mixer_set_bchannel_id_esc(plci, plci->b_channel);
5883                        if (plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5884                        {
5885                                chi[2] = plci->b_channel;
5886                                SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5887                        }
5888                        sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5889                        plci->State = INC_ACT_PENDING;
5890                }
5891                break;
5892
5893        case TEL_CTRL:
5894                ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5895                if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5896                        switch (ie[1] & 0x91) {
5897                        case 0x80:   /* hook off */
5898                        case 0x81:
5899                                if (plci->internal_command == PERM_COD_HOOK)
5900                                {
5901                                        dbug(1, dprintf("init:hook_off"));
5902                                        plci->hook_state = ie[1];
5903                                        next_internal_command(Id, plci);
5904                                        break;
5905                                }
5906                                else /* ignore doubled hook indications */
5907                                {
5908                                        if (((plci->hook_state) & 0xf0) == 0x80)
5909                                        {
5910                                                dbug(1, dprintf("ignore hook"));
5911                                                break;
5912                                        }
5913                                        plci->hook_state = ie[1]&0x91;
5914                                }
5915                                /* check for incoming call pending */
5916                                /* and signal '+'.Appl must decide */
5917                                /* with connect_res if call must   */
5918                                /* accepted or not                 */
5919                                for (i = 0, tplci = NULL; i < max_appl; i++) {
5920                                        if (a->codec_listen[i]
5921                                            && (a->codec_listen[i]->State == INC_CON_PENDING
5922                                                || a->codec_listen[i]->State == INC_CON_ALERT)) {
5923                                                tplci = a->codec_listen[i];
5924                                                tplci->appl = &application[i];
5925                                        }
5926                                }
5927                                /* no incoming call, do outgoing call */
5928                                /* and signal '+' if outg. setup   */
5929                                if (!a->AdvSignalPLCI && !tplci) {
5930                                        if ((i = get_plci(a))) {
5931                                                a->AdvSignalPLCI = &a->plci[i - 1];
5932                                                tplci = a->AdvSignalPLCI;
5933                                                tplci->tel  = ADV_VOICE;
5934                                                PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5935                                                if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5936                                                        /* early B3 connect (CIP mask bit 9) no release after a disc */
5937                                                        add_p(tplci, LLI, "\x01\x01");
5938                                                }
5939                                                add_p(tplci, CAI, voice_cai);
5940                                                add_p(tplci, OAD, a->TelOAD);
5941                                                add_p(tplci, OSA, a->TelOSA);
5942                                                add_p(tplci, SHIFT | 6, NULL);
5943                                                add_p(tplci, SIN, "\x02\x01\x00");
5944                                                add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5945                                                sig_req(tplci, ASSIGN, DSIG_ID);
5946                                                a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5947                                                a->AdvSignalPLCI->command = 0;
5948                                                tplci->appl = a->AdvSignalAppl;
5949                                                tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5950                                                send_req(tplci);
5951                                        }
5952
5953                                }
5954
5955                                if (!tplci) break;
5956                                Id = ((word)tplci->Id << 8) | a->Id;
5957                                Id |= EXT_CONTROLLER;
5958                                sendf(tplci->appl,
5959                                      _FACILITY_I,
5960                                      Id,
5961                                      0,
5962                                      "ws", (word)0, "\x01+");
5963                                break;
5964
5965                        case 0x90:   /* hook on  */
5966                        case 0x91:
5967                                if (plci->internal_command == PERM_COD_HOOK)
5968                                {
5969                                        dbug(1, dprintf("init:hook_on"));
5970                                        plci->hook_state = ie[1] & 0x91;
5971                                        next_internal_command(Id, plci);
5972                                        break;
5973                                }
5974                                else /* ignore doubled hook indications */
5975                                {
5976                                        if (((plci->hook_state) & 0xf0) == 0x90) break;
5977                                        plci->hook_state = ie[1] & 0x91;
5978                                }
5979                                /* hangup the adv. voice call and signal '-' to the appl */
5980                                if (a->AdvSignalPLCI) {
5981                                        Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5982                                        if (plci->tel) Id |= EXT_CONTROLLER;
5983                                        sendf(a->AdvSignalAppl,
5984                                              _FACILITY_I,
5985                                              Id,
5986                                              0,
5987                                              "ws", (word)0, "\x01-");
5988                                        a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5989                                        a->AdvSignalPLCI->command = 0;
5990                                        sig_req(a->AdvSignalPLCI, HANGUP, 0);
5991                                        send_req(a->AdvSignalPLCI);
5992                                }
5993                                break;
5994                        }
5995                }
5996                break;
5997
5998        case RESUME:
5999                clear_c_ind_mask_bit(plci, (word)(plci->appl->Id - 1));
6000                PUT_WORD(&resume_cau[4], GOOD);
6001                sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6002                break;
6003
6004        case SUSPEND:
6005                clear_c_ind_mask(plci);
6006
6007                if (plci->NL.Id && !plci->nl_remove_id) {
6008                        mixer_remove(plci);
6009                        nl_req_ncci(plci, REMOVE, 0);
6010                }
6011                if (!plci->sig_remove_id) {
6012                        plci->internal_command = 0;
6013                        sig_req(plci, REMOVE, 0);
6014                }
6015                send_req(plci);
6016                if (!plci->channels) {
6017                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6018                        sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6019                }
6020                break;
6021
6022        case SUSPEND_REJ:
6023                break;
6024
6025        case HANGUP:
6026                plci->hangup_flow_ctrl_timer = 0;
6027                if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
6028                cau = parms[7];
6029                if (cau) {
6030                        i = _L3_CAUSE | cau[2];
6031                        if (cau[2] == 0) i = 0;
6032                        else if (cau[2] == 8) i = _L1_ERROR;
6033                        else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
6034                        else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
6035                }
6036                else {
6037                        i = _L3_ERROR;
6038                }
6039
6040                if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
6041                {
6042                        for (i = 0; i < max_appl; i++)
6043                        {
6044                                if (test_c_ind_mask_bit(plci, i))
6045                                        sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6046                        }
6047                }
6048                else
6049                {
6050                        clear_c_ind_mask(plci);
6051                }
6052                if (!plci->appl)
6053                {
6054                        if (plci->State == LISTENING)
6055                        {
6056                                plci->notifiedcall = 0;
6057                                a->listen_active--;
6058                        }
6059                        plci->State = INC_DIS_PENDING;
6060                        if (c_ind_mask_empty(plci))
6061                        {
6062                                plci->State = IDLE;
6063                                if (plci->NL.Id && !plci->nl_remove_id)
6064                                {
6065                                        mixer_remove(plci);
6066                                        nl_req_ncci(plci, REMOVE, 0);
6067                                }
6068                                if (!plci->sig_remove_id)
6069                                {
6070                                        plci->internal_command = 0;
6071                                        sig_req(plci, REMOVE, 0);
6072                                }
6073                                send_req(plci);
6074                        }
6075                }
6076                else
6077                {
6078                        /* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
6079                        /* result in a second HANGUP! Don't generate another        */
6080                        /* DISCONNECT                                               */
6081                        if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
6082                        {
6083                                if (plci->State == RESUMING)
6084                                {
6085                                        PUT_WORD(&resume_cau[4], i);
6086                                        sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6087                                }
6088                                plci->State = INC_DIS_PENDING;
6089                                sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
6090                        }
6091                }
6092                break;
6093
6094        case SSEXT_IND:
6095                SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
6096                break;
6097
6098        case VSWITCH_REQ:
6099                VSwitchReqInd(plci, Id, multi_vswitch_parms);
6100                break;
6101        case VSWITCH_IND:
6102                if (plci->relatedPTYPLCI &&
6103                    plci->vswitchstate == 3 &&
6104                    plci->relatedPTYPLCI->vswitchstate == 3 &&
6105                    parms[MAXPARMSIDS - 1][0])
6106                {
6107                        add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
6108                        sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
6109                        send_req(plci->relatedPTYPLCI);
6110                }
6111                else VSwitchReqInd(plci, Id, multi_vswitch_parms);
6112                break;
6113
6114        }
6115}
6116
6117
6118static void SendSetupInfo(APPL *appl, PLCI *plci, dword Id, byte **parms, byte Info_Sent_Flag)
6119{
6120        word i;
6121        byte *ie;
6122        word Info_Number;
6123        byte *Info_Element;
6124        word Info_Mask = 0;
6125
6126        dbug(1, dprintf("SetupInfo"));
6127
6128        for (i = 0; i < MAXPARMSIDS; i++) {
6129                ie = parms[i];
6130                Info_Number = 0;
6131                Info_Element = ie;
6132                if (ie[0]) {
6133                        switch (i) {
6134                        case 0:
6135                                dbug(1, dprintf("CPN "));
6136                                Info_Number = 0x0070;
6137                                Info_Mask = 0x80;
6138                                Info_Sent_Flag = true;
6139                                break;
6140                        case 8:  /* display      */
6141                                dbug(1, dprintf("display(%d)", i));
6142                                Info_Number = 0x0028;
6143                                Info_Mask = 0x04;
6144                                Info_Sent_Flag = true;
6145                                break;
6146                        case 16: /* Channel Id */
6147                                dbug(1, dprintf("CHI"));
6148                                Info_Number = 0x0018;
6149                                Info_Mask = 0x100;
6150                                Info_Sent_Flag = true;
6151                                mixer_set_bchannel_id(plci, Info_Element);
6152                                break;
6153                        case 19: /* Redirected Number */
6154                                dbug(1, dprintf("RDN"));
6155                                Info_Number = 0x0074;
6156                                Info_Mask = 0x400;
6157                                Info_Sent_Flag = true;
6158                                break;
6159                        case 20: /* Redirected Number extended */
6160                                dbug(1, dprintf("RDX"));
6161                                Info_Number = 0x0073;
6162                                Info_Mask = 0x400;
6163                                Info_Sent_Flag = true;
6164                                break;
6165                        case 22: /* Redirecing Number  */
6166                                dbug(1, dprintf("RIN"));
6167                                Info_Number = 0x0076;
6168                                Info_Mask = 0x400;
6169                                Info_Sent_Flag = true;
6170                                break;
6171                        default:
6172                                Info_Number = 0;
6173                                break;
6174                        }
6175                }
6176
6177                if (i == MAXPARMSIDS - 2) { /* to indicate the message type "Setup" */
6178                        Info_Number = 0x8000 | 5;
6179                        Info_Mask = 0x10;
6180                        Info_Element = "";
6181                }
6182
6183                if (Info_Sent_Flag && Info_Number) {
6184                        if (plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask) {
6185                                sendf(appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6186                        }
6187                }
6188        }
6189}
6190
6191
6192static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6193{
6194        word i;
6195        word j;
6196        word k;
6197        byte *ie;
6198        word Info_Number;
6199        byte *Info_Element;
6200        word Info_Mask = 0;
6201        static byte charges[5] = {4, 0, 0, 0, 0};
6202        static byte cause[] = {0x02, 0x80, 0x00};
6203        APPL *appl;
6204
6205        dbug(1, dprintf("InfoParse "));
6206
6207        if (
6208                !plci->appl
6209                && !plci->State
6210                && plci->Sig.Ind != NCR_FACILITY
6211                )
6212        {
6213                dbug(1, dprintf("NoParse "));
6214                return;
6215        }
6216        cause[2] = 0;
6217        for (i = 0; i < MAXPARMSIDS; i++) {
6218                ie = parms[i];
6219                Info_Number = 0;
6220                Info_Element = ie;
6221                if (ie[0]) {
6222                        switch (i) {
6223                        case 0:
6224                                dbug(1, dprintf("CPN "));
6225                                Info_Number = 0x0070;
6226                                Info_Mask   = 0x80;
6227                                break;
6228                        case 7: /* ESC_CAU */
6229                                dbug(1, dprintf("cau(0x%x)", ie[2]));
6230                                Info_Number = 0x0008;
6231                                Info_Mask = 0x00;
6232                                cause[2] = ie[2];
6233                                Info_Element = NULL;
6234                                break;
6235                        case 8:  /* display      */
6236                                dbug(1, dprintf("display(%d)", i));
6237                                Info_Number = 0x0028;
6238                                Info_Mask = 0x04;
6239                                break;
6240                        case 9:  /* Date display */
6241                                dbug(1, dprintf("date(%d)", i));
6242                                Info_Number = 0x0029;
6243                                Info_Mask = 0x02;
6244                                break;
6245                        case 10: /* charges */
6246                                for (j = 0; j < 4; j++) charges[1 + j] = 0;
6247                                for (j = 0; j < ie[0] && !(ie[1 + j] & 0x80); j++);
6248                                for (k = 1, j++; j < ie[0] && k <= 4; j++, k++) charges[k] = ie[1 + j];
6249                                Info_Number = 0x4000;
6250                                Info_Mask = 0x40;
6251                                Info_Element = charges;
6252                                break;
6253                        case 11: /* user user info */
6254                                dbug(1, dprintf("uui"));
6255                                Info_Number = 0x007E;
6256                                Info_Mask = 0x08;
6257                                break;
6258                        case 12: /* congestion receiver ready */
6259                                dbug(1, dprintf("clRDY"));
6260                                Info_Number = 0x00B0;
6261                                Info_Mask = 0x08;
6262                                Info_Element = "";
6263                                break;
6264                        case 13: /* congestion receiver not ready */
6265                                dbug(1, dprintf("clNRDY"));
6266                                Info_Number = 0x00BF;
6267                                Info_Mask = 0x08;
6268                                Info_Element = "";
6269                                break;
6270                        case 15: /* Keypad Facility */
6271                                dbug(1, dprintf("KEY"));
6272                                Info_Number = 0x002C;
6273                                Info_Mask = 0x20;
6274                                break;
6275                        case 16: /* Channel Id */
6276                                dbug(1, dprintf("CHI"));
6277                                Info_Number = 0x0018;
6278                                Info_Mask = 0x100;
6279                                mixer_set_bchannel_id(plci, Info_Element);
6280                                break;
6281                        case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6282                                dbug(1, dprintf("q9cau(0x%x)", ie[2]));
6283                                if (!cause[2] || cause[2] < 0x80) break;  /* eg. layer 1 error */
6284                                Info_Number = 0x0008;
6285                                Info_Mask = 0x01;
6286                                if (cause[2] != ie[2]) Info_Element = cause;
6287                                break;
6288                        case 19: /* Redirected Number */
6289                                dbug(1, dprintf("RDN"));
6290                                Info_Number = 0x0074;
6291                                Info_Mask = 0x400;
6292                                break;
6293                        case 22: /* Redirecing Number  */
6294                                dbug(1, dprintf("RIN"));
6295                                Info_Number = 0x0076;
6296                                Info_Mask = 0x400;
6297                                break;
6298                        case 23: /* Notification Indicator  */
6299                                dbug(1, dprintf("NI"));
6300                                Info_Number = (word)NI;
6301                                Info_Mask = 0x210;
6302                                break;
6303                        case 26: /* Call State  */
6304                                dbug(1, dprintf("CST"));
6305                                Info_Number = (word)CST;
6306                                Info_Mask = 0x01; /* do with cause i.e. for now */
6307                                break;
6308                        case MAXPARMSIDS - 2:  /* Escape Message Type, must be the last indication */
6309                                dbug(1, dprintf("ESC/MT[0x%x]", ie[3]));
6310                                Info_Number = 0x8000 | ie[3];
6311                                if (iesent) Info_Mask = 0xffff;
6312                                else  Info_Mask = 0x10;
6313                                Info_Element = "";
6314                                break;
6315                        default:
6316                                Info_Number  = 0;
6317                                Info_Mask    = 0;
6318                                Info_Element = "";
6319                                break;
6320                        }
6321                }
6322
6323                if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6324                {
6325                        for (j = 0; j < max_appl; j++)
6326                        {
6327                                appl = &application[j];
6328                                if (Info_Number
6329                                    && appl->Id
6330                                    && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6331                                {
6332                                        dbug(1, dprintf("NCR_Ind"));
6333                                        iesent = true;
6334                                        sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6335                                }
6336                        }
6337                }
6338                else if (!plci->appl)
6339                { /* overlap receiving broadcast */
6340                        if (Info_Number == CPN
6341                            || Info_Number == KEY
6342                            || Info_Number == NI
6343                            || Info_Number == DSP
6344                            || Info_Number == UUI)
6345                        {
6346                                for (j = 0; j < max_appl; j++)
6347                                {
6348                                        if (test_c_ind_mask_bit(plci, j))
6349                                        {
6350                                                dbug(1, dprintf("Ovl_Ind"));
6351                                                iesent = true;
6352                                                sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6353                                        }
6354                                }
6355                        }
6356                }               /* all other signalling states */
6357                else if (Info_Number
6358                         && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6359                {
6360                        dbug(1, dprintf("Std_Ind"));
6361                        iesent = true;
6362                        sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6363                }
6364        }
6365}
6366
6367
6368static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6369                        dword info_mask, byte setupParse)
6370{
6371        word i;
6372        word j;
6373        byte *ie;
6374        word Info_Number;
6375        byte *Info_Element;
6376        APPL *appl;
6377        word Info_Mask = 0;
6378        byte iesent = 0;
6379
6380        if (
6381                !plci->appl
6382                && !plci->State
6383                && plci->Sig.Ind != NCR_FACILITY
6384                && !setupParse
6385                )
6386        {
6387                dbug(1, dprintf("NoM-IEParse "));
6388                return 0;
6389        }
6390        dbug(1, dprintf("M-IEParse "));
6391
6392        for (i = 0; i < MAX_MULTI_IE; i++)
6393        {
6394                ie = parms[i];
6395                Info_Number = 0;
6396                Info_Element = ie;
6397                if (ie[0])
6398                {
6399                        dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci->Sig.Ind, ie_type));
6400                        Info_Number = (word)ie_type;
6401                        Info_Mask = (word)info_mask;
6402                }
6403
6404                if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6405                {
6406                        for (j = 0; j < max_appl; j++)
6407                        {
6408                                appl = &application[j];
6409                                if (Info_Number
6410                                    && appl->Id
6411                                    && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6412                                {
6413                                        iesent = true;
6414                                        dbug(1, dprintf("Mlt_NCR_Ind"));
6415                                        sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6416                                }
6417                        }
6418                }
6419                else if (!plci->appl && Info_Number)
6420                {                                        /* overlap receiving broadcast */
6421                        for (j = 0; j < max_appl; j++)
6422                        {
6423                                if (test_c_ind_mask_bit(plci, j))
6424                                {
6425                                        iesent = true;
6426                                        dbug(1, dprintf("Mlt_Ovl_Ind"));
6427                                        sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6428                                }
6429                        }
6430                }                                        /* all other signalling states */
6431                else if (Info_Number
6432                         && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6433                {
6434                        iesent = true;
6435                        dbug(1, dprintf("Mlt_Std_Ind"));
6436                        sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6437                }
6438        }
6439        return iesent;
6440}
6441
6442static void SendSSExtInd(APPL *appl, PLCI *plci, dword Id, byte **parms)
6443{
6444        word i;
6445        /* Format of multi_ssext_parms[i][]:
6446           0 byte length
6447           1 byte SSEXTIE
6448           2 byte SSEXT_REQ/SSEXT_IND
6449           3 byte length
6450           4 word SSExtCommand
6451           6... Params
6452        */
6453        if (
6454                plci
6455                && plci->State
6456                && plci->Sig.Ind != NCR_FACILITY
6457                )
6458                for (i = 0; i < MAX_MULTI_IE; i++)
6459                {
6460                        if (parms[i][0] < 6) continue;
6461                        if (parms[i][2] == SSEXT_REQ) continue;
6462
6463                        if (appl)
6464                        {
6465                                parms[i][0] = 0; /* kill it */
6466                                sendf(appl, _MANUFACTURER_I,
6467                                      Id,
6468                                      0,
6469                                      "dwS",
6470                                      _DI_MANU_ID,
6471                                      _DI_SSEXT_CTRL,
6472                                      &parms[i][3]);
6473                        }
6474                        else if (plci->appl)
6475                        {
6476                                parms[i][0] = 0; /* kill it */
6477                                sendf(plci->appl, _MANUFACTURER_I,
6478                                      Id,
6479                                      0,
6480                                      "dwS",
6481                                      _DI_MANU_ID,
6482                                      _DI_SSEXT_CTRL,
6483                                      &parms[i][3]);
6484                        }
6485                }
6486};
6487
6488static void nl_ind(PLCI *plci)
6489{
6490        byte ch;
6491        word ncci;
6492        dword Id;
6493        DIVA_CAPI_ADAPTER *a;
6494        word NCCIcode;
6495        APPL *APPLptr;
6496        word count;
6497        word Num;
6498        word i, ncpi_state;
6499        byte len, ncci_state;
6500        word msg;
6501        word info = 0;
6502        word fax_feature_bits;
6503        byte fax_send_edata_ack;
6504        static byte v120_header_buffer[2 + 3];
6505        static word fax_info[] = {
6506                0,                     /* T30_SUCCESS                        */
6507                _FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
6508                _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
6509                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
6510                _FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
6511                _FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
6512                _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
6513                _FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
6514                _FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
6515                _FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
6516                _FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
6517                _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
6518                _FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
6519                _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
6520                _FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
6521                _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
6522                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
6523                _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
6524                _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
6525                _FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
6526                _FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
6527                _FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
6528                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
6529                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
6530                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
6531                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
6532                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
6533                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
6534                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
6535                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
6536                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
6537                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
6538                _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
6539                0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
6540                0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
6541                0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
6542                _FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
6543                _FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
6544                _FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
6545                _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
6546                _FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
6547                _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6548                _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
6549                _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
6550                _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
6551                _FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
6552                _FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
6553        };
6554
6555        byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6556
6557
6558        static word rtp_info[] = {
6559                GOOD,                  /* RTP_SUCCESS                       */
6560                0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
6561        };
6562
6563        static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6564                {
6565                        0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6566                        0x00000000, 0x00000000, 0x00000000, 0x00000000
6567                };
6568
6569        ch = plci->NL.IndCh;
6570        a = plci->adapter;
6571        ncci = a->ch_ncci[ch];
6572        Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6573        if (plci->tel) Id |= EXT_CONTROLLER;
6574        APPLptr = plci->appl;
6575        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",
6576                        plci->NL.Id, Id, plci->Id, plci->tel, plci->State, ch, plci->channels, plci->NL.Ind & 0x0f));
6577
6578        /* in the case if no connect_active_Ind was sent to the appl we wait for */
6579
6580        if (plci->nl_remove_id)
6581        {
6582                plci->NL.RNR = 2; /* discard */
6583                dbug(1, dprintf("NL discard while remove pending"));
6584                return;
6585        }
6586        if ((plci->NL.Ind & 0x0f) == N_CONNECT)
6587        {
6588                if (plci->State == INC_DIS_PENDING
6589                    || plci->State == OUTG_DIS_PENDING
6590                    || plci->State == IDLE)
6591                {
6592                        plci->NL.RNR = 2; /* discard */
6593                        dbug(1, dprintf("discard n_connect"));
6594                        return;
6595                }
6596                if (plci->State < INC_ACT_PENDING)
6597                {
6598                        plci->NL.RNR = 1; /* flow control */
6599                        channel_x_off(plci, ch, N_XON_CONNECT_IND);
6600                        return;
6601                }
6602        }
6603
6604        if (!APPLptr)                         /* no application or invalid data */
6605        {                                    /* while reloading the DSP        */
6606                dbug(1, dprintf("discard1"));
6607                plci->NL.RNR = 2;
6608                return;
6609        }
6610
6611        if (((plci->NL.Ind & 0x0f) == N_UDATA)
6612            && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6613                || (plci->B2_prot == 7)
6614                || (plci->B3_prot == 7)))
6615        {
6616                plci->ncpi_buffer[0] = 0;
6617
6618                ncpi_state = plci->ncpi_state;
6619                if (plci->NL.complete == 1)
6620                {
6621                        byte *data = &plci->NL.RBuffer->P[0];
6622
6623                        if ((plci->NL.RBuffer->length >= 12)
6624                            && ((*data == DSP_UDATA_INDICATION_DCD_ON)
6625                                || (*data == DSP_UDATA_INDICATION_CTS_ON)))
6626                        {
6627                                word conn_opt, ncpi_opt = 0x00;
6628/*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6629
6630                                if (*data == DSP_UDATA_INDICATION_DCD_ON)
6631                                        plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6632                                if (*data == DSP_UDATA_INDICATION_CTS_ON)
6633                                        plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6634
6635                                data++;    /* indication code */
6636                                data += 2; /* timestamp */
6637                                if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6638                                        ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6639                                data++;    /* connected norm */
6640                                conn_opt = GET_WORD(data);
6641                                data += 2; /* connected options */
6642
6643                                PUT_WORD(&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6644
6645                                if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6646                                {
6647                                        ncpi_opt |= MDM_NCPI_ECM_V42;
6648                                }
6649                                else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6650                                {
6651                                        ncpi_opt |= MDM_NCPI_ECM_MNP;
6652                                }
6653                                else
6654                                {
6655                                        ncpi_opt |= MDM_NCPI_TRANSPARENT;
6656                                }
6657                                if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6658                                {
6659                                        ncpi_opt |= MDM_NCPI_COMPRESSED;
6660                                }
6661                                PUT_WORD(&(plci->ncpi_buffer[3]), ncpi_opt);
6662                                plci->ncpi_buffer[0] = 4;
6663
6664                                plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6665                        }
6666                }
6667                if (plci->B3_prot == 7)
6668                {
6669                        if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6670                            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6671                            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6672                        {
6673                                a->ncci_state[ncci] = INC_ACT_PENDING;
6674                                sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6675                                plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6676                        }
6677                }
6678
6679                if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
6680                      & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6681                    || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6682                    || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6683
6684                {
6685                        plci->NL.RNR = 2;
6686                        return;
6687                }
6688        }
6689
6690        if (plci->NL.complete == 2)
6691        {
6692                if (((plci->NL.Ind & 0x0f) == N_UDATA)
6693                    && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6694                {
6695                        switch (plci->RData[0].P[0])
6696                        {
6697
6698                        case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6699                                if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6700                                        sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01X");
6701                                break;
6702                        case DTMF_UDATA_INDICATION_ANSWER_TONE:
6703                                if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6704                                        sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01Y");
6705                                break;
6706                        case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6707                                dtmf_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6708                                break;
6709                        case DTMF_UDATA_INDICATION_DIGITS_SENT:
6710                                dtmf_confirmation(Id, plci);
6711                                break;
6712
6713
6714                        case UDATA_INDICATION_MIXER_TAP_DATA:
6715                                capidtmf_recv_process_block(&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6716                                i = capidtmf_indication(&(plci->capidtmf_state), dtmf_code_buffer + 1);
6717                                if (i != 0)
6718                                {
6719                                        dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6720                                        dtmf_indication(Id, plci, dtmf_code_buffer, (word)(i + 1));
6721                                }
6722                                break;
6723
6724
6725                        case UDATA_INDICATION_MIXER_COEFS_SET:
6726                                mixer_indication_coefs_set(Id, plci);
6727                                break;
6728                        case UDATA_INDICATION_XCONNECT_FROM:
6729                                mixer_indication_xconnect_from(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6730                                break;
6731                        case UDATA_INDICATION_XCONNECT_TO:
6732                                mixer_indication_xconnect_to(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6733                                break;
6734
6735
6736                        case LEC_UDATA_INDICATION_DISABLE_DETECT:
6737                                ec_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6738                                break;
6739
6740
6741
6742                        default:
6743                                break;
6744                        }
6745                }
6746                else
6747                {
6748                        if ((plci->RData[0].PLength != 0)
6749                            && ((plci->B2_prot == B2_V120_ASYNC)
6750                                || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6751                                || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6752                        {
6753
6754                                sendf(plci->appl, _DATA_B3_I, Id, 0,
6755                                      "dwww",
6756                                      plci->RData[1].P,
6757                                      (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6758                                      plci->RNum,
6759                                      plci->RFlags);
6760
6761                        }
6762                        else
6763                        {
6764
6765                                sendf(plci->appl, _DATA_B3_I, Id, 0,
6766                                      "dwww",
6767                                      plci->RData[0].P,
6768                                      plci->RData[0].PLength,
6769                                      plci->RNum,
6770                                      plci->RFlags);
6771
6772                        }
6773                }
6774                return;
6775        }
6776
6777        fax_feature_bits = 0;
6778        if ((plci->NL.Ind & 0x0f) == N_CONNECT ||
6779            (plci->NL.Ind & 0x0f) == N_CONNECT_ACK ||
6780            (plci->NL.Ind & 0x0f) == N_DISC ||
6781            (plci->NL.Ind & 0x0f) == N_EDATA ||
6782            (plci->NL.Ind & 0x0f) == N_DISC_ACK)
6783        {
6784                info = 0;
6785                plci->ncpi_buffer[0] = 0;
6786                switch (plci->B3_prot) {
6787                case  0: /*XPARENT*/
6788                case  1: /*T.90 NL*/
6789                        break;    /* no network control protocol info - jfr */
6790                case  2: /*ISO8202*/
6791                case  3: /*X25 DCE*/
6792                        for (i = 0; i < plci->NL.RLength; i++) plci->ncpi_buffer[4 + i] = plci->NL.RBuffer->P[i];
6793                        plci->ncpi_buffer[0] = (byte)(i + 3);
6794                        plci->ncpi_buffer[1] = (byte)(plci->NL.Ind & N_D_BIT ? 1 : 0);
6795                        plci->ncpi_buffer[2] = 0;
6796                        plci->ncpi_buffer[3] = 0;
6797                        break;
6798                case  4: /*T.30 - FAX*/
6799                case  5: /*T.30 - FAX*/
6800                        if (plci->NL.RLength >= sizeof(T30_INFO))
6801                        {
6802                                dbug(1, dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6803                                len = 9;
6804                                PUT_WORD(&(plci->ncpi_buffer[1]), ((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6805                                fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6806                                i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6807                                if (plci->B3_prot == 5)
6808                                {
6809                                        if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6810                                                i |= 0x8000; /* This is not an ECM connection */
6811                                        if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6812                                                i |= 0x4000; /* This is a connection with MMR compression */
6813                                        if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6814                                                i |= 0x2000; /* This is a connection with MR compression */
6815                                        if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6816                                                i |= 0x0004; /* More documents */
6817                                        if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6818                                                i |= 0x0002; /* Fax-polling indication */
6819                                }
6820                                dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits, i));
6821                                PUT_WORD(&(plci->ncpi_buffer[3]), i);
6822                                PUT_WORD(&(plci->ncpi_buffer[5]), ((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6823                                plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6824                                plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6825                                plci->ncpi_buffer[len] = 0;
6826                                if (((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6827                                {
6828                                        plci->ncpi_buffer[len] = 20;
6829                                        for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6830                                                plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6831                                }
6832                                if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6833                                {
6834                                        if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6835                                                info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6836                                        else
6837                                                info = _FAX_PROTOCOL_ERROR;
6838                                }
6839
6840                                if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6841                                    & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6842                                {
6843                                        i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6844                                        while (i < plci->NL.RBuffer->length)
6845                                                plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6846                                }
6847
6848                                plci->ncpi_buffer[0] = len;
6849                                fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6850                                PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6851
6852                                plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6853                                if (((plci->NL.Ind & 0x0f) == N_CONNECT_ACK)
6854                                    || (((plci->NL.Ind & 0x0f) == N_CONNECT)
6855                                        && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6856                                    || (((plci->NL.Ind & 0x0f) == N_EDATA)
6857                                        && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6858                                            || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6859                                            || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6860                                {
6861                                        plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6862                                }
6863                                if (((plci->NL.Ind & 0x0f) == N_DISC)
6864                                    || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)
6865                                    || (((plci->NL.Ind & 0x0f) == N_EDATA)
6866                                        && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6867                                {
6868                                        plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6869                                }
6870                        }
6871                        break;
6872
6873                case B3_RTP:
6874                        if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6875                        {
6876                                if (plci->NL.RLength != 0)
6877                                {
6878                                        info = rtp_info[plci->NL.RBuffer->P[0]];
6879                                        plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6880                                        for (i = 1; i < plci->NL.RLength; i++)
6881                                                plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6882                                }
6883                        }
6884                        break;
6885
6886                }
6887                plci->NL.RNR = 2;
6888        }
6889        switch (plci->NL.Ind & 0x0f) {
6890        case N_EDATA:
6891                if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6892                {
6893                        dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6894                                        ((T30_INFO *)plci->NL.RBuffer->P)->code));
6895                        fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6896
6897                        if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6898                            && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6899                            && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6900                            && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6901                            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6902                            && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6903                        {
6904                                ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6905                                sendf(plci->appl, _MANUFACTURER_I, Id, 0, "dwbS", _DI_MANU_ID, _DI_NEGOTIATE_B3,
6906                                      (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6907                                plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6908                                if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6909                                        fax_send_edata_ack = false;
6910                        }
6911
6912                        if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6913                        {
6914                                switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6915                                {
6916                                case EDATA_T30_DIS:
6917                                        if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6918                                            && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6919                                            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6920                                            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6921                                        {
6922                                                a->ncci_state[ncci] = INC_ACT_PENDING;
6923                                                if (plci->B3_prot == 4)
6924                                                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6925                                                else
6926                                                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6927                                                plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6928                                        }
6929                                        break;
6930
6931                                case EDATA_T30_TRAIN_OK:
6932                                        if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6933                                            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6934                                            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6935                                        {
6936                                                if (plci->B3_prot == 4)
6937                                                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6938                                                else
6939                                                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6940                                                plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6941                                        }
6942                                        break;
6943
6944                                case EDATA_T30_EOP_CAPI:
6945                                        if (a->ncci_state[ncci] == CONNECTED)
6946                                        {
6947                                                sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", GOOD, plci->ncpi_buffer);
6948                                                a->ncci_state[ncci] = INC_DIS_PENDING;
6949                                                plci->ncpi_state = 0;
6950                                                fax_send_edata_ack = false;
6951                                        }
6952                                        break;
6953                                }
6954                        }
6955                        else
6956                        {
6957                                switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6958                                {
6959                                case EDATA_T30_TRAIN_OK:
6960                                        if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6961                                            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6962                                            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6963                                        {
6964                                                if (plci->B3_prot == 4)
6965                                                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6966                                                else
6967                                                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6968                                                plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6969                                        }
6970                                        break;
6971                                }
6972                        }
6973                        if (fax_send_edata_ack)
6974                        {
6975                                ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6976                                plci->fax_edata_ack_length = 1;
6977                                start_internal_command(Id, plci, fax_edata_ack_command);
6978                        }
6979                }
6980                else
6981                {
6982                        dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6983                }
6984                break;
6985        case N_CONNECT:
6986                if (!a->ch_ncci[ch])
6987                {
6988                        ncci = get_ncci(plci, ch, 0);
6989                        Id = (Id & 0xffff) | (((dword) ncci) << 16);
6990                }
6991                dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6992                                ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6993
6994                msg = _CONNECT_B3_I;
6995                if (a->ncci_state[ncci] == IDLE)
6996                        plci->channels++;
6997                else if (plci->B3_prot == 1)
6998                        msg = _CONNECT_B3_T90_ACTIVE_I;
6999
7000                a->ncci_state[ncci] = INC_CON_PENDING;
7001                if (plci->B3_prot == 4)
7002                        sendf(plci->appl, msg, Id, 0, "s", "");
7003                else
7004                        sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7005                break;
7006        case N_CONNECT_ACK:
7007                dbug(1, dprintf("N_connect_Ack"));
7008                if (plci->internal_command_queue[0]
7009                    && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
7010                        || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
7011                        || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
7012                {
7013                        (*(plci->internal_command_queue[0]))(Id, plci, 0);
7014                        if (!plci->internal_command)
7015                                next_internal_command(Id, plci);
7016                        break;
7017                }
7018                msg = _CONNECT_B3_ACTIVE_I;
7019                if (plci->B3_prot == 1)
7020                {
7021                        if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7022                                msg = _CONNECT_B3_T90_ACTIVE_I;
7023                        a->ncci_state[ncci] = INC_ACT_PENDING;
7024                        sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7025                }
7026                else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7027                {
7028                        if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7029                            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7030                            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7031                        {
7032                                a->ncci_state[ncci] = INC_ACT_PENDING;
7033                                if (plci->B3_prot == 4)
7034                                        sendf(plci->appl, msg, Id, 0, "s", "");
7035                                else
7036                                        sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7037                                plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7038                        }
7039                }
7040                else
7041                {
7042                        a->ncci_state[ncci] = INC_ACT_PENDING;
7043                        sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7044                }
7045                if (plci->adjust_b_restore)
7046                {
7047                        plci->adjust_b_restore = false;
7048                        start_internal_command(Id, plci, adjust_b_restore);
7049                }
7050                break;
7051        case N_DISC:
7052        case N_DISC_ACK:
7053                if (plci->internal_command_queue[0]
7054                    && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7055                        || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7056                        || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7057                {
7058                        (*(plci->internal_command_queue[0]))(Id, plci, 0);
7059                        if (!plci->internal_command)
7060                                next_internal_command(Id, plci);
7061                }
7062                ncci_state = a->ncci_state[ncci];
7063                ncci_remove(plci, ncci, false);
7064
7065                /* with N_DISC or N_DISC_ACK the IDI frees the respective   */
7066                /* channel, so we cannot store the state in ncci_state! The */
7067                /* information which channel we received a N_DISC is thus   */
7068                /* stored in the inc_dis_ncci_table buffer.                 */
7069                for (i = 0; plci->inc_dis_ncci_table[i]; i++);
7070                plci->inc_dis_ncci_table[i] = (byte) ncci;
7071
7072                /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7073                if (!plci->channels
7074                    && (plci->B1_resource == 16)
7075                    && (plci->State <= CONNECTED))
7076                {
7077                        len = 9;
7078                        i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7079                        PUT_WORD(&plci->ncpi_buffer[1], i);
7080                        PUT_WORD(&plci->ncpi_buffer[3], 0);
7081                        i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7082                        PUT_WORD(&plci->ncpi_buffer[5], i);
7083                        PUT_WORD(&plci->ncpi_buffer[7], 0);
7084                        plci->ncpi_buffer[len] = 0;
7085                        plci->ncpi_buffer[0] = len;
7086                        if (plci->B3_prot == 4)
7087                                sendf(plci->appl, _CONNECT_B3_I, Id, 0, "s", "");
7088                        else
7089                        {
7090
7091                                if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
7092                                    & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7093                                {
7094                                        plci->ncpi_buffer[++len] = 0;
7095                                        plci->ncpi_buffer[++len] = 0;
7096                                        plci->ncpi_buffer[++len] = 0;
7097                                        plci->ncpi_buffer[0] = len;
7098                                }
7099
7100                                sendf(plci->appl, _CONNECT_B3_I, Id, 0, "S", plci->ncpi_buffer);
7101                        }
7102                        sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7103                        plci->ncpi_state = 0;
7104                        sig_req(plci, HANGUP, 0);
7105                        send_req(plci);
7106                        plci->State = OUTG_DIS_PENDING;
7107                        /* disc here */
7108                }
7109                else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7110                         && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7111                         && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7112                {
7113                        if (ncci_state == IDLE)
7114                        {
7115                                if (plci->channels)
7116                                        plci->channels--;
7117                                if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
7118                                        if (plci->State == SUSPENDING) {
7119                                                sendf(plci->appl,
7120                                                      _FACILITY_I,
7121                                                      Id & 0xffffL,
7122                                                      0,
7123                                                      "ws", (word)3, "\x03\x04\x00\x00");
7124                                                sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7125                                        }
7126                                        plci_remove(plci);
7127                                        plci->State = IDLE;
7128                                }
7129                        }
7130                }
7131                else if (plci->channels)
7132                {
7133                        sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7134                        plci->ncpi_state = 0;
7135                        if ((ncci_state == OUTG_REJ_PENDING)
7136                            && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7137                        {
7138                                sig_req(plci, HANGUP, 0);
7139                                send_req(plci);
7140                                plci->State = OUTG_DIS_PENDING;
7141                        }
7142                }
7143                break;
7144        case N_RESET:
7145                a->ncci_state[ncci] = INC_RES_PENDING;
7146                sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7147                break;
7148        case N_RESET_ACK:
7149                a->ncci_state[ncci] = CONNECTED;
7150                sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7151                break;
7152
7153        case N_UDATA:
7154                if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7155                {
7156                        plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7157                        plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7158                        plci->NL.R = plci->RData;
7159                        plci->NL.RNum = 1;
7160                        return;
7161                }
7162        case N_BDATA:
7163        case N_DATA:
7164                if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7165                    || (a->ncci_state[ncci] == IDLE)
7166                    || (a->ncci_state[ncci] == INC_DIS_PENDING))
7167                {
7168                        plci->NL.RNR = 2;
7169                        break;
7170                }
7171                if ((a->ncci_state[ncci] != CONNECTED)
7172                    && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7173                    && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7174                {
7175                        dbug(1, dprintf("flow control"));
7176                        plci->NL.RNR = 1; /* flow control  */
7177                        channel_x_off(plci, ch, 0);
7178                        break;
7179                }
7180
7181                NCCIcode = ncci | (((word)a->Id) << 8);
7182
7183                /* count all buffers within the Application pool    */
7184                /* belonging to the same NCCI. If this is below the */
7185                /* number of buffers available per NCCI we accept   */
7186                /* this packet, otherwise we reject it              */
7187                count = 0;
7188                Num = 0xffff;
7189                for (i = 0; i < APPLptr->MaxBuffer; i++) {
7190                        if (NCCIcode == APPLptr->DataNCCI[i]) count++;
7191                        if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
7192                }
7193
7194                if (count >= APPLptr->MaxNCCIData || Num == 0xffff)
7195                {
7196                        dbug(3, dprintf("Flow-Control"));
7197                        plci->NL.RNR = 1;
7198                        if (++(APPLptr->NCCIDataFlowCtrlTimer) >=
7199                            (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7200                        {
7201                                plci->NL.RNR = 2;
7202                                dbug(3, dprintf("DiscardData"));
7203                        } else {
7204                                channel_x_off(plci, ch, 0);
7205                        }
7206                        break;
7207                }
7208                else
7209                {
7210                        APPLptr->NCCIDataFlowCtrlTimer = 0;
7211                }
7212
7213                plci->RData[0].P = ReceiveBufferGet(APPLptr, Num);
7214                if (!plci->RData[0].P) {
7215                        plci->NL.RNR = 1;
7216                        channel_x_off(plci, ch, 0);
7217                        break;
7218                }
7219
7220                APPLptr->DataNCCI[Num] = NCCIcode;
7221                APPLptr->DataFlags[Num] = (plci->Id << 8) | (plci->NL.Ind >> 4);
7222                dbug(3, dprintf("Buffer(%d), Max = %d", Num, APPLptr->MaxBuffer));
7223
7224                plci->RNum = Num;
7225                plci->RFlags = plci->NL.Ind >> 4;
7226                plci->RData[0].PLength = APPLptr->MaxDataLength;
7227                plci->NL.R = plci->RData;
7228                if ((plci->NL.RLength != 0)
7229                    && ((plci->B2_prot == B2_V120_ASYNC)
7230                        || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7231                        || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7232                {
7233                        plci->RData[1].P = plci->RData[0].P;
7234                        plci->RData[1].PLength = plci->RData[0].PLength;
7235                        plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7236                        if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7237                                plci->RData[0].PLength = 1;
7238                        else
7239                                plci->RData[0].PLength = 2;
7240                        if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7241                                plci->RFlags |= 0x0010;
7242                        if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7243                                plci->RFlags |= 0x8000;
7244                        plci->NL.RNum = 2;
7245                }
7246                else
7247                {
7248                        if ((plci->NL.Ind & 0x0f) == N_UDATA)
7249                                plci->RFlags |= 0x0010;
7250
7251                        else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7252                                plci->RFlags |= 0x0001;
7253
7254                        plci->NL.RNum = 1;
7255                }
7256                break;
7257        case N_DATA_ACK:
7258                data_ack(plci, ch);
7259                break;
7260        default:
7261                plci->NL.RNR = 2;
7262                break;
7263        }
7264}
7265
7266/*------------------------------------------------------------------*/
7267/* find a free PLCI */
7268/*------------------------------------------------------------------*/
7269
7270static word get_plci(DIVA_CAPI_ADAPTER *a)
7271{
7272        word i, j;
7273        PLCI *plci;
7274
7275        dump_plcis(a);
7276        for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
7277        if (i == a->max_plci) {
7278                dbug(1, dprintf("get_plci: out of PLCIs"));
7279                return 0;
7280        }
7281        plci = &a->plci[i];
7282        plci->Id = (byte)(i + 1);
7283
7284        plci->Sig.Id = 0;
7285        plci->NL.Id = 0;
7286        plci->sig_req = 0;
7287        plci->nl_req = 0;
7288
7289        plci->appl = NULL;
7290        plci->relatedPTYPLCI = NULL;
7291        plci->State = IDLE;
7292        plci->SuppState = IDLE;
7293        plci->channels = 0;
7294        plci->tel = 0;
7295        plci->B1_resource = 0;
7296        plci->B2_prot = 0;
7297        plci->B3_prot = 0;
7298
7299        plci->command = 0;
7300        plci->m_command = 0;
7301        init_internal_command_queue(plci);
7302        plci->number = 0;
7303        plci->req_in_start = 0;
7304        plci->req_in = 0;
7305        plci->req_out = 0;
7306        plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7307        plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7308        plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7309
7310        plci->data_sent = false;
7311        plci->send_disc = 0;
7312        plci->sig_global_req = 0;
7313        plci->sig_remove_id = 0;
7314        plci->nl_global_req = 0;
7315        plci->nl_remove_id = 0;
7316        plci->adv_nl = 0;
7317        plci->manufacturer = false;
7318        plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7319        plci->spoofed_msg = 0;
7320        plci->ptyState = 0;
7321        plci->cr_enquiry = false;
7322        plci->hangup_flow_ctrl_timer = 0;
7323
7324        plci->ncci_ring_list = 0;
7325        for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
7326        clear_c_ind_mask(plci);
7327        set_group_ind_mask(plci);
7328        plci->fax_connect_info_length = 0;
7329        plci->nsf_control_bits = 0;
7330        plci->ncpi_state = 0x00;
7331        plci->ncpi_buffer[0] = 0;
7332
7333        plci->requested_options_conn = 0;
7334        plci->requested_options = 0;
7335        plci->notifiedcall = 0;
7336        plci->vswitchstate = 0;
7337        plci->vsprot = 0;
7338        plci->vsprotdialect = 0;
7339        init_b1_config(plci);
7340        dbug(1, dprintf("get_plci(%x)", plci->Id));
7341        return i + 1;
7342}
7343
7344/*------------------------------------------------------------------*/
7345/* put a parameter in the parameter buffer                          */
7346/*------------------------------------------------------------------*/
7347
7348static void add_p(PLCI *plci, byte code, byte *p)
7349{
7350        word p_length;
7351
7352        p_length = 0;
7353        if (p) p_length = p[0];
7354        add_ie(plci, code, p, p_length);
7355}
7356
7357/*------------------------------------------------------------------*/
7358/* put a structure in the parameter buffer                          */
7359/*------------------------------------------------------------------*/
7360static void add_s(PLCI *plci, byte code, API_PARSE *p)
7361{
7362        if (p) add_ie(plci, code, p->info, (word)p->length);
7363}
7364
7365/*------------------------------------------------------------------*/
7366/* put multiple structures in the parameter buffer                  */
7367/*------------------------------------------------------------------*/
7368static void add_ss(PLCI *plci, byte code, API_PARSE *p)
7369{
7370        byte i;
7371
7372        if (p) {
7373                dbug(1, dprintf("add_ss(%x,len=%d)", code, p->length));
7374                for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7375                        dbug(1, dprintf("add_ss_ie(%x,len=%d)", p->info[i - 1], p->info[i]));
7376                        add_ie(plci, p->info[i - 1], (byte *)&(p->info[i]), (word)p->info[i]);
7377                }
7378        }
7379}
7380
7381/*------------------------------------------------------------------*/
7382/* return the channel number sent by the application in a esc_chi   */
7383/*------------------------------------------------------------------*/
7384static byte getChannel(API_PARSE *p)
7385{
7386        byte i;
7387
7388        if (p) {
7389                for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7390                        if (p->info[i] == 2) {
7391                                if (p->info[i - 1] == ESC && p->info[i + 1] == CHI) return (p->info[i + 2]);
7392                        }
7393                }
7394        }
7395        return 0;
7396}
7397
7398
7399/*------------------------------------------------------------------*/
7400/* put an information element in the parameter buffer               */
7401/*------------------------------------------------------------------*/
7402
7403static void add_ie(PLCI *plci, byte code, byte *p, word p_length)
7404{
7405        word i;
7406
7407        if (!(code & 0x80) && !p_length) return;
7408
7409        if (plci->req_in == plci->req_in_start) {
7410                plci->req_in += 2;
7411        }
7412        else {
7413                plci->req_in--;
7414        }
7415        plci->RBuffer[plci->req_in++] = code;
7416
7417        if (p) {
7418                plci->RBuffer[plci->req_in++] = (byte)p_length;
7419                for (i = 0; i < p_length; i++) plci->RBuffer[plci->req_in++] = p[1 + i];
7420        }
7421
7422        plci->RBuffer[plci->req_in++] = 0;
7423}
7424
7425/*------------------------------------------------------------------*/
7426/* put a unstructured data into the buffer                          */
7427/*------------------------------------------------------------------*/
7428
7429static void add_d(PLCI *plci, word length, byte *p)
7430{
7431        word i;
7432
7433        if (plci->req_in == plci->req_in_start) {
7434                plci->req_in += 2;
7435        }
7436        else {
7437                plci->req_in--;
7438        }
7439        for (i = 0; i < length; i++) plci->RBuffer[plci->req_in++] = p[i];
7440}
7441
7442/*------------------------------------------------------------------*/
7443/* put parameters from the Additional Info parameter in the         */
7444/* parameter buffer                                                 */
7445/*------------------------------------------------------------------*/
7446
7447static void add_ai(PLCI *plci, API_PARSE *ai)
7448{
7449        word i;
7450        API_PARSE ai_parms[5];
7451
7452        for (i = 0; i < 5; i++) ai_parms[i].length = 0;
7453
7454        if (!ai->length)
7455                return;
7456        if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7457                return;
7458
7459        add_s(plci, KEY, &ai_parms[1]);
7460        add_s(plci, UUI, &ai_parms[2]);
7461        add_ss(plci, FTY, &ai_parms[3]);
7462}
7463
7464/*------------------------------------------------------------------*/
7465/* put parameter for b1 protocol in the parameter buffer            */
7466/*------------------------------------------------------------------*/
7467
7468static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7469                   word b1_facilities)
7470{
7471        API_PARSE bp_parms[8];
7472        API_PARSE mdm_cfg[9];
7473        API_PARSE global_config[2];
7474        byte cai[256];
7475        byte resource[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7476        byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7477        word i;
7478
7479        API_PARSE mdm_cfg_v18[4];
7480        word j, n, w;
7481        dword d;
7482
7483
7484        for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7485        for (i = 0; i < 2; i++) global_config[i].length = 0;
7486
7487        dbug(1, dprintf("add_b1"));
7488        api_save_msg(bp, "s", &plci->B_protocol);
7489
7490        if (b_channel_info == 2) {
7491                plci->B1_resource = 0;
7492                adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7493                add_p(plci, CAI, "\x01\x00");
7494                dbug(1, dprintf("Cai=1,0 (no resource)"));
7495                return 0;
7496        }
7497
7498        if (plci->tel == CODEC_PERMANENT) return 0;
7499        else if (plci->tel == CODEC) {
7500                plci->B1_resource = 1;
7501                adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7502                add_p(plci, CAI, "\x01\x01");
7503                dbug(1, dprintf("Cai=1,1 (Codec)"));
7504                return 0;
7505        }
7506        else if (plci->tel == ADV_VOICE) {
7507                plci->B1_resource = add_b1_facilities(plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7508                adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7509                voice_cai[1] = plci->B1_resource;
7510                PUT_WORD(&voice_cai[5], plci->appl->MaxDataLength);
7511                add_p(plci, CAI, voice_cai);
7512                dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai[1]));
7513                return 0;
7514        }
7515        plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7516        if (plci->call_dir & CALL_DIR_OUT)
7517                plci->call_dir |= CALL_DIR_ORIGINATE;
7518        else if (plci->call_dir & CALL_DIR_IN)
7519                plci->call_dir |= CALL_DIR_ANSWER;
7520
7521        if (!bp->length) {
7522                plci->B1_resource = 0x5;
7523                adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7524                add_p(plci, CAI, "\x01\x05");
7525                return 0;
7526        }
7527
7528        dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7529        if (bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7530        if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7531        {
7532                bp_parms[6].length = 0;
7533                if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7534                {
7535                        dbug(1, dprintf("b-form.!"));
7536                        return _WRONG_MESSAGE_FORMAT;
7537                }
7538        }
7539        else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7540        {
7541                dbug(1, dprintf("b-form.!"));
7542                return _WRONG_MESSAGE_FORMAT;
7543        }
7544
7545        if (bp_parms[6].length)
7546        {
7547                if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7548                {
7549                        return _WRONG_MESSAGE_FORMAT;
7550                }
7551                switch (GET_WORD(global_config[0].info))
7552                {
7553                case 1:
7554                        plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7555                        break;
7556                case 2:
7557                        plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7558                        break;
7559                }
7560        }
7561        dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7562
7563
7564        if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7565            && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7566        {
7567                plci->B1_resource = add_b1_facilities(plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7568                adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7569                cai[1] = plci->B1_resource;
7570                cai[2] = 0;
7571                cai[3] = 0;
7572                cai[4] = 0;
7573                PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7574                for (i = 0; i < bp_parms[3].length; i++)
7575                        cai[7 + i] = bp_parms[3].info[1 + i];
7576                cai[0] = 6 + bp_parms[3].length;
7577                add_p(plci, CAI, cai);
7578                return 0;
7579        }
7580
7581
7582        if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7583            && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7584        {
7585                plci->B1_resource = add_b1_facilities(plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7586                adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7587                cai[1] = plci->B1_resource;
7588                cai[2] = 0;
7589                cai[3] = 0;
7590                cai[4] = 0;
7591                PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7592                cai[0] = 6;
7593                add_p(plci, CAI, cai);
7594                return 0;
7595        }
7596
7597
7598        if ((GET_WORD(bp_parms[0].info) >= 32)
7599            || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7600                && ((GET_WORD(bp_parms[0].info) != 3)
7601                    || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7602                    || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7603        {
7604                return _B1_NOT_SUPPORTED;
7605        }
7606        plci->B1_resource = add_b1_facilities(plci, resource[GET_WORD(bp_parms[0].info)],
7607                                              (word)(b1_facilities & ~B1_FACILITY_VOICE));
7608        adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7609        cai[0] = 6;
7610        cai[1] = plci->B1_resource;
7611        for (i = 2; i < sizeof(cai); i++) cai[i] = 0;
7612
7613        if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7614            || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7615            || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7616        { /* B1 - modem */
7617                for (i = 0; i < 7; i++) mdm_cfg[i].length = 0;
7618
7619                if (bp_parms[3].length)
7620                {
7621                        if (api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwww", mdm_cfg))
7622                        {
7623                                return (_WRONG_MESSAGE_FORMAT);
7624                        }
7625
7626                        cai[2] = 0; /* Bit rate for adaptation */
7627
7628                        dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7629
7630                        PUT_WORD(&cai[13], 0);                          /* Min Tx speed */
7631                        PUT_WORD(&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7632                        PUT_WORD(&cai[17], 0);                          /* Min Rx speed */
7633                        PUT_WORD(&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7634
7635                        cai[3] = 0; /* Async framing parameters */
7636                        switch (GET_WORD(mdm_cfg[2].info))
7637                        {       /* Parity     */
7638                        case 1: /* odd parity */
7639                                cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7640                                dbug(1, dprintf("MDM: odd parity"));
7641                                break;
7642
7643                        case 2: /* even parity */
7644                                cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7645                                dbug(1, dprintf("MDM: even parity"));
7646                                break;
7647
7648                        default:
7649                                dbug(1, dprintf("MDM: no parity"));
7650                                break;
7651                        }
7652
7653                        switch (GET_WORD(mdm_cfg[3].info))
7654                        {       /* stop bits   */
7655                        case 1: /* 2 stop bits */
7656                                cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7657                                dbug(1, dprintf("MDM: 2 stop bits"));
7658                                break;
7659
7660                        default:
7661                                dbug(1, dprintf("MDM: 1 stop bit"));
7662                                break;
7663                        }
7664
7665                        switch (GET_WORD(mdm_cfg[1].info))
7666                        {     /* char length */
7667                        case 5:
7668                                cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7669                                dbug(1, dprintf("MDM: 5 bits"));
7670                                break;
7671
7672                        case 6:
7673                                cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7674                                dbug(1, dprintf("MDM: 6 bits"));
7675                                break;
7676
7677                        case 7:
7678                                cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7679                                dbug(1, dprintf("MDM: 7 bits"));
7680                                break;
7681
7682                        default:
7683                                dbug(1, dprintf("MDM: 8 bits"));
7684                                break;
7685                        }
7686
7687                        cai[7] = 0; /* Line taking options */
7688                        cai[8] = 0; /* Modulation negotiation options */
7689                        cai[9] = 0; /* Modulation options */
7690
7691                        if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7692                        {
7693                                cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7694                                dbug(1, dprintf("MDM: Reverse direction"));
7695                        }
7696
7697                        if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7698                        {
7699                                cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7700                                dbug(1, dprintf("MDM: Disable retrain"));
7701                        }
7702
7703                        if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7704                        {
7705                                cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7706                                dbug(1, dprintf("MDM: Disable ring tone"));
7707                        }
7708
7709                        if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7710                        {
7711                                cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7712                                dbug(1, dprintf("MDM: 1800 guard tone"));
7713                        }
7714                        else if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_550)
7715                        {
7716                                cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7717                                dbug(1, dprintf("MDM: 550 guard tone"));
7718                        }
7719
7720                        if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7721                        {
7722                                cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7723                                dbug(1, dprintf("MDM: V100"));
7724                        }
7725                        else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7726                        {
7727                                cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7728                                dbug(1, dprintf("MDM: IN CLASS"));
7729                        }
7730                        else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7731                        {
7732                                cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7733                                dbug(1, dprintf("MDM: DISABLED"));
7734                        }
7735                        cai[0] = 20;
7736
7737                        if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7738                            && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7739                        {
7740                                plci->requested_options |= 1L << PRIVATE_V18;
7741                        }
7742                        if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7743                                plci->requested_options |= 1L << PRIVATE_VOWN;
7744
7745                        if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
7746                            & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7747                        {
7748                                if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwws", mdm_cfg))
7749                                {
7750                                        i = 27;
7751                                        if (mdm_cfg[6].length >= 4)
7752                                        {
7753                                                d = GET_DWORD(&mdm_cfg[6].info[1]);
7754                                                cai[7] |= (byte) d;          /* line taking options */
7755                                                cai[9] |= (byte)(d >> 8);    /* modulation options */
7756                                                cai[++i] = (byte)(d >> 16);  /* vown modulation options */
7757                                                cai[++i] = (byte)(d >> 24);
7758                                                if (mdm_cfg[6].length >= 8)
7759                                                {
7760                                                        d = GET_DWORD(&mdm_cfg[6].info[5]);
7761                                                        cai[10] |= (byte) d;        /* disabled modulations mask */
7762                                                        cai[11] |= (byte)(d >> 8);
7763                                                        if (mdm_cfg[6].length >= 12)
7764                                                        {
7765                                                                d = GET_DWORD(&mdm_cfg[6].info[9]);
7766                                                                cai[12] = (byte) d;          /* enabled modulations mask */
7767                                                                cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */
7768                                                                cai[++i] = (byte)(d >> 16);
7769                                                                cai[++i] = (byte)(d >> 24);
7770                                                                cai[++i] = 0;
7771                                                                if (mdm_cfg[6].length >= 14)
7772                                                                {
7773                                                                        w = GET_WORD(&mdm_cfg[6].info[13]);
7774                                                                        if (w != 0)
7775                                                                                PUT_WORD(&cai[13], w);  /* min tx speed */
7776                                                                        if (mdm_cfg[6].length >= 16)
7777                                                                        {
7778                                                                                w = GET_WORD(&mdm_cfg[6].info[15]);
7779                                                                                if (w != 0)
7780                                                                                        PUT_WORD(&cai[15], w);  /* max tx speed */
7781                                                                                if (mdm_cfg[6].length >= 18)
7782                                                                                {
7783                                                                                        w = GET_WORD(&mdm_cfg[6].info[17]);
7784                                                                                        if (w != 0)
7785                                                                                                PUT_WORD(&cai[17], w);  /* min rx speed */
7786                                                                                        if (mdm_cfg[6].length >= 20)
7787                                                                                        {
7788                                                                                                w = GET_WORD(&mdm_cfg[6].info[19]);
7789                                                                                                if (w != 0)
7790                                                                                                        PUT_WORD(&cai[19], w);  /* max rx speed */
7791                                                                                                if (mdm_cfg[6].length >= 22)
7792                                                                                                {
7793                                                                                                        w = GET_WORD(&mdm_cfg[6].info[21]);
7794                                                                                                        cai[23] = (byte)(-((short) w));  /* transmit level */
7795                                                                                                        if (mdm_cfg[6].length >= 24)
7796                                                                                                        {
7797                                                                                                                w = GET_WORD(&mdm_cfg[6].info[23]);
7798                                                                                                                cai[22] |= (byte) w;        /* info options mask */
7799                                                                                                                cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */
7800                                                                                                        }
7801                                                                                                }
7802                                                                                        }
7803                                                                                }
7804                                                                        }
7805                                                                }
7806                                                        }
7807                                                }
7808                                        }
7809                                        cai[27] = i - 27;
7810                                        i++;
7811                                        if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwwss", mdm_cfg))
7812                                        {
7813                                                if (!api_parse(&mdm_cfg[7].info[1], (word)mdm_cfg[7].length, "sss", mdm_cfg_v18))
7814                                                {
7815                                                        for (n = 0; n < 3; n++)
7816                                                        {
7817                                                                cai[i] = (byte)(mdm_cfg_v18[n].length);
7818                                                                for (j = 1; j < ((word)(cai[i] + 1)); j++)
7819                                                                        cai[i + j] = mdm_cfg_v18[n].info[j];
7820                                                                i += cai[i] + 1;
7821                                                        }
7822                                                }
7823                                        }
7824                                        cai[0] = (byte)(i - 1);
7825                                }
7826                        }
7827
7828                }
7829        }
7830        if (GET_WORD(bp_parms[0].info) == 2 ||                         /* V.110 async */
7831            GET_WORD(bp_parms[0].info) == 3)                           /* V.110 sync */
7832        {
7833                if (bp_parms[3].length) {
7834                        dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms[3].info[1])));
7835                        switch (GET_WORD(&bp_parms[3].info[1])) {                 /* Rate */
7836                        case 0:
7837                        case 56000:
7838                                if (GET_WORD(bp_parms[0].info) == 3) {                  /* V.110 sync 56k */
7839                                        dbug(1, dprintf("56k sync HSCX"));
7840                                        cai[1] = 8;
7841                                        cai[2] = 0;
7842                                        cai[3] = 0;
7843                                }
7844                                else if (GET_WORD(bp_parms[0].info) == 2) {
7845                                        dbug(1, dprintf("56k async DSP"));
7846                                        cai[2] = 9;
7847                                }
7848                                break;
7849                        case 50:     cai[2] = 1;  break;
7850                        case 75:     cai[2] = 1;  break;
7851                        case 110:    cai[2] = 1;  break;
7852                        case 150:    cai[2] = 1;  break;
7853                        case 200:    cai[2] = 1;  break;
7854                        case 300:    cai[2] = 1;  break;
7855                        case 600:    cai[2] = 1;  break;
7856                        case 1200:   cai[2] = 2;  break;
7857                        case 2400:   cai[2] = 3;  break;
7858                        case 4800:   cai[2] = 4;  break;
7859                        case 7200:   cai[2] = 10; break;
7860                        case 9600:   cai[2] = 5;  break;
7861                        case 12000:  cai[2] = 13; break;
7862                        case 24000:  cai[2] = 0;  break;
7863                        case 14400:  cai[2] = 11; break;
7864                        case 19200:  cai[2] = 6;  break;
7865                        case 28800:  cai[2] = 12; break;
7866                        case 38400:  cai[2] = 7;  break;
7867                        case 48000:  cai[2] = 8;  break;
7868                        case 76:     cai[2] = 15; break;  /* 75/1200     */
7869                        case 1201:   cai[2] = 14; break;  /* 1200/75     */
7870                        case 56001:  cai[2] = 9;  break;  /* V.110 56000 */
7871
7872                        default:
7873                                return _B1_PARM_NOT_SUPPORTED;
7874                        }
7875                        cai[3] = 0;
7876                        if (cai[1] == 13)                                        /* v.110 async */
7877                        {
7878                                if (bp_parms[3].length >= 8)
7879                                {
7880                                        switch (GET_WORD(&bp_parms[3].info[3]))
7881                                        {       /* char length */
7882                                        case 5:
7883                                                cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7884                                                break;
7885                                        case 6:
7886                                                cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7887                                                break;
7888                                        case 7:
7889                                                cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7890                                                break;
7891                                        }
7892                                        switch (GET_WORD(&bp_parms[3].info[5]))
7893                                        {       /* Parity     */
7894                                        case 1: /* odd parity */
7895                                                cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7896                                                break;
7897                                        case 2: /* even parity */
7898                                                cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7899                                                break;
7900                                        }
7901                                        switch (GET_WORD(&bp_parms[3].info[7]))
7902                                        {       /* stop bits   */
7903                                        case 1: /* 2 stop bits */
7904                                                cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7905                                                break;
7906                                        }
7907                                }
7908                        }
7909                }
7910                else if (cai[1] == 8 || GET_WORD(bp_parms[0].info) == 3) {
7911                        dbug(1, dprintf("V.110 default 56k sync"));
7912                        cai[1] = 8;
7913                        cai[2] = 0;
7914                        cai[3] = 0;
7915                }
7916                else {
7917                        dbug(1, dprintf("V.110 default 9600 async"));
7918                        cai[2] = 5;
7919                }
7920        }
7921        PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7922        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]));
7923/* HexDump ("CAI", sizeof(cai), &cai[0]); */
7924
7925        add_p(plci, CAI, cai);
7926        return 0;
7927}
7928
7929/*------------------------------------------------------------------*/
7930/* put parameter for b2 and B3  protocol in the parameter buffer    */
7931/*------------------------------------------------------------------*/
7932
7933static word add_b23(PLCI *plci, API_PARSE *bp)
7934{
7935        word i, fax_control_bits;
7936        byte pos, len;
7937        byte SAPI = 0x40;  /* default SAPI 16 for x.31 */
7938        API_PARSE bp_parms[8];
7939        API_PARSE *b1_config;
7940        API_PARSE *b2_config;
7941        API_PARSE b2_config_parms[8];
7942        API_PARSE *b3_config;
7943        API_PARSE b3_config_parms[6];
7944        API_PARSE global_config[2];
7945
7946        static byte llc[3] = {2,0,0};
7947        static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7948        static byte nlc[256];
7949        static byte lli[12] = {1,1};
7950
7951        const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7952        const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7953
7954        const byte llc3[] = {4,3,2,2,6,6,0};
7955        const byte header[] = {0,2,3,3,0,0,0};
7956
7957        for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7958        for (i = 0; i < 6; i++) b2_config_parms[i].length = 0;
7959        for (i = 0; i < 5; i++) b3_config_parms[i].length = 0;
7960
7961        lli[0] = 1;
7962        lli[1] = 1;
7963        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7964                lli[1] |= 2;
7965        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7966                lli[1] |= 4;
7967
7968        if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7969                lli[1] |= 0x10;
7970                if (plci->rx_dma_descriptor <= 0) {
7971                        plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
7972                        if (plci->rx_dma_descriptor >= 0)
7973                                plci->rx_dma_descriptor++;
7974                }
7975                if (plci->rx_dma_descriptor > 0) {
7976                        lli[0] = 6;
7977                        lli[1] |= 0x40;
7978                        lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7979                        lli[3] = (byte)plci->rx_dma_magic;
7980                        lli[4] = (byte)(plci->rx_dma_magic >>  8);
7981                        lli[5] = (byte)(plci->rx_dma_magic >> 16);
7982                        lli[6] = (byte)(plci->rx_dma_magic >> 24);
7983                }
7984        }
7985
7986        if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7987                lli[1] |= 0x20;
7988        }
7989
7990        dbug(1, dprintf("add_b23"));
7991        api_save_msg(bp, "s", &plci->B_protocol);
7992
7993        if (!bp->length && plci->tel)
7994        {
7995                plci->adv_nl = true;
7996                dbug(1, dprintf("Default adv.Nl"));
7997                add_p(plci, LLI, lli);
7998                plci->B2_prot = 1 /*XPARENT*/;
7999                plci->B3_prot = 0 /*XPARENT*/;
8000                llc[1] = 2;
8001                llc[2] = 4;
8002                add_p(plci, LLC, llc);
8003                dlc[0] = 2;
8004                PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8005                add_p(plci, DLC, dlc);
8006                return 0;
8007        }
8008
8009        if (!bp->length) /*default*/
8010        {
8011                dbug(1, dprintf("ret default"));
8012                add_p(plci, LLI, lli);
8013                plci->B2_prot = 0 /*X.75   */;
8014                plci->B3_prot = 0 /*XPARENT*/;
8015                llc[1] = 1;
8016                llc[2] = 4;
8017                add_p(plci, LLC, llc);
8018                dlc[0] = 2;
8019                PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8020                add_p(plci, DLC, dlc);
8021                return 0;
8022        }
8023        dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
8024        if ((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT;
8025
8026        if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8027        {
8028                bp_parms[6].length = 0;
8029                if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8030                {
8031                        dbug(1, dprintf("b-form.!"));
8032                        return _WRONG_MESSAGE_FORMAT;
8033                }
8034        }
8035        else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8036        {
8037                dbug(1, dprintf("b-form.!"));
8038                return _WRONG_MESSAGE_FORMAT;
8039        }
8040
8041        if (plci->tel == ADV_VOICE) /* transparent B on advanced voice */
8042        {
8043                if (GET_WORD(bp_parms[1].info) != 1
8044                    || GET_WORD(bp_parms[2].info) != 0) return _B2_NOT_SUPPORTED;
8045                plci->adv_nl = true;
8046        }
8047        else if (plci->tel) return _B2_NOT_SUPPORTED;
8048
8049
8050        if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8051            && (GET_WORD(bp_parms[2].info) == B3_RTP)
8052            && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8053        {
8054                add_p(plci, LLI, lli);
8055                plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8056                plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8057                llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8058                llc[2] = 4;
8059                add_p(plci, LLC, llc);
8060                dlc[0] = 2;
8061                PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8062                dlc[3] = 3; /* Addr A */
8063                dlc[4] = 1; /* Addr B */
8064                dlc[5] = 7; /* modulo mode */
8065                dlc[6] = 7; /* window size */
8066                dlc[7] = 0; /* XID len Lo  */
8067                dlc[8] = 0; /* XID len Hi  */
8068                for (i = 0; i < bp_parms[4].length; i++)
8069                        dlc[9 + i] = bp_parms[4].info[1 + i];
8070                dlc[0] = (byte)(8 + bp_parms[4].length);
8071                add_p(plci, DLC, dlc);
8072                for (i = 0; i < bp_parms[5].length; i++)
8073                        nlc[1 + i] = bp_parms[5].info[1 + i];
8074                nlc[0] = (byte)(bp_parms[5].length);
8075                add_p(plci, NLC, nlc);
8076                return 0;
8077        }
8078
8079
8080
8081        if ((GET_WORD(bp_parms[1].info) >= 32)
8082            || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8083                && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8084                    || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8085
8086        {
8087                return _B2_NOT_SUPPORTED;
8088        }
8089        if ((GET_WORD(bp_parms[2].info) >= 32)
8090            || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8091        {
8092                return _B3_NOT_SUPPORTED;
8093        }
8094        if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8095            && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8096                || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8097                || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8098        {
8099                return (add_modem_b23(plci, bp_parms));
8100        }
8101
8102        add_p(plci, LLI, lli);
8103
8104        plci->B2_prot = (byte)GET_WORD(bp_parms[1].info);
8105        plci->B3_prot = (byte)GET_WORD(bp_parms[2].info);
8106        if (plci->B2_prot == 12) SAPI = 0; /* default SAPI D-channel */
8107
8108        if (bp_parms[6].length)
8109        {
8110                if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8111                {
8112                        return _WRONG_MESSAGE_FORMAT;
8113                }
8114                switch (GET_WORD(global_config[0].info))
8115                {
8116                case 1:
8117                        plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8118                        break;
8119                case 2:
8120                        plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8121                        break;
8122                }
8123        }
8124        dbug(1, dprintf("call_dir=%04x", plci->call_dir));
8125
8126
8127        if (plci->B2_prot == B2_PIAFS)
8128                llc[1] = PIAFS_CRC;
8129        else
8130/* IMPLEMENT_PIAFS */
8131        {
8132                llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8133                        llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8134        }
8135        llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8136
8137        add_p(plci, LLC, llc);
8138
8139        dlc[0] = 2;
8140        PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8141                 header[GET_WORD(bp_parms[2].info)]);
8142
8143        b1_config = &bp_parms[3];
8144        nlc[0] = 0;
8145        if (plci->B3_prot == 4
8146            || plci->B3_prot == 5)
8147        {
8148                for (i = 0; i < sizeof(T30_INFO); i++) nlc[i] = 0;
8149                nlc[0] = sizeof(T30_INFO);
8150                if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8151                        ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8152                ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8153                if (b1_config->length >= 2)
8154                {
8155                        ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1]) / 2400);
8156                }
8157        }
8158        b2_config = &bp_parms[4];
8159
8160
8161        if (llc[1] == PIAFS_CRC)
8162        {
8163                if (plci->B3_prot != B3_TRANSPARENT)
8164                {
8165                        return _B_STACK_NOT_SUPPORTED;
8166                }
8167                if (b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8168                        return _WRONG_MESSAGE_FORMAT;
8169                }
8170                PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8171                dlc[3] = 0; /* Addr A */
8172                dlc[4] = 0; /* Addr B */
8173                dlc[5] = 0; /* modulo mode */
8174                dlc[6] = 0; /* window size */
8175                if (b2_config->length >= 7) {
8176                        dlc[7] = 7;
8177                        dlc[8] = 0;
8178                        dlc[9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8179                        dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8180                        dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8181                        dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8182                        dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8183                        dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8184                        dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8185                        dlc[0] = 15;
8186                        if (b2_config->length >= 8) { /* PIAFS control abilities */
8187                                dlc[7] = 10;
8188                                dlc[16] = 2; /* Length of PIAFS extension */
8189                                dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8190                                dlc[18] = b2_config_parms[4].info[0]; /* value */
8191                                dlc[0] = 18;
8192                        }
8193                }
8194                else /* default values, 64K, variable, no compression */
8195                {
8196                        dlc[7] = 7;
8197                        dlc[8] = 0;
8198                        dlc[9] = 0x03; /* PIAFS protocol Speed configuration */
8199                        dlc[10] = 0x03; /* V.42bis P0 */
8200                        dlc[11] = 0;    /* V.42bis P0 */
8201                        dlc[12] = 0;    /* V.42bis P1 */
8202                        dlc[13] = 0;    /* V.42bis P1 */
8203                        dlc[14] = 0;    /* V.42bis P2 */
8204                        dlc[15] = 0;    /* V.42bis P2 */
8205                        dlc[0] = 15;
8206                }
8207                add_p(plci, DLC, dlc);
8208        }
8209        else
8210
8211                if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8212                {
8213                        if (plci->B3_prot != B3_TRANSPARENT)
8214                                return _B_STACK_NOT_SUPPORTED;
8215
8216                        dlc[0] = 6;
8217                        PUT_WORD(&dlc[1], GET_WORD(&dlc[1]) + 2);
8218                        dlc[3] = 0x08;
8219                        dlc[4] = 0x01;
8220                        dlc[5] = 127;
8221                        dlc[6] = 7;
8222                        if (b2_config->length != 0)
8223                        {
8224                                if ((llc[1] == V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8225                                        return _WRONG_MESSAGE_FORMAT;
8226                                }
8227                                dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8228                                dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8229                                if (b2_config->info[3] != 128)
8230                                {
8231                                        dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8232                                        return _B2_PARM_NOT_SUPPORTED;
8233                                }
8234                                dlc[5] = (byte)(b2_config->info[3] - 1);
8235                                dlc[6] = b2_config->info[4];
8236                                if (llc[1] == V120_V42BIS) {
8237                                        if (b2_config->length >= 10) {
8238                                                dlc[7] = 6;
8239                                                dlc[8] = 0;
8240                                                dlc[9] = b2_config_parms[4].info[0];
8241                                                dlc[10] = b2_config_parms[4].info[1];
8242                                                dlc[11] = b2_config_parms[5].info[0];
8243                                                dlc[12] = b2_config_parms[5].info[1];
8244                                                dlc[13] = b2_config_parms[6].info[0];
8245                                                dlc[14] = b2_config_parms[6].info[1];
8246                                                dlc[0] = 14;
8247                                                dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8248                                                dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8249                                                dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8250                                        }
8251                                        else {
8252                                                dlc[6] = 14;
8253                                        }
8254                                }
8255                        }
8256                }
8257                else
8258                {
8259                        if (b2_config->length)
8260                        {
8261                                dbug(1, dprintf("B2-Config"));
8262                                if (llc[1] == X75_V42BIS) {
8263                                        if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8264                                        {
8265                                                return _WRONG_MESSAGE_FORMAT;
8266                                        }
8267                                }
8268                                else {
8269                                        if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8270                                        {
8271                                                return _WRONG_MESSAGE_FORMAT;
8272                                        }
8273                                }
8274                                /* if B2 Protocol is LAPD, b2_config structure is different */
8275                                if (llc[1] == 6)
8276                                {
8277                                        dlc[0] = 4;
8278                                        if (b2_config->length >= 1) dlc[2] = b2_config->info[1];      /* TEI */
8279                                        else dlc[2] = 0x01;
8280                                        if ((b2_config->length >= 2) && (plci->B2_prot == 12))
8281                                        {
8282                                                SAPI = b2_config->info[2];    /* SAPI */
8283                                        }
8284                                        dlc[1] = SAPI;
8285                                        if ((b2_config->length >= 3) && (b2_config->info[3] == 128))
8286                                        {
8287                                                dlc[3] = 127;      /* Mode */
8288                                        }
8289                                        else
8290                                        {
8291                                                dlc[3] = 7;        /* Mode */
8292                                        }
8293
8294                                        if (b2_config->length >= 4) dlc[4] = b2_config->info[4];      /* Window */
8295                                        else dlc[4] = 1;
8296                                        dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8297                                        if (b2_config->length > 5) return _B2_PARM_NOT_SUPPORTED;
8298                                }
8299                                else
8300                                {
8301                                        dlc[0] = (byte)(b2_config_parms[4].length + 6);
8302                                        dlc[3] = b2_config->info[1];
8303                                        dlc[4] = b2_config->info[2];
8304                                        if (b2_config->info[3] != 8 && b2_config->info[3] != 128) {
8305                                                dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8306                                                return _B2_PARM_NOT_SUPPORTED;
8307                                        }
8308
8309                                        dlc[5] = (byte)(b2_config->info[3] - 1);
8310                                        dlc[6] = b2_config->info[4];
8311                                        if (dlc[6] > dlc[5]) {
8312                                                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]));
8313                                                return _B2_PARM_NOT_SUPPORTED;
8314                                        }
8315
8316                                        if (llc[1] == X75_V42BIS) {
8317                                                if (b2_config->length >= 10) {
8318                                                        dlc[7] = 6;
8319                                                        dlc[8] = 0;
8320                                                        dlc[9] = b2_config_parms[4].info[0];
8321                                                        dlc[10] = b2_config_parms[4].info[1];
8322                                                        dlc[11] = b2_config_parms[5].info[0];
8323                                                        dlc[12] = b2_config_parms[5].info[1];
8324                                                        dlc[13] = b2_config_parms[6].info[0];
8325                                                        dlc[14] = b2_config_parms[6].info[1];
8326                                                        dlc[0] = 14;
8327                                                        dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8328                                                        dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8329                                                        dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8330                                                }
8331                                                else {
8332                                                        dlc[6] = 14;
8333                                                }
8334
8335                                        }
8336                                        else {
8337                                                PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8338                                                for (i = 0; i < b2_config_parms[4].length; i++)
8339                                                        dlc[11 + i] = b2_config_parms[4].info[1 + i];
8340                                        }
8341                                }
8342                        }
8343                }
8344        add_p(plci, DLC, dlc);
8345
8346        b3_config = &bp_parms[5];
8347        if (b3_config->length)
8348        {
8349                if (plci->B3_prot == 4
8350                    || plci->B3_prot == 5)
8351                {
8352                        if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8353                        {
8354                                return _WRONG_MESSAGE_FORMAT;
8355                        }
8356                        i = GET_WORD((byte *)(b3_config_parms[0].info));
8357                        ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8358                                                                    ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8359                        ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8360                        fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8361                        if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8362                                fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8363                        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8364                        {
8365
8366                                if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8367                                    & (1L << PRIVATE_FAX_PAPER_FORMATS))
8368                                {
8369                                        ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8370                                                T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8371                                                T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8372                                }
8373
8374                                ((T30_INFO *)&nlc[1])->recording_properties =
8375                                        T30_RECORDING_WIDTH_ISO_A3 |
8376                                        (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8377                                        (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8378                        }
8379                        if (plci->B3_prot == 5)
8380                        {
8381                                if (i & 0x0002) /* Accept incoming fax-polling requests */
8382                                        fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8383                                if (i & 0x2000) /* Do not use MR compression */
8384                                        fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8385                                if (i & 0x4000) /* Do not use MMR compression */
8386                                        fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8387                                if (i & 0x8000) /* Do not use ECM */
8388                                        fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8389                                if (plci->fax_connect_info_length != 0)
8390                                {
8391                                        ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8392                                        ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8393                                        ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8394                                        fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8395                                                (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8396                                }
8397                        }
8398                        /* copy station id to NLC */
8399                        for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
8400                        {
8401                                if (i < b3_config_parms[2].length)
8402                                {
8403                                        ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1 + i];
8404                                }
8405                                else
8406                                {
8407                                        ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8408                                }
8409                        }
8410                        ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8411                        /* copy head line to NLC */
8412                        if (b3_config_parms[3].length)
8413                        {
8414
8415                                pos = (byte)(fax_head_line_time(&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8416                                if (pos != 0)
8417                                {
8418                                        if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8419                                                pos = 0;
8420                                        else
8421                                        {
8422                                                nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8423                                                nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8424                                                len = (byte)b3_config_parms[2].length;
8425                                                if (len > 20)
8426                                                        len = 20;
8427                                                if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8428                                                {
8429                                                        for (i = 0; i < len; i++)
8430                                                                nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1 + i];
8431                                                        nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8432                                                        nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8433                                                }
8434                                        }
8435                                }
8436
8437                                len = (byte)b3_config_parms[3].length;
8438                                if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8439                                        len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8440                                ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8441                                nlc[0] += (byte)(pos + len);
8442                                for (i = 0; i < len; i++)
8443                                        nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] =  ((byte *)b3_config_parms[3].info)[1 + i];
8444                        } else
8445                                ((T30_INFO *)&nlc[1])->head_line_len = 0;
8446
8447                        plci->nsf_control_bits = 0;
8448                        if (plci->B3_prot == 5)
8449                        {
8450                                if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8451                                    && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8452                                {
8453                                        plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8454                                }
8455                                if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8456                                    && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8457                                {
8458                                        plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8459                                }
8460                                if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8461                                    & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8462                                {
8463                                        if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8464                                            & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8465                                        {
8466                                                fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8467                                                if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8468                                                        fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8469                                        }
8470                                        len = nlc[0];
8471                                        pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8472                                        if (pos < plci->fax_connect_info_length)
8473                                        {
8474                                                for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8475                                                        nlc[++len] = plci->fax_connect_info_buffer[pos++];
8476                                        }
8477                                        else
8478                                                nlc[++len] = 0;
8479                                        if (pos < plci->fax_connect_info_length)
8480                                        {
8481                                                for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8482                                                        nlc[++len] = plci->fax_connect_info_buffer[pos++];
8483                                        }
8484                                        else
8485                                                nlc[++len] = 0;
8486                                        if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8487                                            & (1L << PRIVATE_FAX_NONSTANDARD))
8488                                        {
8489                                                if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8490                                                {
8491                                                        if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos + 1] >= 2))
8492                                                                plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos + 2]);
8493                                                        for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8494                                                                nlc[++len] = plci->fax_connect_info_buffer[pos++];
8495                                                }
8496                                                else
8497                                                {
8498                                                        if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8499                                                        {
8500                                                                dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8501                                                                nlc[++len] = 0;
8502                                                        }
8503                                                        else
8504                                                        {
8505                                                                if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8506                                                                        plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8507                                                                nlc[++len] = (byte)(b3_config_parms[4].length);
8508                                                                for (i = 0; i < b3_config_parms[4].length; i++)
8509                                                                        nlc[++len] = b3_config_parms[4].info[1 + i];
8510                                                        }
8511                                                }
8512                                        }
8513                                        nlc[0] = len;
8514                                        if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8515                                            && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8516                                        {
8517                                                ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8518                                        }
8519                                }
8520                        }
8521
8522                        PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8523                        len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8524                        for (i = 0; i < len; i++)
8525                                plci->fax_connect_info_buffer[i] = nlc[1 + i];
8526                        ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8527                        i += ((T30_INFO *)&nlc[1])->head_line_len;
8528                        while (i < nlc[0])
8529                                plci->fax_connect_info_buffer[len++] = nlc[++i];
8530                        plci->fax_connect_info_length = len;
8531                }
8532                else
8533                {
8534                        nlc[0] = 14;
8535                        if (b3_config->length != 16)
8536                                return _B3_PARM_NOT_SUPPORTED;
8537                        for (i = 0; i < 12; i++) nlc[1 + i] = b3_config->info[1 + i];
8538                        if (GET_WORD(&b3_config->info[13]) != 8 && GET_WORD(&b3_config->info[13]) != 128)
8539                                return _B3_PARM_NOT_SUPPORTED;
8540                        nlc[13] = b3_config->info[13];
8541                        if (GET_WORD(&b3_config->info[15]) >= nlc[13])
8542                                return _B3_PARM_NOT_SUPPORTED;
8543                        nlc[14] = b3_config->info[15];
8544                }
8545        }
8546        else
8547        {
8548                if (plci->B3_prot == 4
8549                    || plci->B3_prot == 5 /*T.30 - FAX*/) return _B3_PARM_NOT_SUPPORTED;
8550        }
8551        add_p(plci, NLC, nlc);
8552        return 0;
8553}
8554
8555/*----------------------------------------------------------------*/
8556/*      make the same as add_b23, but only for the modem related  */
8557/*      L2 and L3 B-Chan protocol.                                */
8558/*                                                                */
8559/*      Enabled L2 and L3 Configurations:                         */
8560/*        If L1 == Modem all negotiation                          */
8561/*          only L2 == Modem with full negotiation is allowed     */
8562/*        If L1 == Modem async or sync                            */
8563/*          only L2 == Transparent is allowed                     */
8564/*        L3 == Modem or L3 == Transparent are allowed            */
8565/*      B2 Configuration for modem:                               */
8566/*          word : enable/disable compression, bitoptions         */
8567/*      B3 Configuration for modem:                               */
8568/*          empty                                                 */
8569/*----------------------------------------------------------------*/
8570static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms)
8571{
8572        static byte lli[12] = {1,1};
8573        static byte llc[3] = {2,0,0};
8574        static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8575        API_PARSE mdm_config[2];
8576        word i;
8577        word b2_config = 0;
8578
8579        for (i = 0; i < 2; i++) mdm_config[i].length = 0;
8580        for (i = 0; i < sizeof(dlc); i++) dlc[i] = 0;
8581
8582        if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8583             && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8584            || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8585                && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8586        {
8587                return (_B_STACK_NOT_SUPPORTED);
8588        }
8589        if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8590            && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8591        {
8592                return (_B_STACK_NOT_SUPPORTED);
8593        }
8594
8595        plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8596        plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8597
8598        if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8599        {
8600                if (api_parse(&bp_parms[4].info[1],
8601                              (word)bp_parms[4].length, "w",
8602                              mdm_config))
8603                {
8604                        return (_WRONG_MESSAGE_FORMAT);
8605                }
8606                b2_config = GET_WORD(mdm_config[0].info);
8607        }
8608
8609        /* OK, L2 is modem */
8610
8611        lli[0] = 1;
8612        lli[1] = 1;
8613        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8614                lli[1] |= 2;
8615        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8616                lli[1] |= 4;
8617
8618        if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8619                lli[1] |= 0x10;
8620                if (plci->rx_dma_descriptor <= 0) {
8621                        plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
8622                        if (plci->rx_dma_descriptor >= 0)
8623                                plci->rx_dma_descriptor++;
8624                }
8625                if (plci->rx_dma_descriptor > 0) {
8626                        lli[1] |= 0x40;
8627                        lli[0] = 6;
8628                        lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8629                        lli[3] = (byte)plci->rx_dma_magic;
8630                        lli[4] = (byte)(plci->rx_dma_magic >>  8);
8631                        lli[5] = (byte)(plci->rx_dma_magic >> 16);
8632                        lli[6] = (byte)(plci->rx_dma_magic >> 24);
8633                }
8634        }
8635
8636        if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8637                lli[1] |= 0x20;
8638        }
8639
8640        llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8641                /*V42*/ 10 : /*V42_IN*/ 9;
8642        llc[2] = 4;                      /* pass L3 always transparent */
8643        add_p(plci, LLI, lli);
8644        add_p(plci, LLC, llc);
8645        i =  1;
8646        PUT_WORD(&dlc[i], plci->appl->MaxDataLength);
8647        i += 2;
8648        if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8649        {
8650                if (bp_parms[4].length)
8651                {
8652                        dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8653                        dlc[i++] = 3; /* Addr A */
8654                        dlc[i++] = 1; /* Addr B */
8655                        dlc[i++] = 7; /* modulo mode */
8656                        dlc[i++] = 7; /* window size */
8657                        dlc[i++] = 0; /* XID len Lo  */
8658                        dlc[i++] = 0; /* XID len Hi  */
8659
8660                        if (b2_config & MDM_B2_DISABLE_V42bis)
8661                        {
8662                                dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8663                        }
8664                        if (b2_config & MDM_B2_DISABLE_MNP)
8665                        {
8666                                dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8667                        }
8668                        if (b2_config & MDM_B2_DISABLE_TRANS)
8669                        {
8670                                dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8671                        }
8672                        if (b2_config & MDM_B2_DISABLE_V42)
8673                        {
8674                                dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8675                        }
8676                        if (b2_config & MDM_B2_DISABLE_COMP)
8677                        {
8678                                dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8679                        }
8680                        i++;
8681                }
8682        }
8683        else
8684        {
8685                dlc[i++] = 3; /* Addr A */
8686                dlc[i++] = 1; /* Addr B */
8687                dlc[i++] = 7; /* modulo mode */
8688                dlc[i++] = 7; /* window size */
8689                dlc[i++] = 0; /* XID len Lo  */
8690                dlc[i++] = 0; /* XID len Hi  */
8691                dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8692                        DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8693                        DLC_MODEMPROT_DISABLE_V42_DETECT |
8694                        DLC_MODEMPROT_DISABLE_COMPRESSION;
8695        }
8696        dlc[0] = (byte)(i - 1);
8697/* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8698        add_p(plci, DLC, dlc);
8699        return (0);
8700}
8701
8702
8703/*------------------------------------------------------------------*/
8704/* send a request for the signaling entity                          */
8705/*------------------------------------------------------------------*/
8706
8707static void sig_req(PLCI *plci, byte req, byte Id)
8708{
8709        if (!plci) return;
8710        if (plci->adapter->adapter_disabled) return;
8711        dbug(1, dprintf("sig_req(%x)", req));
8712        if (req == REMOVE)
8713                plci->sig_remove_id = plci->Sig.Id;
8714        if (plci->req_in == plci->req_in_start) {
8715                plci->req_in += 2;
8716                plci->RBuffer[plci->req_in++] = 0;
8717        }
8718        PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8719        plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
8720        plci->RBuffer[plci->req_in++] = req;  /* request */
8721        plci->RBuffer[plci->req_in++] = 0;    /* channel */
8722        plci->req_in_start = plci->req_in;
8723}
8724
8725/*------------------------------------------------------------------*/
8726/* send a request for the network layer entity                      */
8727/*------------------------------------------------------------------*/
8728
8729static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8730{
8731        if (!plci) return;
8732        if (plci->adapter->adapter_disabled) return;
8733        dbug(1, dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8734        if (req == REMOVE)
8735        {
8736                plci->nl_remove_id = plci->NL.Id;
8737                ncci_remove(plci, 0, (byte)(ncci != 0));
8738                ncci = 0;
8739        }
8740        if (plci->req_in == plci->req_in_start) {
8741                plci->req_in += 2;
8742                plci->RBuffer[plci->req_in++] = 0;
8743        }
8744        PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8745        plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */
8746        plci->RBuffer[plci->req_in++] = req;  /* request */
8747        plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
8748        plci->req_in_start = plci->req_in;
8749}
8750
8751static void send_req(PLCI *plci)
8752{
8753        ENTITY *e;
8754        word l;
8755/*  word i; */
8756
8757        if (!plci) return;
8758        if (plci->adapter->adapter_disabled) return;
8759        channel_xmit_xon(plci);
8760
8761        /* if nothing to do, return */
8762        if (plci->req_in == plci->req_out) return;
8763        dbug(1, dprintf("send_req(in=%d,out=%d)", plci->req_in, plci->req_out));
8764
8765        if (plci->nl_req || plci->sig_req) return;
8766
8767        l = GET_WORD(&plci->RBuffer[plci->req_out]);
8768        plci->req_out += 2;
8769        plci->XData[0].P = &plci->RBuffer[plci->req_out];
8770        plci->req_out += l;
8771        if (plci->RBuffer[plci->req_out] == 1)
8772        {
8773                e = &plci->NL;
8774                plci->req_out++;
8775                e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8776                e->ReqCh = plci->RBuffer[plci->req_out++];
8777                if (!(e->Id & 0x1f))
8778                {
8779                        e->Id = NL_ID;
8780                        plci->RBuffer[plci->req_out - 4] = CAI;
8781                        plci->RBuffer[plci->req_out - 3] = 1;
8782                        plci->RBuffer[plci->req_out - 2] = (plci->Sig.Id == 0xff) ? 0 : plci->Sig.Id;
8783                        plci->RBuffer[plci->req_out - 1] = 0;
8784                        l += 3;
8785                        plci->nl_global_req = plci->nl_req;
8786                }
8787                dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8788        }
8789        else
8790        {
8791                e = &plci->Sig;
8792                if (plci->RBuffer[plci->req_out])
8793                        e->Id = plci->RBuffer[plci->req_out];
8794                plci->req_out++;
8795                e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8796                e->ReqCh = plci->RBuffer[plci->req_out++];
8797                if (!(e->Id & 0x1f))
8798                        plci->sig_global_req = plci->sig_req;
8799                dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8800        }
8801        plci->XData[0].PLength = l;
8802        e->X = plci->XData;
8803        plci->adapter->request(e);
8804        dbug(1, dprintf("send_ok"));
8805}
8806
8807static void send_data(PLCI *plci)
8808{
8809        DIVA_CAPI_ADAPTER *a;
8810        DATA_B3_DESC *data;
8811        NCCI   *ncci_ptr;
8812        word ncci;
8813
8814        if (!plci->nl_req && plci->ncci_ring_list)
8815        {
8816                a = plci->adapter;
8817                ncci = plci->ncci_ring_list;
8818                do
8819                {
8820                        ncci = a->ncci_next[ncci];
8821                        ncci_ptr = &(a->ncci[ncci]);
8822                        if (!(a->ncci_ch[ncci]
8823                              && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8824                        {
8825                                if (ncci_ptr->data_pending)
8826                                {
8827                                        if ((a->ncci_state[ncci] == CONNECTED)
8828                                            || (a->ncci_state[ncci] == INC_ACT_PENDING)
8829                                            || (plci->send_disc == ncci))
8830                                        {
8831                                                data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8832                                                if ((plci->B2_prot == B2_V120_ASYNC)
8833                                                    || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8834                                                    || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8835                                                {
8836                                                        plci->NData[1].P = TransmitBufferGet(plci->appl, data->P);
8837                                                        plci->NData[1].PLength = data->Length;
8838                                                        if (data->Flags & 0x10)
8839                                                                plci->NData[0].P = v120_break_header;
8840                                                        else
8841                                                                plci->NData[0].P = v120_default_header;
8842                                                        plci->NData[0].PLength = 1;
8843                                                        plci->NL.XNum = 2;
8844                                                        plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8845                                                }
8846                                                else
8847                                                {
8848                                                        plci->NData[0].P = TransmitBufferGet(plci->appl, data->P);
8849                                                        plci->NData[0].PLength = data->Length;
8850                                                        if (data->Flags & 0x10)
8851                                                                plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8852
8853                                                        else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8854                                                                plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8855
8856                                                        else
8857                                                                plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8858                                                }
8859                                                plci->NL.X = plci->NData;
8860                                                plci->NL.ReqCh = a->ncci_ch[ncci];
8861                                                dbug(1, dprintf("%x:DREQ(%x:%x)", a->Id, plci->NL.Id, plci->NL.Req));
8862                                                plci->data_sent = true;
8863                                                plci->data_sent_ptr = data->P;
8864                                                a->request(&plci->NL);
8865                                        }
8866                                        else {
8867                                                cleanup_ncci_data(plci, ncci);
8868                                        }
8869                                }
8870                                else if (plci->send_disc == ncci)
8871                                {
8872                                        /* dprintf("N_DISC"); */
8873                                        plci->NData[0].PLength = 0;
8874                                        plci->NL.ReqCh = a->ncci_ch[ncci];
8875                                        plci->NL.Req = plci->nl_req = N_DISC;
8876                                        a->request(&plci->NL);
8877                                        plci->command = _DISCONNECT_B3_R;
8878                                        plci->send_disc = 0;
8879                                }
8880                        }
8881                } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8882                plci->ncci_ring_list = ncci;
8883        }
8884}
8885
8886static void listen_check(DIVA_CAPI_ADAPTER *a)
8887{
8888        word i, j;
8889        PLCI *plci;
8890        byte activnotifiedcalls = 0;
8891
8892        dbug(1, dprintf("listen_check(%d,%d)", a->listen_active, a->max_listen));
8893        if (!remove_started && !a->adapter_disabled)
8894        {
8895                for (i = 0; i < a->max_plci; i++)
8896                {
8897                        plci = &(a->plci[i]);
8898                        if (plci->notifiedcall) activnotifiedcalls++;
8899                }
8900                dbug(1, dprintf("listen_check(%d)", activnotifiedcalls));
8901
8902                for (i = a->listen_active; i < ((word)(a->max_listen + activnotifiedcalls)); i++) {
8903                        if ((j = get_plci(a))) {
8904                                a->listen_active++;
8905                                plci = &a->plci[j - 1];
8906                                plci->State = LISTENING;
8907
8908                                add_p(plci, OAD, "\x01\xfd");
8909
8910                                add_p(plci, KEY, "\x04\x43\x41\x32\x30");
8911
8912                                add_p(plci, CAI, "\x01\xc0");
8913                                add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
8914                                add_p(plci, LLI, "\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */
8915                                add_p(plci, SHIFT | 6, NULL);
8916                                add_p(plci, SIN, "\x02\x00\x00");
8917                                plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
8918                                sig_req(plci, ASSIGN, DSIG_ID);
8919                                send_req(plci);
8920                        }
8921                }
8922        }
8923}
8924
8925/*------------------------------------------------------------------*/
8926/* functions for all parameters sent in INDs                        */
8927/*------------------------------------------------------------------*/
8928
8929static void IndParse(PLCI *plci, word *parms_id, byte **parms, byte multiIEsize)
8930{
8931        word ploc;            /* points to current location within packet */
8932        byte w;
8933        byte wlen;
8934        byte codeset, lock;
8935        byte *in;
8936        word i;
8937        word code;
8938        word mIEindex = 0;
8939        ploc = 0;
8940        codeset = 0;
8941        lock = 0;
8942
8943        in = plci->Sig.RBuffer->P;
8944        for (i = 0; i < parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
8945        {                            /* element but parms array is larger      */
8946                parms[i] = (byte *)"";
8947        }
8948        for (i = 0; i < multiIEsize; i++)
8949        {
8950                parms[i] = (byte *)"";
8951        }
8952
8953        while (ploc < plci->Sig.RBuffer->length - 1) {
8954
8955                /* read information element id and length                   */
8956                w = in[ploc];
8957
8958                if (w & 0x80) {
8959/*    w &=0xf0; removed, cannot detect congestion levels */
8960/*    upper 4 bit masked with w==SHIFT now               */
8961                        wlen = 0;
8962                }
8963                else {
8964                        wlen = (byte)(in[ploc + 1] + 1);
8965                }
8966                /* check if length valid (not exceeding end of packet)      */
8967                if ((ploc + wlen) > 270) return;
8968                if (lock & 0x80) lock &= 0x7f;
8969                else codeset = lock;
8970
8971                if ((w & 0xf0) == SHIFT) {
8972                        codeset = in[ploc];
8973                        if (!(codeset & 0x08)) lock = (byte)(codeset & 7);
8974                        codeset &= 7;
8975                        lock |= 0x80;
8976                }
8977                else {
8978                        if (w == ESC && wlen >= 3) code = in[ploc + 2] | 0x800;
8979                        else code = w;
8980                        code |= (codeset << 8);
8981
8982                        for (i = 1; i < parms_id[0] + 1 && parms_id[i] != code; i++);
8983
8984                        if (i < parms_id[0] + 1) {
8985                                if (!multiIEsize) { /* with multiIEs use next field index,          */
8986                                        mIEindex = i - 1;    /* with normal IEs use same index like parms_id */
8987                                }
8988
8989                                parms[mIEindex] = &in[ploc + 1];
8990                                dbug(1, dprintf("mIE[%d]=0x%x", *parms[mIEindex], in[ploc]));
8991                                if (parms_id[i] == OAD
8992                                    || parms_id[i] == CONN_NR
8993                                    || parms_id[i] == CAD) {
8994                                        if (in[ploc + 2] & 0x80) {
8995                                                in[ploc + 0] = (byte)(in[ploc + 1] + 1);
8996                                                in[ploc + 1] = (byte)(in[ploc + 2] & 0x7f);
8997                                                in[ploc + 2] = 0x80;
8998                                                parms[mIEindex] = &in[ploc];
8999                                        }
9000                                }
9001                                mIEindex++;       /* effects multiIEs only */
9002                        }
9003                }
9004
9005                ploc += (wlen + 1);
9006        }
9007        return;
9008}
9009
9010/*------------------------------------------------------------------*/
9011/* try to match a cip from received BC and HLC                      */
9012/*------------------------------------------------------------------*/
9013
9014static byte ie_compare(byte *ie1, byte *ie2)
9015{
9016        word i;
9017        if (!ie1 || !ie2) return false;
9018        if (!ie1[0]) return false;
9019        for (i = 0; i < (word)(ie1[0] + 1); i++) if (ie1[i] != ie2[i]) return false;
9020        return true;
9021}
9022
9023static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
9024{
9025        word i;
9026        word j;
9027
9028        for (i = 9; i && !ie_compare(bc, cip_bc[i][a->u_law]); i--);
9029
9030        for (j = 16; j < 29 &&
9031                     (!ie_compare(bc, cip_bc[j][a->u_law]) || !ie_compare(hlc, cip_hlc[j])); j++);
9032        if (j == 29) return i;
9033        return j;
9034}
9035
9036
9037static byte AddInfo(byte **add_i,
9038                    byte **fty_i,
9039                    byte *esc_chi,
9040                    byte *facility)
9041{
9042        byte i;
9043        byte j;
9044        byte k;
9045        byte flen;
9046        byte len = 0;
9047        /* facility is a nested structure */
9048        /* FTY can be more than once      */
9049
9050        if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
9051        {
9052                add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9053        }
9054
9055        else
9056        {
9057                add_i[0] = (byte *)"";
9058        }
9059        if (!fty_i[0][0])
9060        {
9061                add_i[3] = (byte *)"";
9062        }
9063        else
9064        {    /* facility array found  */
9065                for (i = 0, j = 1; i < MAX_MULTI_IE && fty_i[i][0]; i++)
9066                {
9067                        dbug(1, dprintf("AddIFac[%d]", fty_i[i][0]));
9068                        len += fty_i[i][0];
9069                        len += 2;
9070                        flen = fty_i[i][0];
9071                        facility[j++] = 0x1c; /* copy fac IE */
9072                        for (k = 0; k <= flen; k++, j++)
9073                        {
9074                                facility[j] = fty_i[i][k];
9075/*      dbug(1, dprintf("%x ",facility[j])); */
9076                        }
9077                }
9078                facility[0] = len;
9079                add_i[3] = facility;
9080        }
9081/*  dbug(1, dprintf("FacArrLen=%d ",len)); */
9082        len = add_i[0][0] + add_i[1][0] + add_i[2][0] + add_i[3][0];
9083        len += 4;                          /* calculate length of all */
9084        return (len);
9085}
9086
9087/*------------------------------------------------------------------*/
9088/* voice and codec features                                         */
9089/*------------------------------------------------------------------*/
9090
9091static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
9092{
9093        byte voice_chi[] = "\x02\x18\x01";
9094        byte channel;
9095
9096        channel = chi[chi[0]] & 0x3;
9097        dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel));
9098        voice_chi[2] = (channel) ? channel : 1;
9099        add_p(plci, FTY, "\x02\x01\x07");             /* B On, default on 1 */
9100        add_p(plci, ESC, voice_chi);                  /* Channel */
9101        sig_req(plci, TEL_CTRL, 0);
9102        send_req(plci);
9103        if (a->AdvSignalPLCI)
9104        {
9105                adv_voice_write_coefs(a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9106        }
9107}
9108
9109static void VoiceChannelOff(PLCI *plci)
9110{
9111        dbug(1, dprintf("ExtDevOFF"));
9112        add_p(plci, FTY, "\x02\x01\x08");             /* B Off */
9113        sig_req(plci, TEL_CTRL, 0);
9114        send_req(plci);
9115        if (plci->adapter->AdvSignalPLCI)
9116        {
9117                adv_voice_clear_config(plci->adapter->AdvSignalPLCI);
9118        }
9119}
9120
9121
9122static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9123                            byte hook_listen)
9124{
9125        word j;
9126        PLCI *splci;
9127
9128        /* check if hardware supports handset with hook states (adv.codec) */
9129        /* or if just a on board codec is supported                        */
9130        /* the advanced codec plci is just for internal use                */
9131
9132        /* diva Pro with on-board codec:                                   */
9133        if (a->profile.Global_Options & HANDSET)
9134        {
9135                /* new call, but hook states are already signalled */
9136                if (a->AdvCodecFLAG)
9137                {
9138                        if (a->AdvSignalAppl != appl || a->AdvSignalPLCI)
9139                        {
9140                                dbug(1, dprintf("AdvSigPlci=0x%x", a->AdvSignalPLCI));
9141                                return 0x2001; /* codec in use by another application */
9142                        }
9143                        if (plci != NULL)
9144                        {
9145                                a->AdvSignalPLCI = plci;
9146                                plci->tel = ADV_VOICE;
9147                        }
9148                        return 0;                      /* adv codec still used */
9149                }
9150                if ((j = get_plci(a)))
9151                {
9152                        splci = &a->plci[j - 1];
9153                        splci->tel = CODEC_PERMANENT;
9154                        /* hook_listen indicates if a facility_req with handset/hook support */
9155                        /* was sent. Otherwise if just a call on an external device was made */
9156                        /* the codec will be used but the hook info will be discarded (just  */
9157                        /* the external controller is in use                                 */
9158                        if (hook_listen) splci->State = ADVANCED_VOICE_SIG;
9159                        else
9160                        {
9161                                splci->State = ADVANCED_VOICE_NOSIG;
9162                                if (plci)
9163                                {
9164                                        plci->spoofed_msg = SPOOFING_REQUIRED;
9165                                }
9166                                /* indicate D-ch connect if  */
9167                        }                                        /* codec is connected OK     */
9168                        if (plci != NULL)
9169                        {
9170                                a->AdvSignalPLCI = plci;
9171                                plci->tel = ADV_VOICE;
9172                        }
9173                        a->AdvSignalAppl = appl;
9174                        a->AdvCodecFLAG = true;
9175                        a->AdvCodecPLCI = splci;
9176                        add_p(splci, CAI, "\x01\x15");
9177                        add_p(splci, LLI, "\x01\x00");
9178                        add_p(splci, ESC, "\x02\x18\x00");
9179                        add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9180                        splci->internal_command = PERM_COD_ASSIGN;
9181                        dbug(1, dprintf("Codec Assign"));
9182                        sig_req(splci, ASSIGN, DSIG_ID);
9183                        send_req(splci);
9184                }
9185                else
9186                {
9187                        return 0x2001; /* wrong state, no more plcis */
9188                }
9189        }
9190        else if (a->profile.Global_Options & ON_BOARD_CODEC)
9191        {
9192                if (hook_listen) return 0x300B;               /* Facility not supported */
9193                /* no hook with SCOM      */
9194                if (plci != NULL) plci->tel = CODEC;
9195                dbug(1, dprintf("S/SCOM codec"));
9196                /* first time we use the scom-s codec we must shut down the internal   */
9197                /* handset application of the card. This can be done by an assign with */
9198                /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9199                if (!a->scom_appl_disable) {
9200                        if ((j = get_plci(a))) {
9201                                splci = &a->plci[j - 1];
9202                                add_p(splci, CAI, "\x01\x80");
9203                                add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9204                                sig_req(splci, ASSIGN, 0xC0);  /* 0xc0 is the TEL_ID */
9205                                send_req(splci);
9206                                a->scom_appl_disable = true;
9207                        }
9208                        else{
9209                                return 0x2001; /* wrong state, no more plcis */
9210                        }
9211                }
9212        }
9213        else return 0x300B;               /* Facility not supported */
9214
9215        return 0;
9216}
9217
9218
9219static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9220{
9221
9222        dbug(1, dprintf("CodecIdCheck"));
9223
9224        if (a->AdvSignalPLCI == plci)
9225        {
9226                dbug(1, dprintf("PLCI owns codec"));
9227                VoiceChannelOff(a->AdvCodecPLCI);
9228                if (a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9229                {
9230                        dbug(1, dprintf("remove temp codec PLCI"));
9231                        plci_remove(a->AdvCodecPLCI);
9232                        a->AdvCodecFLAG  = 0;
9233                        a->AdvCodecPLCI  = NULL;
9234                        a->AdvSignalAppl = NULL;
9235                }
9236                a->AdvSignalPLCI = NULL;
9237        }
9238}
9239
9240/* -------------------------------------------------------------------
9241   Ask for physical address of card on PCI bus
9242   ------------------------------------------------------------------- */
9243static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *a,
9244                                       IDI_SYNC_REQ *preq) {
9245        a->sdram_bar = 0;
9246        if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9247                ENTITY *e = (ENTITY *)preq;
9248
9249                e->user[0] = a->Id - 1;
9250                preq->xdi_sdram_bar.info.bar    = 0;
9251                preq->xdi_sdram_bar.Req         = 0;
9252                preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9253
9254                (*(a->request))(e);
9255
9256                a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9257                dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9258        }
9259}
9260
9261/* -------------------------------------------------------------------
9262   Ask XDI about extended features
9263   ------------------------------------------------------------------- */
9264static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a) {
9265        IDI_SYNC_REQ *preq;
9266        char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
9267
9268        char features[4];
9269        preq = (IDI_SYNC_REQ *)&buffer[0];
9270
9271        if (!diva_xdi_extended_features) {
9272                ENTITY *e = (ENTITY *)preq;
9273                diva_xdi_extended_features |= 0x80000000;
9274
9275                e->user[0] = a->Id - 1;
9276                preq->xdi_extended_features.Req = 0;
9277                preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9278                preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9279                preq->xdi_extended_features.info.features = &features[0];
9280
9281                (*(a->request))(e);
9282
9283                if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9284                        /*
9285                          Check features located in the byte '0'
9286                        */
9287                        if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9288                                diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9289                        }
9290                        if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9291                                diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9292                                dbug(1, dprintf("XDI provides RxDMA"));
9293                        }
9294                        if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9295                                diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9296                        }
9297                        if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9298                                diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9299                                dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9300                        }
9301
9302                }
9303        }
9304
9305        diva_ask_for_xdi_sdram_bar(a, preq);
9306}
9307
9308/*------------------------------------------------------------------*/
9309/* automatic law                                                    */
9310/*------------------------------------------------------------------*/
9311/* called from OS specific part after init time to get the Law              */
9312/* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9313void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9314{
9315        word j;
9316        PLCI *splci;
9317
9318        if (a->automatic_law) {
9319                return;
9320        }
9321        if ((j = get_plci(a))) {
9322                diva_get_extended_adapter_features(a);
9323                splci = &a->plci[j - 1];
9324                a->automatic_lawPLCI = splci;
9325                a->automatic_law = 1;
9326                add_p(splci, CAI, "\x01\x80");
9327                add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9328                splci->internal_command = USELAW_REQ;
9329                splci->command = 0;
9330                splci->number = 0;
9331                sig_req(splci, ASSIGN, DSIG_ID);
9332                send_req(splci);
9333        }
9334}
9335
9336/* called from OS specific part if an application sends an Capi20Release */
9337word CapiRelease(word Id)
9338{
9339        word i, j, appls_found;
9340        PLCI *plci;
9341        APPL   *this;
9342        DIVA_CAPI_ADAPTER *a;
9343
9344        if (!Id)
9345        {
9346                dbug(0, dprintf("A: CapiRelease(Id==0)"));
9347                return (_WRONG_APPL_ID);
9348        }
9349
9350        this = &application[Id - 1];               /* get application pointer */
9351
9352        for (i = 0, appls_found = 0; i < max_appl; i++)
9353        {
9354                if (application[i].Id)       /* an application has been found        */
9355                {
9356                        appls_found++;
9357                }
9358        }
9359
9360        for (i = 0; i < max_adapter; i++)             /* scan all adapters...    */
9361        {
9362                a = &adapter[i];
9363                if (a->request)
9364                {
9365                        a->Info_Mask[Id - 1] = 0;
9366                        a->CIP_Mask[Id - 1] = 0;
9367                        a->Notification_Mask[Id - 1] = 0;
9368                        a->codec_listen[Id - 1] = NULL;
9369                        a->requested_options_table[Id - 1] = 0;
9370                        for (j = 0; j < a->max_plci; j++)           /* and all PLCIs connected */
9371                        {                                      /* with this application   */
9372                                plci = &a->plci[j];
9373                                if (plci->Id)                         /* if plci owns no application */
9374                                {                                    /* it may be not jet connected */
9375                                        if (plci->State == INC_CON_PENDING
9376                                            || plci->State == INC_CON_ALERT)
9377                                        {
9378                                                if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9379                                                {
9380                                                        clear_c_ind_mask_bit(plci, (word)(Id - 1));
9381                                                        if (c_ind_mask_empty(plci))
9382                                                        {
9383                                                                sig_req(plci, HANGUP, 0);
9384                                                                send_req(plci);
9385                                                                plci->State = OUTG_DIS_PENDING;
9386                                                        }
9387                                                }
9388                                        }
9389                                        if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9390                                        {
9391                                                clear_c_ind_mask_bit(plci, (word)(Id - 1));
9392                                                if (c_ind_mask_empty(plci))
9393                                                {
9394                                                        if (!plci->appl)
9395                                                        {
9396                                                                plci_remove(plci);
9397                                                                plci->State = IDLE;
9398                                                        }
9399                                                }
9400                                        }
9401                                        if (plci->appl == this)
9402                                        {
9403                                                plci->appl = NULL;
9404                                                plci_remove(plci);
9405                                                plci->State = IDLE;
9406                                        }
9407                                }
9408                        }
9409                        listen_check(a);
9410
9411                        if (a->flag_dynamic_l1_down)
9412                        {
9413                                if (appls_found == 1)            /* last application does a capi release */
9414                                {
9415                                        if ((j = get_plci(a)))
9416                                        {
9417                                                plci = &a->plci[j - 1];
9418                                                plci->command = 0;
9419                                                add_p(plci, OAD, "\x01\xfd");
9420                                                add_p(plci, CAI, "\x01\x80");
9421                                                add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9422                                                add_p(plci, SHIFT | 6, NULL);
9423                                                add_p(plci, SIN, "\x02\x00\x00");
9424                                                plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9425                                                sig_req(plci, ASSIGN, DSIG_ID);
9426                                                add_p(plci, FTY, "\x02\xff\x06"); /* l1 down */
9427                                                sig_req(plci, SIG_CTRL, 0);
9428                                                send_req(plci);
9429                                        }
9430                                }
9431                        }
9432                        if (a->AdvSignalAppl == this)
9433                        {
9434                                this->NullCREnable = false;
9435                                if (a->AdvCodecPLCI)
9436                                {
9437                                        plci_remove(a->AdvCodecPLCI);
9438                                        a->AdvCodecPLCI->tel = 0;
9439                                        a->AdvCodecPLCI->adv_nl = 0;
9440                                }
9441                                a->AdvSignalAppl = NULL;
9442                                a->AdvSignalPLCI = NULL;
9443                                a->AdvCodecFLAG = 0;
9444                                a->AdvCodecPLCI = NULL;
9445                        }
9446                }
9447        }
9448
9449        this->Id = 0;
9450
9451        return GOOD;
9452}
9453
9454static word plci_remove_check(PLCI *plci)
9455{
9456        if (!plci) return true;
9457        if (!plci->NL.Id && c_ind_mask_empty(plci))
9458        {
9459                if (plci->Sig.Id == 0xff)
9460                        plci->Sig.Id = 0;
9461                if (!plci->Sig.Id)
9462                {
9463                        dbug(1, dprintf("plci_remove_complete(%x)", plci->Id));
9464                        dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci->tel, plci->Sig.Id));
9465                        if (plci->Id)
9466                        {
9467                                CodecIdCheck(plci->adapter, plci);
9468                                clear_b1_config(plci);
9469                                ncci_remove(plci, 0, false);
9470                                plci_free_msg_in_queue(plci);
9471                                channel_flow_control_remove(plci);
9472                                plci->Id = 0;
9473                                plci->State = IDLE;
9474                                plci->channels = 0;
9475                                plci->appl = NULL;
9476                                plci->notifiedcall = 0;
9477                        }
9478                        listen_check(plci->adapter);
9479                        return true;
9480                }
9481        }
9482        return false;
9483}
9484
9485
9486/*------------------------------------------------------------------*/
9487
9488static byte plci_nl_busy(PLCI *plci)
9489{
9490        /* only applicable for non-multiplexed protocols */
9491        return (plci->nl_req
9492                || (plci->ncci_ring_list
9493                    && plci->adapter->ncci_ch[plci->ncci_ring_list]
9494                    && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9495}
9496
9497
9498/*------------------------------------------------------------------*/
9499/* DTMF facilities                                                  */
9500/*------------------------------------------------------------------*/
9501
9502
9503static struct
9504{
9505        byte send_mask;
9506        byte listen_mask;
9507        byte character;
9508        byte code;
9509} dtmf_digit_map[] =
9510{
9511        { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9512        { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9513        { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9514        { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9515        { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9516        { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9517        { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9518        { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9519        { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9520        { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9521        { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9522        { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9523        { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9524        { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9525        { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9526        { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9527        { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9528        { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9529        { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9530        { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9531
9532        { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9533        { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9534        { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9535        { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9536        { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9537        { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9538        { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9539        { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9540        { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9541        { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9542        { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9543        { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9544        { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9545        { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9546        { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9547        { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9548        { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9549        { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9550        { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9551        { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9552        { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9553        { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9554        { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9555        { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9556        { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9557        { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9558        { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9559        { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9560        { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9561        { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9562        { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9563        { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9564        { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9565        { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9566        { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9567        { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9568        { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9569        { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9570        { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9571        { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9572        { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9573        { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9574        { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9575        { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9576        { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9577        { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9578        { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9579        { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9580        { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9581        { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9582        { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9583        { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9584
9585};
9586
9587#define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9588
9589
9590static void dtmf_enable_receiver(PLCI *plci, byte enable_mask)
9591{
9592        word min_digit_duration, min_gap_duration;
9593
9594        dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9595                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9596                        (char *)(FILE_), __LINE__, enable_mask));
9597
9598        if (enable_mask != 0)
9599        {
9600                min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9601                min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9602                plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9603                PUT_WORD(&plci->internal_req_buffer[1], min_digit_duration);
9604                PUT_WORD(&plci->internal_req_buffer[3], min_gap_duration);
9605                plci->NData[0].PLength = 5;
9606
9607                PUT_WORD(&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9608                plci->NData[0].PLength += 2;
9609                capidtmf_recv_enable(&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9610
9611        }
9612        else
9613        {
9614                plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9615                plci->NData[0].PLength = 1;
9616
9617                capidtmf_recv_disable(&(plci->capidtmf_state));
9618
9619        }
9620        plci->NData[0].P = plci->internal_req_buffer;
9621        plci->NL.X = plci->NData;
9622        plci->NL.ReqCh = 0;
9623        plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9624        plci->adapter->request(&plci->NL);
9625}
9626
9627
9628static void dtmf_send_digits(PLCI *plci, byte *digit_buffer, word digit_count)
9629{
9630        word w, i;
9631
9632        dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9633                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9634                        (char *)(FILE_), __LINE__, digit_count));
9635
9636        plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9637        w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9638        PUT_WORD(&plci->internal_req_buffer[1], w);
9639        w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9640        PUT_WORD(&plci->internal_req_buffer[3], w);
9641        for (i = 0; i < digit_count; i++)
9642        {
9643                w = 0;
9644                while ((w < DTMF_DIGIT_MAP_ENTRIES)
9645                       && (digit_buffer[i] != dtmf_digit_map[w].character))
9646                {
9647                        w++;
9648                }
9649                plci->internal_req_buffer[5 + i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9650                        dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9651        }
9652        plci->NData[0].PLength = 5 + digit_count;
9653        plci->NData[0].P = plci->internal_req_buffer;
9654        plci->NL.X = plci->NData;
9655        plci->NL.ReqCh = 0;
9656        plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9657        plci->adapter->request(&plci->NL);
9658}
9659
9660
9661static void dtmf_rec_clear_config(PLCI *plci)
9662{
9663
9664        dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9665                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9666                        (char *)(FILE_), __LINE__));
9667
9668        plci->dtmf_rec_active = 0;
9669        plci->dtmf_rec_pulse_ms = 0;
9670        plci->dtmf_rec_pause_ms = 0;
9671
9672        capidtmf_init(&(plci->capidtmf_state), plci->adapter->u_law);
9673
9674}
9675
9676
9677static void dtmf_send_clear_config(PLCI *plci)
9678{
9679
9680        dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9681                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9682                        (char *)(FILE_), __LINE__));
9683
9684        plci->dtmf_send_requests = 0;
9685        plci->dtmf_send_pulse_ms = 0;
9686        plci->dtmf_send_pause_ms = 0;
9687}
9688
9689
9690static void dtmf_prepare_switch(dword Id, PLCI *plci)
9691{
9692
9693        dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9694                        UnMapId(Id), (char *)(FILE_), __LINE__));
9695
9696        while (plci->dtmf_send_requests != 0)
9697                dtmf_confirmation(Id, plci);
9698}
9699
9700
9701static word dtmf_save_config(dword Id, PLCI *plci, byte Rc)
9702{
9703
9704        dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9705                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9706
9707        return (GOOD);
9708}
9709
9710
9711static word dtmf_restore_config(dword Id, PLCI *plci, byte Rc)
9712{
9713        word Info;
9714
9715        dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9716                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9717
9718        Info = GOOD;
9719        if (plci->B1_facilities & B1_FACILITY_DTMFR)
9720        {
9721                switch (plci->adjust_b_state)
9722                {
9723                case ADJUST_B_RESTORE_DTMF_1:
9724                        plci->internal_command = plci->adjust_b_command;
9725                        if (plci_nl_busy(plci))
9726                        {
9727                                plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9728                                break;
9729                        }
9730                        dtmf_enable_receiver(plci, plci->dtmf_rec_active);
9731                        plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9732                        break;
9733                case ADJUST_B_RESTORE_DTMF_2:
9734                        if ((Rc != OK) && (Rc != OK_FC))
9735                        {
9736                                dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9737                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9738                                Info = _WRONG_STATE;
9739                                break;
9740                        }
9741                        break;
9742                }
9743        }
9744        return (Info);
9745}
9746
9747
9748static void dtmf_command(dword Id, PLCI *plci, byte Rc)
9749{
9750        word internal_command, Info;
9751        byte mask;
9752        byte result[4];
9753
9754        dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9755                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9756                        plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9757                        plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9758
9759        Info = GOOD;
9760        result[0] = 2;
9761        PUT_WORD(&result[1], DTMF_SUCCESS);
9762        internal_command = plci->internal_command;
9763        plci->internal_command = 0;
9764        mask = 0x01;
9765        switch (plci->dtmf_cmd)
9766        {
9767
9768        case DTMF_LISTEN_TONE_START:
9769                mask <<= 1;
9770        case DTMF_LISTEN_MF_START:
9771                mask <<= 1;
9772
9773        case DTMF_LISTEN_START:
9774                switch (internal_command)
9775                {
9776                default:
9777                        adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9778                                                                  B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9779                case DTMF_COMMAND_1:
9780                        if (adjust_b_process(Id, plci, Rc) != GOOD)
9781                        {
9782                                dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9783                                                UnMapId(Id), (char *)(FILE_), __LINE__));
9784                                Info = _FACILITY_NOT_SUPPORTED;
9785                                break;
9786                        }
9787                        if (plci->internal_command)
9788                                return;
9789                case DTMF_COMMAND_2:
9790                        if (plci_nl_busy(plci))
9791                        {
9792                                plci->internal_command = DTMF_COMMAND_2;
9793                                return;
9794                        }
9795                        plci->internal_command = DTMF_COMMAND_3;
9796                        dtmf_enable_receiver(plci, (byte)(plci->dtmf_rec_active | mask));
9797                        return;
9798                case DTMF_COMMAND_3:
9799                        if ((Rc != OK) && (Rc != OK_FC))
9800                        {
9801                                dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9802                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9803                                Info = _FACILITY_NOT_SUPPORTED;
9804                                break;
9805                        }
9806
9807                        plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9808
9809                        plci->dtmf_rec_active |= mask;
9810                        break;
9811                }
9812                break;
9813
9814
9815        case DTMF_LISTEN_TONE_STOP:
9816                mask <<= 1;
9817        case DTMF_LISTEN_MF_STOP:
9818                mask <<= 1;
9819
9820        case DTMF_LISTEN_STOP:
9821                switch (internal_command)
9822                {
9823                default:
9824                        plci->dtmf_rec_active &= ~mask;
9825                        if (plci->dtmf_rec_active)
9826                                break;
9827/*
9828  case DTMF_COMMAND_1:
9829  if (plci->dtmf_rec_active)
9830  {
9831  if (plci_nl_busy (plci))
9832  {
9833  plci->internal_command = DTMF_COMMAND_1;
9834  return;
9835  }
9836  plci->dtmf_rec_active &= ~mask;
9837  plci->internal_command = DTMF_COMMAND_2;
9838  dtmf_enable_receiver (plci, false);
9839  return;
9840  }
9841  Rc = OK;
9842  case DTMF_COMMAND_2:
9843  if ((Rc != OK) && (Rc != OK_FC))
9844  {
9845  dbug (1, dprintf("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9846  UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9847  Info = _FACILITY_NOT_SUPPORTED;
9848  break;
9849  }
9850*/
9851                        adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
9852                                                                  ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9853                case DTMF_COMMAND_3:
9854                        if (adjust_b_process(Id, plci, Rc) != GOOD)
9855                        {
9856                                dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9857                                                UnMapId(Id), (char *)(FILE_), __LINE__));
9858                                Info = _FACILITY_NOT_SUPPORTED;
9859                                break;
9860                        }
9861                        if (plci->internal_command)
9862                                return;
9863                        break;
9864                }
9865                break;
9866
9867
9868        case DTMF_SEND_TONE:
9869                mask <<= 1;
9870        case DTMF_SEND_MF:
9871                mask <<= 1;
9872
9873        case DTMF_DIGITS_SEND:
9874                switch (internal_command)
9875                {
9876                default:
9877                        adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9878                                                                  ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9879                                           DTMF_COMMAND_1);
9880                case DTMF_COMMAND_1:
9881                        if (adjust_b_process(Id, plci, Rc) != GOOD)
9882                        {
9883                                dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9884                                                UnMapId(Id), (char *)(FILE_), __LINE__));
9885                                Info = _FACILITY_NOT_SUPPORTED;
9886                                break;
9887                        }
9888                        if (plci->internal_command)
9889                                return;
9890                case DTMF_COMMAND_2:
9891                        if (plci_nl_busy(plci))
9892                        {
9893                                plci->internal_command = DTMF_COMMAND_2;
9894                                return;
9895                        }
9896                        plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9897                        plci->internal_command = DTMF_COMMAND_3;
9898                        dtmf_send_digits(plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9899                        return;
9900                case DTMF_COMMAND_3:
9901                        if ((Rc != OK) && (Rc != OK_FC))
9902                        {
9903                                dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9904                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9905                                if (plci->dtmf_send_requests != 0)
9906                                        (plci->dtmf_send_requests)--;
9907                                Info = _FACILITY_NOT_SUPPORTED;
9908                                break;
9909                        }
9910                        return;
9911                }
9912                break;
9913        }
9914        sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9915              "wws", Info, SELECTOR_DTMF, result);
9916}
9917
9918
9919static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
9920{
9921        word Info;
9922        word i, j;
9923        byte mask;
9924        API_PARSE dtmf_parms[5];
9925        byte result[40];
9926
9927        dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9928                        UnMapId(Id), (char *)(FILE_), __LINE__));
9929
9930        Info = GOOD;
9931        result[0] = 2;
9932        PUT_WORD(&result[1], DTMF_SUCCESS);
9933        if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9934        {
9935                dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9936                                UnMapId(Id), (char *)(FILE_), __LINE__));
9937                Info = _FACILITY_NOT_SUPPORTED;
9938        }
9939        else if (api_parse(&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9940        {
9941                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9942                                UnMapId(Id), (char *)(FILE_), __LINE__));
9943                Info = _WRONG_MESSAGE_FORMAT;
9944        }
9945
9946        else if ((GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9947                 || (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9948        {
9949                if (!((a->requested_options_table[appl->Id - 1])
9950                      & (1L << PRIVATE_DTMF_TONE)))
9951                {
9952                        dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9953                                        UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9954                        PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9955                }
9956                else
9957                {
9958                        for (i = 0; i < 32; i++)
9959                                result[4 + i] = 0;
9960                        if (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9961                        {
9962                                for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9963                                {
9964                                        if (dtmf_digit_map[i].listen_mask != 0)
9965                                                result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9966                                }
9967                        }
9968                        else
9969                        {
9970                                for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9971                                {
9972                                        if (dtmf_digit_map[i].send_mask != 0)
9973                                                result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9974                                }
9975                        }
9976                        result[0] = 3 + 32;
9977                        result[3] = 32;
9978                }
9979        }
9980
9981        else if (plci == NULL)
9982        {
9983                dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9984                                UnMapId(Id), (char *)(FILE_), __LINE__));
9985                Info = _WRONG_IDENTIFIER;
9986        }
9987        else
9988        {
9989                if (!plci->State
9990                    || !plci->NL.Id || plci->nl_remove_id)
9991                {
9992                        dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9993                                        UnMapId(Id), (char *)(FILE_), __LINE__));
9994                        Info = _WRONG_STATE;
9995                }
9996                else
9997                {
9998                        plci->command = 0;
9999                        plci->dtmf_cmd = GET_WORD(dtmf_parms[0].info);
10000                        mask = 0x01;
10001                        switch (plci->dtmf_cmd)
10002                        {
10003
10004                        case DTMF_LISTEN_TONE_START:
10005                        case DTMF_LISTEN_TONE_STOP:
10006                                mask <<= 1;
10007                        case DTMF_LISTEN_MF_START:
10008                        case DTMF_LISTEN_MF_STOP:
10009                                mask <<= 1;
10010                                if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10011                                      & (1L << PRIVATE_DTMF_TONE)))
10012                                {
10013                                        dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10014                                                        UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10015                                        PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10016                                        break;
10017                                }
10018
10019                        case DTMF_LISTEN_START:
10020                        case DTMF_LISTEN_STOP:
10021                                if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10022                                    && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10023                                {
10024                                        dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
10025                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
10026                                        Info = _FACILITY_NOT_SUPPORTED;
10027                                        break;
10028                                }
10029                                if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10030                                {
10031                                        if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10032                                        {
10033                                                plci->dtmf_rec_pulse_ms = 0;
10034                                                plci->dtmf_rec_pause_ms = 0;
10035                                        }
10036                                        else
10037                                        {
10038                                                plci->dtmf_rec_pulse_ms = GET_WORD(dtmf_parms[1].info);
10039                                                plci->dtmf_rec_pause_ms = GET_WORD(dtmf_parms[2].info);
10040                                        }
10041                                }
10042                                start_internal_command(Id, plci, dtmf_command);
10043                                return (false);
10044
10045
10046                        case DTMF_SEND_TONE:
10047                                mask <<= 1;
10048                        case DTMF_SEND_MF:
10049                                mask <<= 1;
10050                                if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10051                                      & (1L << PRIVATE_DTMF_TONE)))
10052                                {
10053                                        dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10054                                                        UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10055                                        PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10056                                        break;
10057                                }
10058
10059                        case DTMF_DIGITS_SEND:
10060                                if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10061                                {
10062                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
10063                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
10064                                        Info = _WRONG_MESSAGE_FORMAT;
10065                                        break;
10066                                }
10067                                if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10068                                {
10069                                        plci->dtmf_send_pulse_ms = GET_WORD(dtmf_parms[1].info);
10070                                        plci->dtmf_send_pause_ms = GET_WORD(dtmf_parms[2].info);
10071                                }
10072                                i = 0;
10073                                j = 0;
10074                                while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10075                                {
10076                                        j = 0;
10077                                        while ((j < DTMF_DIGIT_MAP_ENTRIES)
10078                                               && ((dtmf_parms[3].info[i + 1] != dtmf_digit_map[j].character)
10079                                                   || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10080                                        {
10081                                                j++;
10082                                        }
10083                                        i++;
10084                                }
10085                                if (j == DTMF_DIGIT_MAP_ENTRIES)
10086                                {
10087                                        dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10088                                                        UnMapId(Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10089                                        PUT_WORD(&result[1], DTMF_INCORRECT_DIGIT);
10090                                        break;
10091                                }
10092                                if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10093                                {
10094                                        dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
10095                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
10096                                        Info = _WRONG_STATE;
10097                                        break;
10098                                }
10099                                api_save_msg(dtmf_parms, "wwws", &plci->saved_msg);
10100                                start_internal_command(Id, plci, dtmf_command);
10101                                return (false);
10102
10103                        default:
10104                                dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10105                                                UnMapId(Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10106                                PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10107                        }
10108                }
10109        }
10110        sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10111              "wws", Info, SELECTOR_DTMF, result);
10112        return (false);
10113}
10114
10115
10116static void dtmf_confirmation(dword Id, PLCI *plci)
10117{
10118        word i;
10119        byte result[4];
10120
10121        dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
10122                        UnMapId(Id), (char *)(FILE_), __LINE__));
10123
10124        result[0] = 2;
10125        PUT_WORD(&result[1], DTMF_SUCCESS);
10126        if (plci->dtmf_send_requests != 0)
10127        {
10128                sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10129                      "wws", GOOD, SELECTOR_DTMF, result);
10130                (plci->dtmf_send_requests)--;
10131                for (i = 0; i < plci->dtmf_send_requests; i++)
10132                        plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i + 1];
10133        }
10134}
10135
10136
10137static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length)
10138{
10139        word i, j, n;
10140
10141        dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10142                        UnMapId(Id), (char *)(FILE_), __LINE__));
10143
10144        n = 0;
10145        for (i = 1; i < length; i++)
10146        {
10147                j = 0;
10148                while ((j < DTMF_DIGIT_MAP_ENTRIES)
10149                       && ((msg[i] != dtmf_digit_map[j].code)
10150                           || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10151                {
10152                        j++;
10153                }
10154                if (j < DTMF_DIGIT_MAP_ENTRIES)
10155                {
10156
10157                        if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10158                            && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10159                            && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10160                        {
10161                                if (n + 1 == i)
10162                                {
10163                                        for (i = length; i > n + 1; i--)
10164                                                msg[i] = msg[i - 1];
10165                                        length++;
10166                                        i++;
10167                                }
10168                                msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10169                        }
10170                        plci->tone_last_indication_code = dtmf_digit_map[j].character;
10171
10172                        msg[++n] = dtmf_digit_map[j].character;
10173                }
10174        }
10175        if (n != 0)
10176        {
10177                msg[0] = (byte) n;
10178                sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10179        }
10180}
10181
10182
10183/*------------------------------------------------------------------*/
10184/* DTMF parameters                                                  */
10185/*------------------------------------------------------------------*/
10186
10187static void dtmf_parameter_write(PLCI *plci)
10188{
10189        word i;
10190        byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10191
10192        dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10193                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10194                        (char *)(FILE_), __LINE__));
10195
10196        parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10197        parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10198        for (i = 0; i < plci->dtmf_parameter_length; i++)
10199                parameter_buffer[2 + i] = plci->dtmf_parameter_buffer[i];
10200        add_p(plci, FTY, parameter_buffer);
10201        sig_req(plci, TEL_CTRL, 0);
10202        send_req(plci);
10203}
10204
10205
10206static void dtmf_parameter_clear_config(PLCI *plci)
10207{
10208
10209        dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10210                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10211                        (char *)(FILE_), __LINE__));
10212
10213        plci->dtmf_parameter_length = 0;
10214}
10215
10216
10217static void dtmf_parameter_prepare_switch(dword Id, PLCI *plci)
10218{
10219
10220        dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10221                        UnMapId(Id), (char *)(FILE_), __LINE__));
10222
10223}
10224
10225
10226static word dtmf_parameter_save_config(dword Id, PLCI *plci, byte Rc)
10227{
10228
10229        dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10230                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10231
10232        return (GOOD);
10233}
10234
10235
10236static word dtmf_parameter_restore_config(dword Id, PLCI *plci, byte Rc)
10237{
10238        word Info;
10239
10240        dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10241                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10242
10243        Info = GOOD;
10244        if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10245            && (plci->dtmf_parameter_length != 0))
10246        {
10247                switch (plci->adjust_b_state)
10248                {
10249                case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10250                        plci->internal_command = plci->adjust_b_command;
10251                        if (plci->sig_req)
10252                        {
10253                                plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10254                                break;
10255                        }
10256                        dtmf_parameter_write(plci);
10257                        plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10258                        break;
10259                case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10260                        if ((Rc != OK) && (Rc != OK_FC))
10261                        {
10262                                dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10263                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10264                                Info = _WRONG_STATE;
10265                                break;
10266                        }
10267                        break;
10268                }
10269        }
10270        return (Info);
10271}
10272
10273
10274/*------------------------------------------------------------------*/
10275/* Line interconnect facilities                                     */
10276/*------------------------------------------------------------------*/
10277
10278
10279LI_CONFIG   *li_config_table;
10280word li_total_channels;
10281
10282
10283/*------------------------------------------------------------------*/
10284/* translate a CHI information element to a channel number          */
10285/* returns 0xff - any channel                                       */
10286/*         0xfe - chi wrong coding                                  */
10287/*         0xfd - D-channel                                         */
10288/*         0x00 - no channel                                        */
10289/*         else channel number / PRI: timeslot                      */
10290/* if channels is provided we accept more than one channel.         */
10291/*------------------------------------------------------------------*/
10292
10293static byte chi_to_channel(byte *chi, dword *pchannelmap)
10294{
10295        int p;
10296        int i;
10297        dword map;
10298        byte excl;
10299        byte ofs;
10300        byte ch;
10301
10302        if (pchannelmap) *pchannelmap = 0;
10303        if (!chi[0]) return 0xff;
10304        excl = 0;
10305
10306        if (chi[1] & 0x20) {
10307                if (chi[0] == 1 && chi[1] == 0xac) return 0xfd; /* exclusive d-channel */
10308                for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10309                if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10310                if ((chi[1] | 0xc8) != 0xe9) return 0xfe;
10311                if (chi[1] & 0x08) excl = 0x40;
10312
10313                /* int. id present */
10314                if (chi[1] & 0x40) {
10315                        p = i + 1;
10316                        for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10317                        if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10318                }
10319
10320                /* coding standard, Number/Map, Channel Type */
10321                p = i + 1;
10322                for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10323                if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10324                if ((chi[p] | 0xd0) != 0xd3) return 0xfe;
10325
10326                /* Number/Map */
10327                if (chi[p] & 0x10) {
10328
10329                        /* map */
10330                        if ((chi[0] - p) == 4) ofs = 0;
10331                        else if ((chi[0] - p) == 3) ofs = 1;
10332                        else return 0xfe;
10333                        ch = 0;
10334                        map = 0;
10335                        for (i = 0; i < 4 && p < chi[0]; i++) {
10336                                p++;
10337                                ch += 8;
10338                                map <<= 8;
10339                                if (chi[p]) {
10340                                        for (ch = 0; !(chi[p] & (1 << ch)); ch++);
10341                                        map |= chi[p];
10342                                }
10343                        }
10344                        ch += ofs;
10345                        map <<= ofs;
10346                }
10347                else {
10348
10349                        /* number */
10350                        p = i + 1;
10351                        ch = chi[p] & 0x3f;
10352                        if (pchannelmap) {
10353                                if ((byte)(chi[0] - p) > 30) return 0xfe;
10354                                map = 0;
10355                                for (i = p; i <= chi[0]; i++) {
10356                                        if ((chi[i] & 0x7f) > 31) return 0xfe;
10357                                        map |= (1L << (chi[i] & 0x7f));
10358                                }
10359                        }
10360                        else {
10361                                if (p != chi[0]) return 0xfe;
10362                                if (ch > 31) return 0xfe;
10363                                map = (1L << ch);
10364                        }
10365                        if (chi[p] & 0x40) return 0xfe;
10366                }
10367                if (pchannelmap) *pchannelmap = map;
10368                else if (map != ((dword)(1L << ch))) return 0xfe;
10369                return (byte)(excl | ch);
10370        }
10371        else {  /* not PRI */
10372                for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10373                if (i != chi[0] || !(chi[i] & 0x80)) return 0xfe;
10374                if (chi[1] & 0x08) excl = 0x40;
10375
10376                switch (chi[1] | 0x98) {
10377                case 0x98: return 0;
10378                case 0x99:
10379                        if (pchannelmap) *pchannelmap = 2;
10380                        return excl | 1;
10381                case 0x9a:
10382                        if (pchannelmap) *pchannelmap = 4;
10383                        return excl | 2;
10384                case 0x9b: return 0xff;
10385                case 0x9c: return 0xfd; /* d-ch */
10386                default: return 0xfe;
10387                }
10388        }
10389}
10390
10391
10392static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id)
10393{
10394        DIVA_CAPI_ADAPTER *a;
10395        PLCI *splci;
10396        byte old_id;
10397
10398        a = plci->adapter;
10399        old_id = plci->li_bchannel_id;
10400        if (a->li_pri)
10401        {
10402                if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10403                        li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10404                plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10405                if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10406                        li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10407        }
10408        else
10409        {
10410                if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10411                {
10412                        if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10413                                li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10414                        plci->li_bchannel_id = bchannel_id & 0x03;
10415                        if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10416                        {
10417                                splci = a->AdvSignalPLCI;
10418                                if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10419                                {
10420                                        if ((splci->li_bchannel_id != 0)
10421                                            && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10422                                        {
10423                                                li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10424                                        }
10425                                        splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10426                                        li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10427                                        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10428                                                        (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10429                                                        (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10430                                }
10431                        }
10432                        if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10433                                li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10434                }
10435        }
10436        if ((old_id == 0) && (plci->li_bchannel_id != 0)
10437            && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10438        {
10439                mixer_clear_config(plci);
10440        }
10441        dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10442                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10443                        (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10444}
10445
10446
10447static void mixer_set_bchannel_id(PLCI *plci, byte *chi)
10448{
10449        DIVA_CAPI_ADAPTER *a;
10450        PLCI *splci;
10451        byte ch, old_id;
10452
10453        a = plci->adapter;
10454        old_id = plci->li_bchannel_id;
10455        ch = chi_to_channel(chi, NULL);
10456        if (!(ch & 0x80))
10457        {
10458                if (a->li_pri)
10459                {
10460                        if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10461                                li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10462                        plci->li_bchannel_id = (ch & 0x1f) + 1;
10463                        if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10464                                li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10465                }
10466                else
10467                {
10468                        if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10469                        {
10470                                if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10471                                        li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10472                                plci->li_bchannel_id = ch & 0x1f;
10473                                if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10474                                {
10475                                        splci = a->AdvSignalPLCI;
10476                                        if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10477                                        {
10478                                                if ((splci->li_bchannel_id != 0)
10479                                                    && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10480                                                {
10481                                                        li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10482                                                }
10483                                                splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10484                                                li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10485                                                dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10486                                                                (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10487                                                                (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10488                                        }
10489                                }
10490                                if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10491                                        li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10492                        }
10493                }
10494        }
10495        if ((old_id == 0) && (plci->li_bchannel_id != 0)
10496            && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10497        {
10498                mixer_clear_config(plci);
10499        }
10500        dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10501                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10502                        (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10503}
10504
10505
10506#define MIXER_MAX_DUMP_CHANNELS 34
10507
10508static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER *a)
10509{
10510        static char hex_digit_table[0x10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
10511        word n, i, j;
10512        char *p;
10513        char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10514
10515        dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10516                        (dword)(UnMapController(a->Id)), (char *)(FILE_), __LINE__));
10517
10518        for (i = 0; i < li_total_channels; i++)
10519        {
10520                li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10521                if (li_config_table[i].chflags != 0)
10522                        li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10523                else
10524                {
10525                        for (j = 0; j < li_total_channels; j++)
10526                        {
10527                                if (((li_config_table[i].flag_table[j]) != 0)
10528                                    || ((li_config_table[j].flag_table[i]) != 0))
10529                                {
10530                                        li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10531                                }
10532                                if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10533                                    || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10534                                {
10535                                        li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10536                                }
10537                        }
10538                }
10539        }
10540        for (i = 0; i < li_total_channels; i++)
10541        {
10542                for (j = 0; j < li_total_channels; j++)
10543                {
10544                        li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10545                        if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10546                                li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10547                }
10548        }
10549        for (n = 0; n < li_total_channels; n++)
10550        {
10551                if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10552                {
10553                        for (i = 0; i < li_total_channels; i++)
10554                        {
10555                                if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10556                                {
10557                                        for (j = 0; j < li_total_channels; j++)
10558                                        {
10559                                                li_config_table[i].coef_table[j] |=
10560                                                        li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10561                                        }
10562                                }
10563                        }
10564                }
10565        }
10566        for (i = 0; i < li_total_channels; i++)
10567        {
10568                if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10569                {
10570                        li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10571                        for (j = 0; j < li_total_channels; j++)
10572                        {
10573                                if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10574                                        li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10575                        }
10576                        if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10577                                li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10578                }
10579        }
10580        for (i = 0; i < li_total_channels; i++)
10581        {
10582                if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10583                {
10584                        for (j = 0; j < li_total_channels; j++)
10585                        {
10586                                if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10587                                        li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10588                                if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10589                                        li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10590                                if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10591                                        li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10592                                if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10593                                        li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10594                        }
10595                        if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10596                        {
10597                                for (j = 0; j < li_total_channels; j++)
10598                                {
10599                                        if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10600                                        {
10601                                                li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10602                                                if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10603                                                        li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10604                                        }
10605                                }
10606                        }
10607                        if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10608                        {
10609                                for (j = 0; j < li_total_channels; j++)
10610                                {
10611                                        if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10612                                                li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10613                                }
10614                        }
10615                        if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10616                        {
10617                                for (j = 0; j < li_total_channels; j++)
10618                                {
10619                                        if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10620                                        {
10621                                                for (n = 0; n < li_total_channels; n++)
10622                                                {
10623                                                        if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10624                                                        {
10625                                                                li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10626                                                                if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10627                                                                {
10628                                                                        li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10629                                                                        if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10630                                                                                li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10631                                                                }
10632                                                                else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10633                                                                        li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10634                                                        }
10635                                                }
10636                                        }
10637                                }
10638                        }
10639                }
10640        }
10641        for (i = 0; i < li_total_channels; i++)
10642        {
10643                if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10644                {
10645                        if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10646                                li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10647                        if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10648                                li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10649                        if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10650                                li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10651                        for (j = 0; j < li_total_channels; j++)
10652                        {
10653                                if ((li_config_table[i].flag_table[j] &
10654                                     (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10655                                    || (li_config_table[j].flag_table[i] &
10656                                        (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10657                                {
10658                                        li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10659                                }
10660                                if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10661                                        li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10662                                if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10663                                        li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10664                        }
10665                        if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10666                        {
10667                                li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10668                                li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10669                        }
10670                }
10671        }
10672        for (i = 0; i < li_total_channels; i++)
10673        {
10674                if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10675                {
10676                        j = 0;
10677                        while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10678                                j++;
10679                        if (j < li_total_channels)
10680                        {
10681                                for (j = 0; j < li_total_channels; j++)
10682                                {
10683                                        li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10684                                        if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10685                                                li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10686                                }
10687                        }
10688                }
10689        }
10690        n = li_total_channels;
10691        if (n > MIXER_MAX_DUMP_CHANNELS)
10692                n = MIXER_MAX_DUMP_CHANNELS;
10693        p = hex_line;
10694        for (j = 0; j < n; j++)
10695        {
10696                if ((j & 0x7) == 0)
10697                        *(p++) = ' ';
10698                *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10699                *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10700        }
10701        *p = '\0';
10702        dbug(1, dprintf("[%06lx] CURRENT %s",
10703                        (dword)(UnMapController(a->Id)), (char *)hex_line));
10704        p = hex_line;
10705        for (j = 0; j < n; j++)
10706        {
10707                if ((j & 0x7) == 0)
10708                        *(p++) = ' ';
10709                *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10710                *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10711        }
10712        *p = '\0';
10713        dbug(1, dprintf("[%06lx] CHANNEL %s",
10714                        (dword)(UnMapController(a->Id)), (char *)hex_line));
10715        p = hex_line;
10716        for (j = 0; j < n; j++)
10717        {
10718                if ((j & 0x7) == 0)
10719                        *(p++) = ' ';
10720                *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10721                *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10722        }
10723        *p = '\0';
10724        dbug(1, dprintf("[%06lx] CHFLAG  %s",
10725                        (dword)(UnMapController(a->Id)), (char *)hex_line));
10726        for (i = 0; i < n; i++)
10727        {
10728                p = hex_line;
10729                for (j = 0; j < n; j++)
10730                {
10731                        if ((j & 0x7) == 0)
10732                                *(p++) = ' ';
10733                        *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10734                        *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10735                }
10736                *p = '\0';
10737                dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10738                                (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10739        }
10740        for (i = 0; i < n; i++)
10741        {
10742                p = hex_line;
10743                for (j = 0; j < n; j++)
10744                {
10745                        if ((j & 0x7) == 0)
10746                                *(p++) = ' ';
10747                        *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10748                        *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10749                }
10750                *p = '\0';
10751                dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10752                                (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10753        }
10754}
10755
10756
10757static struct
10758{
10759        byte mask;
10760        byte line_flags;
10761} mixer_write_prog_pri[] =
10762{
10763        { LI_COEF_CH_CH, 0 },
10764        { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10765        { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10766        { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10767};
10768
10769static struct
10770{
10771        byte from_ch;
10772        byte to_ch;
10773        byte mask;
10774        byte xconnect_override;
10775} mixer_write_prog_bri[] =
10776{
10777        { 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10778        { 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10779        { 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10780        { 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10781        { 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10782        { 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10783        { 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10784        { 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10785        { 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10786        { 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10787        { 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10788        { 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10789        { 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10790        { 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10791        { 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10792        { 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10793        { 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10794        { 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10795        { 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10796        { 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10797        { 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10798        { 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10799        { 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10800        { 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10801        { 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10802        { 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10803        { 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10804        { 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10805        { 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10806        { 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10807        { 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10808        { 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10809        { 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10810        { 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10811        { 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10812        { 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10813};
10814
10815static byte mixer_swapped_index_bri[] =
10816{
10817        18,  /* B      to B      */
10818        19,  /* Alt B  to B      */
10819        20,  /* PC     to B      */
10820        21,  /* Alt PC to B      */
10821        22,  /* IC     to B      */
10822        23,  /* Alt IC to B      */
10823        24,  /* B      to PC     */
10824        25,  /* Alt B  to PC     */
10825        26,  /* PC     to PC     */
10826        27,  /* Alt PC to PC     */
10827        28,  /* IC     to PC     */
10828        29,  /* Alt IC to PC     */
10829        30,  /* B      to IC     */
10830        31,  /* Alt B  to IC     */
10831        32,  /* PC     to IC     */
10832        33,  /* Alt PC to IC     */
10833        34,  /* IC     to IC     */
10834        35,  /* Alt IC to IC     */
10835        0,   /* Alt B  to Alt B  */
10836        1,   /* B      to Alt B  */
10837        2,   /* Alt PC to Alt B  */
10838        3,   /* PC     to Alt B  */
10839        4,   /* Alt IC to Alt B  */
10840        5,   /* IC     to Alt B  */
10841        6,   /* Alt B  to Alt PC */
10842        7,   /* B      to Alt PC */
10843        8,   /* Alt PC to Alt PC */
10844        9,   /* PC     to Alt PC */
10845        10,  /* Alt IC to Alt PC */
10846        11,  /* IC     to Alt PC */
10847        12,  /* Alt B  to Alt IC */
10848        13,  /* B      to Alt IC */
10849        14,  /* Alt PC to Alt IC */
10850        15,  /* PC     to Alt IC */
10851        16,  /* Alt IC to Alt IC */
10852        17   /* IC     to Alt IC */
10853};
10854
10855static struct
10856{
10857        byte mask;
10858        byte from_pc;
10859        byte to_pc;
10860} xconnect_write_prog[] =
10861{
10862        { LI_COEF_CH_CH, false, false },
10863        { LI_COEF_CH_PC, false, true },
10864        { LI_COEF_PC_CH, true, false },
10865        { LI_COEF_PC_PC, true, true }
10866};
10867
10868
10869static void xconnect_query_addresses(PLCI *plci)
10870{
10871        DIVA_CAPI_ADAPTER *a;
10872        word w, ch;
10873        byte *p;
10874
10875        dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10876                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10877                        (char *)(FILE_), __LINE__));
10878
10879        a = plci->adapter;
10880        if (a->li_pri && ((plci->li_bchannel_id == 0)
10881                          || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10882        {
10883                dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10884                                (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10885                                (char *)(FILE_), __LINE__));
10886                return;
10887        }
10888        p = plci->internal_req_buffer;
10889        ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10890        *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10891        w = ch;
10892        *(p++) = (byte) w;
10893        *(p++) = (byte)(w >> 8);
10894        w = ch | XCONNECT_CHANNEL_PORT_PC;
10895        *(p++) = (byte) w;
10896        *(p++) = (byte)(w >> 8);
10897        plci->NData[0].P = plci->internal_req_buffer;
10898        plci->NData[0].PLength = p - plci->internal_req_buffer;
10899        plci->NL.X = plci->NData;
10900        plci->NL.ReqCh = 0;
10901        plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10902        plci->adapter->request(&plci->NL);
10903}
10904
10905
10906static void xconnect_write_coefs(PLCI *plci, word internal_command)
10907{
10908
10909        dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10910                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10911                        (char *)(FILE_), __LINE__, internal_command));
10912
10913        plci->li_write_command = internal_command;
10914        plci->li_write_channel = 0;
10915}
10916
10917
10918static byte xconnect_write_coefs_process(dword Id, PLCI *plci, byte Rc)
10919{
10920        DIVA_CAPI_ADAPTER *a;
10921        word w, n, i, j, r, s, to_ch;
10922        dword d;
10923        byte *p;
10924        struct xconnect_transfer_address_s   *transfer_address;
10925        byte ch_map[MIXER_CHANNELS_BRI];
10926
10927        dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10928                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10929
10930        a = plci->adapter;
10931        if ((plci->li_bchannel_id == 0)
10932            || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10933        {
10934                dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10935                                UnMapId(Id), (char *)(FILE_), __LINE__));
10936                return (true);
10937        }
10938        i = a->li_base + (plci->li_bchannel_id - 1);
10939        j = plci->li_write_channel;
10940        p = plci->internal_req_buffer;
10941        if (j != 0)
10942        {
10943                if ((Rc != OK) && (Rc != OK_FC))
10944                {
10945                        dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10946                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10947                        return (false);
10948                }
10949        }
10950        if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10951        {
10952                r = 0;
10953                s = 0;
10954                if (j < li_total_channels)
10955                {
10956                        if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10957                        {
10958                                s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10959                                     (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10960                                        ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10961                                         (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10962                        }
10963                        r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10964                        while ((j < li_total_channels)
10965                               && ((r == 0)
10966                                   || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10967                                   || (!li_config_table[j].adapter->li_pri
10968                                       && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10969                                   || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10970                                        || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10971                                       && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10972                                           || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10973                                   || ((li_config_table[j].adapter->li_base != a->li_base)
10974                                       && !(r & s &
10975                                            ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10976                                             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10977                                            ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10978                                             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10979                        {
10980                                j++;
10981                                if (j < li_total_channels)
10982                                        r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10983                        }
10984                }
10985                if (j < li_total_channels)
10986                {
10987                        plci->internal_command = plci->li_write_command;
10988                        if (plci_nl_busy(plci))
10989                                return (true);
10990                        to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10991                        *(p++) = UDATA_REQUEST_XCONNECT_TO;
10992                        do
10993                        {
10994                                if (li_config_table[j].adapter->li_base != a->li_base)
10995                                {
10996                                        r &= s &
10997                                                ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10998                                                 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10999                                                ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11000                                                 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
11001                                }
11002                                n = 0;
11003                                do
11004                                {
11005                                        if (r & xconnect_write_prog[n].mask)
11006                                        {
11007                                                if (xconnect_write_prog[n].from_pc)
11008                                                        transfer_address = &(li_config_table[j].send_pc);
11009                                                else
11010                                                        transfer_address = &(li_config_table[j].send_b);
11011                                                d = transfer_address->card_address.low;
11012                                                *(p++) = (byte) d;
11013                                                *(p++) = (byte)(d >> 8);
11014                                                *(p++) = (byte)(d >> 16);
11015                                                *(p++) = (byte)(d >> 24);
11016                                                d = transfer_address->card_address.high;
11017                                                *(p++) = (byte) d;
11018                                                *(p++) = (byte)(d >> 8);
11019                                                *(p++) = (byte)(d >> 16);
11020                                                *(p++) = (byte)(d >> 24);
11021                                                d = transfer_address->offset;
11022                                                *(p++) = (byte) d;
11023                                                *(p++) = (byte)(d >> 8);
11024                                                *(p++) = (byte)(d >> 16);
11025                                                *(p++) = (byte)(d >> 24);
11026                                                w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11027                                                *(p++) = (byte) w;
11028                                                *(p++) = (byte)(w >> 8);
11029                                                w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11030                                                        (li_config_table[i].adapter->u_law ?
11031                                                         (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11032                                                         (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11033                                                *(p++) = (byte) w;
11034                                                *(p++) = (byte) 0;
11035                                                li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11036                                        }
11037                                        n++;
11038                                } while ((n < ARRAY_SIZE(xconnect_write_prog))
11039                                         && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11040                                if (n == ARRAY_SIZE(xconnect_write_prog))
11041                                {
11042                                        do
11043                                        {
11044                                                j++;
11045                                                if (j < li_total_channels)
11046                                                        r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11047                                        } while ((j < li_total_channels)
11048                                                 && ((r == 0)
11049                                                     || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11050                                                     || (!li_config_table[j].adapter->li_pri
11051                                                         && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11052                                                     || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11053                                                          || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11054                                                         && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11055                                                             || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11056                                                     || ((li_config_table[j].adapter->li_base != a->li_base)
11057                                                         && !(r & s &
11058                                                              ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11059                                                               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11060                                                              ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11061                                                               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11062                                }
11063                        } while ((j < li_total_channels)
11064                                 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11065                }
11066                else if (j == li_total_channels)
11067                {
11068                        plci->internal_command = plci->li_write_command;
11069                        if (plci_nl_busy(plci))
11070                                return (true);
11071                        if (a->li_pri)
11072                        {
11073                                *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11074                                w = 0;
11075                                if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11076                                        w |= MIXER_FEATURE_ENABLE_TX_DATA;
11077                                if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11078                                        w |= MIXER_FEATURE_ENABLE_RX_DATA;
11079                                *(p++) = (byte) w;
11080                                *(p++) = (byte)(w >> 8);
11081                        }
11082                        else
11083                        {
11084                                *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11085                                w = 0;
11086                                if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11087                                    && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11088                                {
11089                                        w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11090                                }
11091                                if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11092                                        w |= MIXER_FEATURE_ENABLE_TX_DATA;
11093                                if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11094                                        w |= MIXER_FEATURE_ENABLE_RX_DATA;
11095                                *(p++) = (byte) w;
11096                                *(p++) = (byte)(w >> 8);
11097                                for (j = 0; j < sizeof(ch_map); j += 2)
11098                                {
11099                                        if (plci->li_bchannel_id == 2)
11100                                        {
11101                                                ch_map[j] = (byte)(j + 1);
11102                                                ch_map[j + 1] = (byte) j;
11103                                        }
11104                                        else
11105                                        {
11106                                                ch_map[j] = (byte) j;
11107                                                ch_map[j + 1] = (byte)(j + 1);
11108                                        }
11109                                }
11110                                for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11111                                {
11112                                        i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11113                                        j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11114                                        if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11115                                        {
11116                                                *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11117                                                        mixer_write_prog_bri[n].xconnect_override :
11118                                                        ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11119                                                if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11120                                                {
11121                                                        w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11122                                                        li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11123                                                }
11124                                        }
11125                                        else
11126                                        {
11127                                                *p = 0x00;
11128                                                if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11129                                                {
11130                                                        w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11131                                                        if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11132                                                                *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11133                                                }
11134                                        }
11135                                        p++;
11136                                }
11137                        }
11138                        j = li_total_channels + 1;
11139                }
11140        }
11141        else
11142        {
11143                if (j <= li_total_channels)
11144                {
11145                        plci->internal_command = plci->li_write_command;
11146                        if (plci_nl_busy(plci))
11147                                return (true);
11148                        if (j < a->li_base)
11149                                j = a->li_base;
11150                        if (a->li_pri)
11151                        {
11152                                *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11153                                w = 0;
11154                                if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11155                                        w |= MIXER_FEATURE_ENABLE_TX_DATA;
11156                                if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11157                                        w |= MIXER_FEATURE_ENABLE_RX_DATA;
11158                                *(p++) = (byte) w;
11159                                *(p++) = (byte)(w >> 8);
11160                                for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11161                                {
11162                                        *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11163                                        for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11164                                        {
11165                                                w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11166                                                if (w & mixer_write_prog_pri[n].mask)
11167                                                {
11168                                                        *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11169                                                        li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11170                                                }
11171                                                else
11172                                                        *(p++) = 0x00;
11173                                        }
11174                                        *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11175                                        for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11176                                        {
11177                                                w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11178                                                if (w & mixer_write_prog_pri[n].mask)
11179                                                {
11180                                                        *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11181                                                        li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11182                                                }
11183                                                else
11184                                                        *(p++) = 0x00;
11185                                        }
11186                                }
11187                        }
11188                        else
11189                        {
11190                                *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11191                                w = 0;
11192                                if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11193                                    && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11194                                {
11195                                        w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11196                                }
11197                                if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11198                                        w |= MIXER_FEATURE_ENABLE_TX_DATA;
11199                                if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11200                                        w |= MIXER_FEATURE_ENABLE_RX_DATA;
11201                                *(p++) = (byte) w;
11202                                *(p++) = (byte)(w >> 8);
11203                                for (j = 0; j < sizeof(ch_map); j += 2)
11204                                {
11205                                        if (plci->li_bchannel_id == 2)
11206                                        {
11207                                                ch_map[j] = (byte)(j + 1);
11208                                                ch_map[j + 1] = (byte) j;
11209                                        }
11210                                        else
11211                                        {
11212                                                ch_map[j] = (byte) j;
11213                                                ch_map[j + 1] = (byte)(j + 1);
11214                                        }
11215                                }
11216                                for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11217                                {
11218                                        i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11219                                        j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11220                                        if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11221                                        {
11222                                                *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11223                                                w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11224                                                li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11225                                        }
11226                                        else
11227                                        {
11228                                                *p = 0x00;
11229                                                if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11230                                                {
11231                                                        w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11232                                                        if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11233                                                                *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11234                                                }
11235                                        }
11236                                        p++;
11237                                }
11238                        }
11239                        j = li_total_channels + 1;
11240                }
11241        }
11242        plci->li_write_channel = j;
11243        if (p != plci->internal_req_buffer)
11244        {
11245                plci->NData[0].P = plci->internal_req_buffer;
11246                plci->NData[0].PLength = p - plci->internal_req_buffer;
11247                plci->NL.X = plci->NData;
11248                plci->NL.ReqCh = 0;
11249                plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11250                plci->adapter->request(&plci->NL);
11251        }
11252        return (true);
11253}
11254
11255
11256static void mixer_notify_update(PLCI *plci, byte others)
11257{
11258        DIVA_CAPI_ADAPTER *a;
11259        word i, w;
11260        PLCI *notify_plci;
11261        byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11262
11263        dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11264                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11265                        (char *)(FILE_), __LINE__, others));
11266
11267        a = plci->adapter;
11268        if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11269        {
11270                if (others)
11271                        plci->li_notify_update = true;
11272                i = 0;
11273                do
11274                {
11275                        notify_plci = NULL;
11276                        if (others)
11277                        {
11278                                while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11279                                        i++;
11280                                if (i < li_total_channels)
11281                                        notify_plci = li_config_table[i++].plci;
11282                        }
11283                        else
11284                        {
11285                                if ((plci->li_bchannel_id != 0)
11286                                    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11287                                {
11288                                        notify_plci = plci;
11289                                }
11290                        }
11291                        if ((notify_plci != NULL)
11292                            && !notify_plci->li_notify_update
11293                            && (notify_plci->appl != NULL)
11294                            && (notify_plci->State)
11295                            && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11296                        {
11297                                notify_plci->li_notify_update = true;
11298                                ((CAPI_MSG *) msg)->header.length = 18;
11299                                ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11300                                ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11301                                ((CAPI_MSG *) msg)->header.number = 0;
11302                                ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11303                                ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11304                                ((CAPI_MSG *) msg)->header.ncci = 0;
11305                                ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11306                                ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11307                                PUT_WORD(&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11308                                ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11309                                w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11310                                if (w != _QUEUE_FULL)
11311                                {
11312                                        if (w != 0)
11313                                        {
11314                                                dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11315                                                                (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11316                                                                (char *)(FILE_), __LINE__,
11317                                                                (dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11318                                        }
11319                                        notify_plci->li_notify_update = false;
11320                                }
11321                        }
11322                } while (others && (notify_plci != NULL));
11323                if (others)
11324                        plci->li_notify_update = false;
11325        }
11326}
11327
11328
11329static void mixer_clear_config(PLCI *plci)
11330{
11331        DIVA_CAPI_ADAPTER *a;
11332        word i, j;
11333
11334        dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11335                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11336                        (char *)(FILE_), __LINE__));
11337
11338        plci->li_notify_update = false;
11339        plci->li_plci_b_write_pos = 0;
11340        plci->li_plci_b_read_pos = 0;
11341        plci->li_plci_b_req_pos = 0;
11342        a = plci->adapter;
11343        if ((plci->li_bchannel_id != 0)
11344            && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11345        {
11346                i = a->li_base + (plci->li_bchannel_id - 1);
11347                li_config_table[i].curchnl = 0;
11348                li_config_table[i].channel = 0;
11349                li_config_table[i].chflags = 0;
11350                for (j = 0; j < li_total_channels; j++)
11351                {
11352                        li_config_table[j].flag_table[i] = 0;
11353                        li_config_table[i].flag_table[j] = 0;
11354                        li_config_table[i].coef_table[j] = 0;
11355                        li_config_table[j].coef_table[i] = 0;
11356                }
11357                if (!a->li_pri)
11358                {
11359                        li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11360                        if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11361                        {
11362                                i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11363                                li_config_table[i].curchnl = 0;
11364                                li_config_table[i].channel = 0;
11365                                li_config_table[i].chflags = 0;
11366                                for (j = 0; j < li_total_channels; j++)
11367                                {
11368                                        li_config_table[i].flag_table[j] = 0;
11369                                        li_config_table[j].flag_table[i] = 0;
11370                                        li_config_table[i].coef_table[j] = 0;
11371                                        li_config_table[j].coef_table[i] = 0;
11372                                }
11373                                if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11374                                {
11375                                        i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11376                                        li_config_table[i].curchnl = 0;
11377                                        li_config_table[i].channel = 0;
11378                                        li_config_table[i].chflags = 0;
11379                                        for (j = 0; j < li_total_channels; j++)
11380                                        {
11381                                                li_config_table[i].flag_table[j] = 0;
11382                                                li_config_table[j].flag_table[i] = 0;
11383                                                li_config_table[i].coef_table[j] = 0;
11384                                                li_config_table[j].coef_table[i] = 0;
11385                                        }
11386                                }
11387                        }
11388                }
11389        }
11390}
11391
11392
11393static void mixer_prepare_switch(dword Id, PLCI *plci)
11394{
11395
11396        dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11397                        UnMapId(Id), (char *)(FILE_), __LINE__));
11398
11399        do
11400        {
11401                mixer_indication_coefs_set(Id, plci);
11402        } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11403}
11404
11405
11406static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11407{
11408        DIVA_CAPI_ADAPTER *a;
11409        word i, j;
11410
11411        dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11412                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11413
11414        a = plci->adapter;
11415        if ((plci->li_bchannel_id != 0)
11416            && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11417        {
11418                i = a->li_base + (plci->li_bchannel_id - 1);
11419                for (j = 0; j < li_total_channels; j++)
11420                {
11421                        li_config_table[i].coef_table[j] &= 0xf;
11422                        li_config_table[j].coef_table[i] &= 0xf;
11423                }
11424                if (!a->li_pri)
11425                        li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11426        }
11427        return (GOOD);
11428}
11429
11430
11431static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11432{
11433        DIVA_CAPI_ADAPTER *a;
11434        word Info;
11435
11436        dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11437                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11438
11439        Info = GOOD;
11440        a = plci->adapter;
11441        if ((plci->B1_facilities & B1_FACILITY_MIXER)
11442            && (plci->li_bchannel_id != 0)
11443            && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11444        {
11445                switch (plci->adjust_b_state)
11446                {
11447                case ADJUST_B_RESTORE_MIXER_1:
11448                        if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11449                        {
11450                                plci->internal_command = plci->adjust_b_command;
11451                                if (plci_nl_busy(plci))
11452                                {
11453                                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11454                                        break;
11455                                }
11456                                xconnect_query_addresses(plci);
11457                                plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11458                                break;
11459                        }
11460                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11461                        Rc = OK;
11462                case ADJUST_B_RESTORE_MIXER_2:
11463                case ADJUST_B_RESTORE_MIXER_3:
11464                case ADJUST_B_RESTORE_MIXER_4:
11465                        if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11466                        {
11467                                dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11468                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11469                                Info = _WRONG_STATE;
11470                                break;
11471                        }
11472                        if (Rc == OK)
11473                        {
11474                                if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11475                                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11476                                else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11477                                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11478                        }
11479                        else if (Rc == 0)
11480                        {
11481                                if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11482                                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11483                                else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11484                                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11485                        }
11486                        if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11487                        {
11488                                plci->internal_command = plci->adjust_b_command;
11489                                break;
11490                        }
11491                case ADJUST_B_RESTORE_MIXER_5:
11492                        xconnect_write_coefs(plci, plci->adjust_b_command);
11493                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11494                        Rc = OK;
11495                case ADJUST_B_RESTORE_MIXER_6:
11496                        if (!xconnect_write_coefs_process(Id, plci, Rc))
11497                        {
11498                                dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11499                                                UnMapId(Id), (char *)(FILE_), __LINE__));
11500                                Info = _FACILITY_NOT_SUPPORTED;
11501                                break;
11502                        }
11503                        if (plci->internal_command)
11504                                break;
11505                        plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11506                case ADJUST_B_RESTORE_MIXER_7:
11507                        break;
11508                }
11509        }
11510        return (Info);
11511}
11512
11513
11514static void mixer_command(dword Id, PLCI *plci, byte Rc)
11515{
11516        DIVA_CAPI_ADAPTER *a;
11517        word i, internal_command;
11518
11519        dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11520                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11521                        plci->li_cmd));
11522
11523        a = plci->adapter;
11524        internal_command = plci->internal_command;
11525        plci->internal_command = 0;
11526        switch (plci->li_cmd)
11527        {
11528        case LI_REQ_CONNECT:
11529        case LI_REQ_DISCONNECT:
11530        case LI_REQ_SILENT_UPDATE:
11531                switch (internal_command)
11532                {
11533                default:
11534                        if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11535                        {
11536                                adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11537                                                                          B1_FACILITY_MIXER), MIXER_COMMAND_1);
11538                        }
11539                case MIXER_COMMAND_1:
11540                        if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11541                        {
11542                                if (adjust_b_process(Id, plci, Rc) != GOOD)
11543                                {
11544                                        dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11545                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
11546                                        break;
11547                                }
11548                                if (plci->internal_command)
11549                                        return;
11550                        }
11551                        plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11552                        if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11553                            || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11554                                && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11555                                                                                      ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11556                        {
11557                                xconnect_write_coefs(plci, MIXER_COMMAND_2);
11558                        }
11559                        else
11560                        {
11561                                do
11562                                {
11563                                        mixer_indication_coefs_set(Id, plci);
11564                                } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11565                        }
11566                case MIXER_COMMAND_2:
11567                        if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11568                            || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11569                                && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11570                                                                                      ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11571                        {
11572                                if (!xconnect_write_coefs_process(Id, plci, Rc))
11573                                {
11574                                        dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11575                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
11576                                        if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11577                                        {
11578                                                do
11579                                                {
11580                                                        plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11581                                                                LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11582                                                        i = (plci->li_plci_b_write_pos == 0) ?
11583                                                                LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11584                                                } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11585                                                         && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11586                                        }
11587                                        break;
11588                                }
11589                                if (plci->internal_command)
11590                                        return;
11591                        }
11592                        if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11593                        {
11594                                adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11595                                                                          ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11596                        }
11597                case MIXER_COMMAND_3:
11598                        if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11599                        {
11600                                if (adjust_b_process(Id, plci, Rc) != GOOD)
11601                                {
11602                                        dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11603                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
11604                                        break;
11605                                }
11606                                if (plci->internal_command)
11607                                        return;
11608                        }
11609                        break;
11610                }
11611                break;
11612        }
11613        if ((plci->li_bchannel_id == 0)
11614            || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11615        {
11616                dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11617                                UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11618        }
11619        else
11620        {
11621                i = a->li_base + (plci->li_bchannel_id - 1);
11622                li_config_table[i].curchnl = plci->li_channel_bits;
11623                if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11624                {
11625                        i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11626                        li_config_table[i].curchnl = plci->li_channel_bits;
11627                        if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11628                        {
11629                                i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11630                                li_config_table[i].curchnl = plci->li_channel_bits;
11631                        }
11632                }
11633        }
11634}
11635
11636
11637static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11638                              dword plci_b_id, byte connect, dword li_flags)
11639{
11640        word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11641        PLCI *plci_b;
11642        DIVA_CAPI_ADAPTER *a_b;
11643
11644        a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11645        plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11646        ch_a = a->li_base + (plci->li_bchannel_id - 1);
11647        if (!a->li_pri && (plci->tel == ADV_VOICE)
11648            && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11649        {
11650                ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11651                ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11652                        a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11653        }
11654        else
11655        {
11656                ch_a_v = ch_a;
11657                ch_a_s = ch_a;
11658        }
11659        ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11660        if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11661            && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11662        {
11663                ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11664                ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11665                        a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11666        }
11667        else
11668        {
11669                ch_b_v = ch_b;
11670                ch_b_s = ch_b;
11671        }
11672        if (connect)
11673        {
11674                li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11675                li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11676                li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11677                li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11678        }
11679        li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11680        li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11681        li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11682        li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11683        if (ch_a_v == ch_b_v)
11684        {
11685                li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11686                li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11687        }
11688        else
11689        {
11690                if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11691                {
11692                        for (i = 0; i < li_total_channels; i++)
11693                        {
11694                                if (i != ch_a_v)
11695                                        li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11696                        }
11697                }
11698                if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11699                {
11700                        for (i = 0; i < li_total_channels; i++)
11701                        {
11702                                if (i != ch_a_s)
11703                                        li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11704                        }
11705                }
11706                if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11707                {
11708                        for (i = 0; i < li_total_channels; i++)
11709                        {
11710                                if (i != ch_a_v)
11711                                        li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11712                        }
11713                }
11714                if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11715                {
11716                        for (i = 0; i < li_total_channels; i++)
11717                        {
11718                                if (i != ch_a_s)
11719                                        li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11720                        }
11721                }
11722        }
11723        if (li_flags & LI_FLAG_CONFERENCE_A_B)
11724        {
11725                li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11726                li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11727                li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11728                li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11729        }
11730        if (li_flags & LI_FLAG_CONFERENCE_B_A)
11731        {
11732                li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11733                li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11734                li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11735                li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11736        }
11737        if (li_flags & LI_FLAG_MONITOR_A)
11738        {
11739                li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11740                li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11741        }
11742        if (li_flags & LI_FLAG_MONITOR_B)
11743        {
11744                li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11745                li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11746        }
11747        if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11748        {
11749                li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11750                li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11751        }
11752        if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11753        {
11754                li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11755                li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11756        }
11757        if (li_flags & LI_FLAG_MIX_A)
11758        {
11759                li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11760                li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11761        }
11762        if (li_flags & LI_FLAG_MIX_B)
11763        {
11764                li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11765                li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11766        }
11767        if (ch_a_v != ch_a_s)
11768        {
11769                li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11770                li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11771        }
11772        if (ch_b_v != ch_b_s)
11773        {
11774                li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11775                li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11776        }
11777}
11778
11779
11780static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11781                               dword plci_b_id, byte connect, dword li_flags)
11782{
11783        word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11784        PLCI *plci_b;
11785        DIVA_CAPI_ADAPTER *a_b;
11786
11787        a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11788        plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11789        ch_a = a->li_base + (plci->li_bchannel_id - 1);
11790        if (!a->li_pri && (plci->tel == ADV_VOICE)
11791            && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11792        {
11793                ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11794                ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11795                        a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11796        }
11797        else
11798        {
11799                ch_a_v = ch_a;
11800                ch_a_s = ch_a;
11801        }
11802        ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11803        if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11804            && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11805        {
11806                ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11807                ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11808                        a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11809        }
11810        else
11811        {
11812                ch_b_v = ch_b;
11813                ch_b_s = ch_b;
11814        }
11815        if (connect)
11816        {
11817                li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11818                li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11819                li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11820                li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11821                li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11822                li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11823        }
11824        li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11825        li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11826        li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11827        li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11828        li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11829        li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11830        li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11831        li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11832        if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11833        {
11834                li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11835                li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11836                li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11837                li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11838        }
11839        if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11840        {
11841                li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11842                li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11843                li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11844                li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11845        }
11846        if (li_flags & LI2_FLAG_MONITOR_B)
11847        {
11848                li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11849                li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11850        }
11851        if (li_flags & LI2_FLAG_MIX_B)
11852        {
11853                li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11854                li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11855        }
11856        if (li_flags & LI2_FLAG_MONITOR_X)
11857                li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11858        if (li_flags & LI2_FLAG_MIX_X)
11859                li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11860        if (li_flags & LI2_FLAG_LOOP_B)
11861        {
11862                li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11863                li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11864                li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11865                li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11866        }
11867        if (li_flags & LI2_FLAG_LOOP_PC)
11868                li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11869        if (li_flags & LI2_FLAG_LOOP_X)
11870                li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11871        if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11872                li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11873        if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11874                li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11875        if (ch_a_v != ch_a_s)
11876        {
11877                li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11878                li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11879        }
11880        if (ch_b_v != ch_b_s)
11881        {
11882                li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11883                li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11884        }
11885}
11886
11887
11888static word li_check_main_plci(dword Id, PLCI *plci)
11889{
11890        if (plci == NULL)
11891        {
11892                dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11893                                UnMapId(Id), (char *)(FILE_), __LINE__));
11894                return (_WRONG_IDENTIFIER);
11895        }
11896        if (!plci->State
11897            || !plci->NL.Id || plci->nl_remove_id
11898            || (plci->li_bchannel_id == 0))
11899        {
11900                dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11901                                UnMapId(Id), (char *)(FILE_), __LINE__));
11902                return (_WRONG_STATE);
11903        }
11904        li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11905        return (GOOD);
11906}
11907
11908
11909static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11910                             dword plci_b_id, word plci_b_write_pos, byte *p_result)
11911{
11912        byte ctlr_b;
11913        PLCI *plci_b;
11914
11915        if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11916             LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11917        {
11918                dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11919                                UnMapId(Id), (char *)(FILE_), __LINE__));
11920                PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11921                return (NULL);
11922        }
11923        ctlr_b = 0;
11924        if ((plci_b_id & 0x7f) != 0)
11925        {
11926                ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11927                if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11928                        ctlr_b = 0;
11929        }
11930        if ((ctlr_b == 0)
11931            || (((plci_b_id >> 8) & 0xff) == 0)
11932            || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11933        {
11934                dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11935                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11936                PUT_WORD(p_result, _WRONG_IDENTIFIER);
11937                return (NULL);
11938        }
11939        plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11940        if (!plci_b->State
11941            || !plci_b->NL.Id || plci_b->nl_remove_id
11942            || (plci_b->li_bchannel_id == 0))
11943        {
11944                dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11945                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11946                PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11947                return (NULL);
11948        }
11949        li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11950        if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11951            ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11952            && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11953                || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11954        {
11955                dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11956                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11957                PUT_WORD(p_result, _WRONG_IDENTIFIER);
11958                return (NULL);
11959        }
11960        if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11961                                                          (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11962        {
11963                dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11964                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11965                PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11966                return (NULL);
11967        }
11968        return (plci_b);
11969}
11970
11971
11972static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11973                              dword plci_b_id, word plci_b_write_pos, byte *p_result)
11974{
11975        byte ctlr_b;
11976        PLCI *plci_b;
11977
11978        if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11979             LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11980        {
11981                dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11982                                UnMapId(Id), (char *)(FILE_), __LINE__));
11983                PUT_WORD(p_result, _WRONG_STATE);
11984                return (NULL);
11985        }
11986        ctlr_b = 0;
11987        if ((plci_b_id & 0x7f) != 0)
11988        {
11989                ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11990                if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11991                        ctlr_b = 0;
11992        }
11993        if ((ctlr_b == 0)
11994            || (((plci_b_id >> 8) & 0xff) == 0)
11995            || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11996        {
11997                dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11998                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11999                PUT_WORD(p_result, _WRONG_IDENTIFIER);
12000                return (NULL);
12001        }
12002        plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
12003        if (!plci_b->State
12004            || !plci_b->NL.Id || plci_b->nl_remove_id
12005            || (plci_b->li_bchannel_id == 0)
12006            || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12007        {
12008                dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
12009                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12010                PUT_WORD(p_result, _WRONG_STATE);
12011                return (NULL);
12012        }
12013        if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12014            ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
12015            && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12016                || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12017        {
12018                dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
12019                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12020                PUT_WORD(p_result, _WRONG_IDENTIFIER);
12021                return (NULL);
12022        }
12023        if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
12024                                                          (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12025        {
12026                dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12027                                UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12028                PUT_WORD(p_result, _WRONG_STATE);
12029                return (NULL);
12030        }
12031        return (plci_b);
12032}
12033
12034
12035static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
12036{
12037        word Info;
12038        word i;
12039        dword d, li_flags, plci_b_id;
12040        PLCI *plci_b;
12041        API_PARSE li_parms[3];
12042        API_PARSE li_req_parms[3];
12043        API_PARSE li_participant_struct[2];
12044        API_PARSE li_participant_parms[3];
12045        word participant_parms_pos;
12046        byte result_buffer[32];
12047        byte *result;
12048        word result_pos;
12049        word plci_b_write_pos;
12050
12051        dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
12052                        UnMapId(Id), (char *)(FILE_), __LINE__));
12053
12054        Info = GOOD;
12055        result = result_buffer;
12056        result_buffer[0] = 0;
12057        if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12058        {
12059                dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12060                                UnMapId(Id), (char *)(FILE_), __LINE__));
12061                Info = _FACILITY_NOT_SUPPORTED;
12062        }
12063        else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
12064        {
12065                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12066                                UnMapId(Id), (char *)(FILE_), __LINE__));
12067                Info = _WRONG_MESSAGE_FORMAT;
12068        }
12069        else
12070        {
12071                result_buffer[0] = 3;
12072                PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
12073                result_buffer[3] = 0;
12074                switch (GET_WORD(li_parms[0].info))
12075                {
12076                case LI_GET_SUPPORTED_SERVICES:
12077                        if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12078                        {
12079                                result_buffer[0] = 17;
12080                                result_buffer[3] = 14;
12081                                PUT_WORD(&result_buffer[4], GOOD);
12082                                d = 0;
12083                                if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12084                                        d |= LI_CONFERENCING_SUPPORTED;
12085                                if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12086                                        d |= LI_MONITORING_SUPPORTED;
12087                                if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12088                                        d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12089                                if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12090                                        d |= LI_CROSS_CONTROLLER_SUPPORTED;
12091                                PUT_DWORD(&result_buffer[6], d);
12092                                if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12093                                {
12094                                        d = 0;
12095                                        for (i = 0; i < li_total_channels; i++)
12096                                        {
12097                                                if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12098                                                    && (li_config_table[i].adapter->li_pri
12099                                                        || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12100                                                {
12101                                                        d++;
12102                                                }
12103                                        }
12104                                }
12105                                else
12106                                {
12107                                        d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12108                                }
12109                                PUT_DWORD(&result_buffer[10], d / 2);
12110                                PUT_DWORD(&result_buffer[14], d);
12111                        }
12112                        else
12113                        {
12114                                result_buffer[0] = 25;
12115                                result_buffer[3] = 22;
12116                                PUT_WORD(&result_buffer[4], GOOD);
12117                                d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12118                                if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12119                                        d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12120                                if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12121                                        d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12122                                if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12123                                        d |= LI2_PC_LOOPING_SUPPORTED;
12124                                if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12125                                        d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12126                                PUT_DWORD(&result_buffer[6], d);
12127                                d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12128                                PUT_DWORD(&result_buffer[10], d / 2);
12129                                PUT_DWORD(&result_buffer[14], d - 1);
12130                                if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12131                                {
12132                                        d = 0;
12133                                        for (i = 0; i < li_total_channels; i++)
12134                                        {
12135                                                if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12136                                                    && (li_config_table[i].adapter->li_pri
12137                                                        || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12138                                                {
12139                                                        d++;
12140                                                }
12141                                        }
12142                                }
12143                                PUT_DWORD(&result_buffer[18], d / 2);
12144                                PUT_DWORD(&result_buffer[22], d - 1);
12145                        }
12146                        break;
12147
12148                case LI_REQ_CONNECT:
12149                        if (li_parms[1].length == 8)
12150                        {
12151                                appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12152                                if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12153                                {
12154                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12155                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12156                                        Info = _WRONG_MESSAGE_FORMAT;
12157                                        break;
12158                                }
12159                                plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12160                                li_flags = GET_DWORD(li_req_parms[1].info);
12161                                Info = li_check_main_plci(Id, plci);
12162                                result_buffer[0] = 9;
12163                                result_buffer[3] = 6;
12164                                PUT_DWORD(&result_buffer[4], plci_b_id);
12165                                PUT_WORD(&result_buffer[8], GOOD);
12166                                if (Info != GOOD)
12167                                        break;
12168                                result = plci->saved_msg.info;
12169                                for (i = 0; i <= result_buffer[0]; i++)
12170                                        result[i] = result_buffer[i];
12171                                plci_b_write_pos = plci->li_plci_b_write_pos;
12172                                plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12173                                if (plci_b == NULL)
12174                                        break;
12175                                li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12176                                plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12177                                plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12178                                plci->li_plci_b_write_pos = plci_b_write_pos;
12179                        }
12180                        else
12181                        {
12182                                appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12183                                if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12184                                {
12185                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12186                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12187                                        Info = _WRONG_MESSAGE_FORMAT;
12188                                        break;
12189                                }
12190                                li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12191                                Info = li_check_main_plci(Id, plci);
12192                                result_buffer[0] = 7;
12193                                result_buffer[3] = 4;
12194                                PUT_WORD(&result_buffer[4], Info);
12195                                result_buffer[6] = 0;
12196                                if (Info != GOOD)
12197                                        break;
12198                                result = plci->saved_msg.info;
12199                                for (i = 0; i <= result_buffer[0]; i++)
12200                                        result[i] = result_buffer[i];
12201                                plci_b_write_pos = plci->li_plci_b_write_pos;
12202                                participant_parms_pos = 0;
12203                                result_pos = 7;
12204                                li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12205                                while (participant_parms_pos < li_req_parms[1].length)
12206                                {
12207                                        result[result_pos] = 6;
12208                                        result_pos += 7;
12209                                        PUT_DWORD(&result[result_pos - 6], 0);
12210                                        PUT_WORD(&result[result_pos - 2], GOOD);
12211                                        if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12212                                                      (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12213                                        {
12214                                                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12215                                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12216                                                PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12217                                                break;
12218                                        }
12219                                        if (api_parse(&li_participant_struct[0].info[1],
12220                                                      li_participant_struct[0].length, "dd", li_participant_parms))
12221                                        {
12222                                                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12223                                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12224                                                PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12225                                                break;
12226                                        }
12227                                        plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12228                                        li_flags = GET_DWORD(li_participant_parms[1].info);
12229                                        PUT_DWORD(&result[result_pos - 6], plci_b_id);
12230                                        if (sizeof(result) - result_pos < 7)
12231                                        {
12232                                                dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12233                                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12234                                                PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12235                                                break;
12236                                        }
12237                                        plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12238                                        if (plci_b != NULL)
12239                                        {
12240                                                li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12241                                                plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12242                                                        ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12243                                                                      LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12244                                                plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12245                                        }
12246                                        participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12247                                                                       (&li_req_parms[1].info[1]));
12248                                }
12249                                result[0] = (byte)(result_pos - 1);
12250                                result[3] = (byte)(result_pos - 4);
12251                                result[6] = (byte)(result_pos - 7);
12252                                i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12253                                if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12254                                    || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12255                                {
12256                                        plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12257                                        plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12258                                }
12259                                else
12260                                        plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12261                                plci->li_plci_b_write_pos = plci_b_write_pos;
12262                        }
12263                        mixer_calculate_coefs(a);
12264                        plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12265                        mixer_notify_update(plci, true);
12266                        sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12267                              "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12268                        plci->command = 0;
12269                        plci->li_cmd = GET_WORD(li_parms[0].info);
12270                        start_internal_command(Id, plci, mixer_command);
12271                        return (false);
12272
12273                case LI_REQ_DISCONNECT:
12274                        if (li_parms[1].length == 4)
12275                        {
12276                                appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12277                                if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12278                                {
12279                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12280                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12281                                        Info = _WRONG_MESSAGE_FORMAT;
12282                                        break;
12283                                }
12284                                plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12285                                Info = li_check_main_plci(Id, plci);
12286                                result_buffer[0] = 9;
12287                                result_buffer[3] = 6;
12288                                PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12289                                PUT_WORD(&result_buffer[8], GOOD);
12290                                if (Info != GOOD)
12291                                        break;
12292                                result = plci->saved_msg.info;
12293                                for (i = 0; i <= result_buffer[0]; i++)
12294                                        result[i] = result_buffer[i];
12295                                plci_b_write_pos = plci->li_plci_b_write_pos;
12296                                plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12297                                if (plci_b == NULL)
12298                                        break;
12299                                li_update_connect(Id, a, plci, plci_b_id, false, 0);
12300                                plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12301                                plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12302                                plci->li_plci_b_write_pos = plci_b_write_pos;
12303                        }
12304                        else
12305                        {
12306                                appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12307                                if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12308                                {
12309                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12310                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12311                                        Info = _WRONG_MESSAGE_FORMAT;
12312                                        break;
12313                                }
12314                                Info = li_check_main_plci(Id, plci);
12315                                result_buffer[0] = 7;
12316                                result_buffer[3] = 4;
12317                                PUT_WORD(&result_buffer[4], Info);
12318                                result_buffer[6] = 0;
12319                                if (Info != GOOD)
12320                                        break;
12321                                result = plci->saved_msg.info;
12322                                for (i = 0; i <= result_buffer[0]; i++)
12323                                        result[i] = result_buffer[i];
12324                                plci_b_write_pos = plci->li_plci_b_write_pos;
12325                                participant_parms_pos = 0;
12326                                result_pos = 7;
12327                                while (participant_parms_pos < li_req_parms[0].length)
12328                                {
12329                                        result[result_pos] = 6;
12330                                        result_pos += 7;
12331                                        PUT_DWORD(&result[result_pos - 6], 0);
12332                                        PUT_WORD(&result[result_pos - 2], GOOD);
12333                                        if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12334                                                      (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12335                                        {
12336                                                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12337                                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12338                                                PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12339                                                break;
12340                                        }
12341                                        if (api_parse(&li_participant_struct[0].info[1],
12342                                                      li_participant_struct[0].length, "d", li_participant_parms))
12343                                        {
12344                                                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12345                                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12346                                                PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12347                                                break;
12348                                        }
12349                                        plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12350                                        PUT_DWORD(&result[result_pos - 6], plci_b_id);
12351                                        if (sizeof(result) - result_pos < 7)
12352                                        {
12353                                                dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12354                                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12355                                                PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12356                                                break;
12357                                        }
12358                                        plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12359                                        if (plci_b != NULL)
12360                                        {
12361                                                li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12362                                                plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12363                                                plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12364                                        }
12365                                        participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12366                                                                       (&li_req_parms[0].info[1]));
12367                                }
12368                                result[0] = (byte)(result_pos - 1);
12369                                result[3] = (byte)(result_pos - 4);
12370                                result[6] = (byte)(result_pos - 7);
12371                                i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12372                                if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12373                                    || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12374                                {
12375                                        plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12376                                        plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12377                                }
12378                                else
12379                                        plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12380                                plci->li_plci_b_write_pos = plci_b_write_pos;
12381                        }
12382                        mixer_calculate_coefs(a);
12383                        plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12384                        mixer_notify_update(plci, true);
12385                        sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12386                              "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12387                        plci->command = 0;
12388                        plci->li_cmd = GET_WORD(li_parms[0].info);
12389                        start_internal_command(Id, plci, mixer_command);
12390                        return (false);
12391
12392                case LI_REQ_SILENT_UPDATE:
12393                        if (!plci || !plci->State
12394                            || !plci->NL.Id || plci->nl_remove_id
12395                            || (plci->li_bchannel_id == 0)
12396                            || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12397                        {
12398                                dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12399                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12400                                return (false);
12401                        }
12402                        plci_b_write_pos = plci->li_plci_b_write_pos;
12403                        if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12404                             LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12405                        {
12406                                dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12407                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12408                                return (false);
12409                        }
12410                        i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12411                        if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12412                            || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12413                        {
12414                                plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12415                                plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12416                        }
12417                        else
12418                                plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12419                        plci->li_plci_b_write_pos = plci_b_write_pos;
12420                        plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12421                        plci->command = 0;
12422                        plci->li_cmd = GET_WORD(li_parms[0].info);
12423                        start_internal_command(Id, plci, mixer_command);
12424                        return (false);
12425
12426                default:
12427                        dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12428                                        UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12429                        Info = _FACILITY_NOT_SUPPORTED;
12430                }
12431        }
12432        sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12433              "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12434        return (false);
12435}
12436
12437
12438static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12439{
12440        dword d;
12441        byte result[12];
12442
12443        dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12444                        UnMapId(Id), (char *)(FILE_), __LINE__));
12445
12446        if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12447        {
12448                do
12449                {
12450                        d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12451                        if (!(d & LI_PLCI_B_SKIP_FLAG))
12452                        {
12453                                if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12454                                {
12455                                        if (d & LI_PLCI_B_DISC_FLAG)
12456                                        {
12457                                                result[0] = 5;
12458                                                PUT_WORD(&result[1], LI_IND_DISCONNECT);
12459                                                result[3] = 2;
12460                                                PUT_WORD(&result[4], _LI_USER_INITIATED);
12461                                        }
12462                                        else
12463                                        {
12464                                                result[0] = 7;
12465                                                PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12466                                                result[3] = 4;
12467                                                PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12468                                        }
12469                                }
12470                                else
12471                                {
12472                                        if (d & LI_PLCI_B_DISC_FLAG)
12473                                        {
12474                                                result[0] = 9;
12475                                                PUT_WORD(&result[1], LI_IND_DISCONNECT);
12476                                                result[3] = 6;
12477                                                PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12478                                                PUT_WORD(&result[8], _LI_USER_INITIATED);
12479                                        }
12480                                        else
12481                                        {
12482                                                result[0] = 7;
12483                                                PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12484                                                result[3] = 4;
12485                                                PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12486                                        }
12487                                }
12488                                sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12489                                      "ws", SELECTOR_LINE_INTERCONNECT, result);
12490                        }
12491                        plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12492                                0 : plci->li_plci_b_read_pos + 1;
12493                } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12494        }
12495}
12496
12497
12498static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12499{
12500        word i, j, ch;
12501        struct xconnect_transfer_address_s s,   *p;
12502        DIVA_CAPI_ADAPTER *a;
12503
12504        dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12505                        UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12506
12507        a = plci->adapter;
12508        i = 1;
12509        for (i = 1; i < length; i += 16)
12510        {
12511                s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12512                s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12513                s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12514                ch = msg[i + 12] | (msg[i + 13] << 8);
12515                j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12516                if (!a->li_pri && (plci->li_bchannel_id == 2))
12517                        j = 1 - j;
12518                j += a->li_base;
12519                if (ch & XCONNECT_CHANNEL_PORT_PC)
12520                        p = &(li_config_table[j].send_pc);
12521                else
12522                        p = &(li_config_table[j].send_b);
12523                p->card_address.low = s.card_address.low;
12524                p->card_address.high = s.card_address.high;
12525                p->offset = s.offset;
12526                li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12527        }
12528        if (plci->internal_command_queue[0]
12529            && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12530                || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12531                || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12532        {
12533                (*(plci->internal_command_queue[0]))(Id, plci, 0);
12534                if (!plci->internal_command)
12535                        next_internal_command(Id, plci);
12536        }
12537        mixer_notify_update(plci, true);
12538}
12539
12540
12541static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12542{
12543
12544        dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12545                        UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12546
12547}
12548
12549
12550static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12551{
12552        word plci_b_write_pos;
12553
12554        plci_b_write_pos = plci->li_plci_b_write_pos;
12555        if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12556             LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12557        {
12558                dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12559                                (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12560                                (char *)(FILE_), __LINE__));
12561                return (false);
12562        }
12563        plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12564        plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12565        plci->li_plci_b_write_pos = plci_b_write_pos;
12566        return (true);
12567}
12568
12569
12570static void mixer_remove(PLCI *plci)
12571{
12572        DIVA_CAPI_ADAPTER *a;
12573        PLCI *notify_plci;
12574        dword plci_b_id;
12575        word i, j;
12576
12577        dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12578                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12579                        (char *)(FILE_), __LINE__));
12580
12581        a = plci->adapter;
12582        plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12583        if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12584        {
12585                if ((plci->li_bchannel_id != 0)
12586                    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12587                {
12588                        i = a->li_base + (plci->li_bchannel_id - 1);
12589                        if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12590                        {
12591                                for (j = 0; j < li_total_channels; j++)
12592                                {
12593                                        if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12594                                            || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12595                                        {
12596                                                notify_plci = li_config_table[j].plci;
12597                                                if ((notify_plci != NULL)
12598                                                    && (notify_plci != plci)
12599                                                    && (notify_plci->appl != NULL)
12600                                                    && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12601                                                    && (notify_plci->State)
12602                                                    && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12603                                                {
12604                                                        mixer_notify_source_removed(notify_plci, plci_b_id);
12605                                                }
12606                                        }
12607                                }
12608                                mixer_clear_config(plci);
12609                                mixer_calculate_coefs(a);
12610                                mixer_notify_update(plci, true);
12611                        }
12612                        li_config_table[i].plci = NULL;
12613                        plci->li_bchannel_id = 0;
12614                }
12615        }
12616}
12617
12618
12619/*------------------------------------------------------------------*/
12620/* Echo canceller facilities                                        */
12621/*------------------------------------------------------------------*/
12622
12623
12624static void ec_write_parameters(PLCI *plci)
12625{
12626        word w;
12627        byte parameter_buffer[6];
12628
12629        dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12630                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12631                        (char *)(FILE_), __LINE__));
12632
12633        parameter_buffer[0] = 5;
12634        parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12635        PUT_WORD(&parameter_buffer[2], plci->ec_idi_options);
12636        plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12637        w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12638        PUT_WORD(&parameter_buffer[4], w);
12639        add_p(plci, FTY, parameter_buffer);
12640        sig_req(plci, TEL_CTRL, 0);
12641        send_req(plci);
12642}
12643
12644
12645static void ec_clear_config(PLCI *plci)
12646{
12647
12648        dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12649                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12650                        (char *)(FILE_), __LINE__));
12651
12652        plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12653                LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12654        plci->ec_tail_length = 0;
12655}
12656
12657
12658static void ec_prepare_switch(dword Id, PLCI *plci)
12659{
12660
12661        dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12662                        UnMapId(Id), (char *)(FILE_), __LINE__));
12663
12664}
12665
12666
12667static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12668{
12669
12670        dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12671                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12672
12673        return (GOOD);
12674}
12675
12676
12677static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12678{
12679        word Info;
12680
12681        dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12682                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12683
12684        Info = GOOD;
12685        if (plci->B1_facilities & B1_FACILITY_EC)
12686        {
12687                switch (plci->adjust_b_state)
12688                {
12689                case ADJUST_B_RESTORE_EC_1:
12690                        plci->internal_command = plci->adjust_b_command;
12691                        if (plci->sig_req)
12692                        {
12693                                plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12694                                break;
12695                        }
12696                        ec_write_parameters(plci);
12697                        plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12698                        break;
12699                case ADJUST_B_RESTORE_EC_2:
12700                        if ((Rc != OK) && (Rc != OK_FC))
12701                        {
12702                                dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12703                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12704                                Info = _WRONG_STATE;
12705                                break;
12706                        }
12707                        break;
12708                }
12709        }
12710        return (Info);
12711}
12712
12713
12714static void ec_command(dword Id, PLCI *plci, byte Rc)
12715{
12716        word internal_command, Info;
12717        byte result[8];
12718
12719        dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12720                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12721                        plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12722
12723        Info = GOOD;
12724        if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12725        {
12726                result[0] = 2;
12727                PUT_WORD(&result[1], EC_SUCCESS);
12728        }
12729        else
12730        {
12731                result[0] = 5;
12732                PUT_WORD(&result[1], plci->ec_cmd);
12733                result[3] = 2;
12734                PUT_WORD(&result[4], GOOD);
12735        }
12736        internal_command = plci->internal_command;
12737        plci->internal_command = 0;
12738        switch (plci->ec_cmd)
12739        {
12740        case EC_ENABLE_OPERATION:
12741        case EC_FREEZE_COEFFICIENTS:
12742        case EC_RESUME_COEFFICIENT_UPDATE:
12743        case EC_RESET_COEFFICIENTS:
12744                switch (internal_command)
12745                {
12746                default:
12747                        adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12748                                                                  B1_FACILITY_EC), EC_COMMAND_1);
12749                case EC_COMMAND_1:
12750                        if (adjust_b_process(Id, plci, Rc) != GOOD)
12751                        {
12752                                dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12753                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12754                                Info = _FACILITY_NOT_SUPPORTED;
12755                                break;
12756                        }
12757                        if (plci->internal_command)
12758                                return;
12759                case EC_COMMAND_2:
12760                        if (plci->sig_req)
12761                        {
12762                                plci->internal_command = EC_COMMAND_2;
12763                                return;
12764                        }
12765                        plci->internal_command = EC_COMMAND_3;
12766                        ec_write_parameters(plci);
12767                        return;
12768                case EC_COMMAND_3:
12769                        if ((Rc != OK) && (Rc != OK_FC))
12770                        {
12771                                dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12772                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12773                                Info = _FACILITY_NOT_SUPPORTED;
12774                                break;
12775                        }
12776                        break;
12777                }
12778                break;
12779
12780        case EC_DISABLE_OPERATION:
12781                switch (internal_command)
12782                {
12783                default:
12784                case EC_COMMAND_1:
12785                        if (plci->B1_facilities & B1_FACILITY_EC)
12786                        {
12787                                if (plci->sig_req)
12788                                {
12789                                        plci->internal_command = EC_COMMAND_1;
12790                                        return;
12791                                }
12792                                plci->internal_command = EC_COMMAND_2;
12793                                ec_write_parameters(plci);
12794                                return;
12795                        }
12796                        Rc = OK;
12797                case EC_COMMAND_2:
12798                        if ((Rc != OK) && (Rc != OK_FC))
12799                        {
12800                                dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12801                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12802                                Info = _FACILITY_NOT_SUPPORTED;
12803                                break;
12804                        }
12805                        adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12806                                                                  ~B1_FACILITY_EC), EC_COMMAND_3);
12807                case EC_COMMAND_3:
12808                        if (adjust_b_process(Id, plci, Rc) != GOOD)
12809                        {
12810                                dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12811                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12812                                Info = _FACILITY_NOT_SUPPORTED;
12813                                break;
12814                        }
12815                        if (plci->internal_command)
12816                                return;
12817                        break;
12818                }
12819                break;
12820        }
12821        sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12822              "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12823              PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12824}
12825
12826
12827static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
12828{
12829        word Info;
12830        word opt;
12831        API_PARSE ec_parms[3];
12832        byte result[16];
12833
12834        dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12835                        UnMapId(Id), (char *)(FILE_), __LINE__));
12836
12837        Info = GOOD;
12838        result[0] = 0;
12839        if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12840        {
12841                dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12842                                UnMapId(Id), (char *)(FILE_), __LINE__));
12843                Info = _FACILITY_NOT_SUPPORTED;
12844        }
12845        else
12846        {
12847                if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12848                {
12849                        if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12850                        {
12851                                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12852                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12853                                Info = _WRONG_MESSAGE_FORMAT;
12854                        }
12855                        else
12856                        {
12857                                if (plci == NULL)
12858                                {
12859                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12860                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12861                                        Info = _WRONG_IDENTIFIER;
12862                                }
12863                                else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12864                                {
12865                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12866                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12867                                        Info = _WRONG_STATE;
12868                                }
12869                                else
12870                                {
12871                                        plci->command = 0;
12872                                        plci->ec_cmd = GET_WORD(ec_parms[0].info);
12873                                        plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12874                                        result[0] = 2;
12875                                        PUT_WORD(&result[1], EC_SUCCESS);
12876                                        if (msg[1].length >= 4)
12877                                        {
12878                                                opt = GET_WORD(&ec_parms[0].info[2]);
12879                                                plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12880                                                                          LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12881                                                if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12882                                                        plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12883                                                if (opt & EC_DETECT_DISABLE_TONE)
12884                                                        plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12885                                                if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12886                                                        plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12887                                                if (msg[1].length >= 6)
12888                                                {
12889                                                        plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12890                                                }
12891                                        }
12892                                        switch (plci->ec_cmd)
12893                                        {
12894                                        case EC_ENABLE_OPERATION:
12895                                                plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12896                                                start_internal_command(Id, plci, ec_command);
12897                                                return (false);
12898
12899                                        case EC_DISABLE_OPERATION:
12900                                                plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12901                                                        LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12902                                                        LEC_RESET_COEFFICIENTS;
12903                                                start_internal_command(Id, plci, ec_command);
12904                                                return (false);
12905
12906                                        case EC_FREEZE_COEFFICIENTS:
12907                                                plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12908                                                start_internal_command(Id, plci, ec_command);
12909                                                return (false);
12910
12911                                        case EC_RESUME_COEFFICIENT_UPDATE:
12912                                                plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12913                                                start_internal_command(Id, plci, ec_command);
12914                                                return (false);
12915
12916                                        case EC_RESET_COEFFICIENTS:
12917                                                plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12918                                                start_internal_command(Id, plci, ec_command);
12919                                                return (false);
12920
12921                                        default:
12922                                                dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12923                                                                UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12924                                                PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12925                                        }
12926                                }
12927                        }
12928                }
12929                else
12930                {
12931                        if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12932                        {
12933                                dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12934                                                UnMapId(Id), (char *)(FILE_), __LINE__));
12935                                Info = _WRONG_MESSAGE_FORMAT;
12936                        }
12937                        else
12938                        {
12939                                if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12940                                {
12941                                        result[0] = 11;
12942                                        PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12943                                        result[3] = 8;
12944                                        PUT_WORD(&result[4], GOOD);
12945                                        PUT_WORD(&result[6], 0x0007);
12946                                        PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12947                                        PUT_WORD(&result[10], 0);
12948                                }
12949                                else if (plci == NULL)
12950                                {
12951                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12952                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12953                                        Info = _WRONG_IDENTIFIER;
12954                                }
12955                                else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12956                                {
12957                                        dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12958                                                        UnMapId(Id), (char *)(FILE_), __LINE__));
12959                                        Info = _WRONG_STATE;
12960                                }
12961                                else
12962                                {
12963                                        plci->command = 0;
12964                                        plci->ec_cmd = GET_WORD(ec_parms[0].info);
12965                                        plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12966                                        result[0] = 5;
12967                                        PUT_WORD(&result[1], plci->ec_cmd);
12968                                        result[3] = 2;
12969                                        PUT_WORD(&result[4], GOOD);
12970                                        plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12971                                                                  LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12972                                        plci->ec_tail_length = 0;
12973                                        if (ec_parms[1].length >= 2)
12974                                        {
12975                                                opt = GET_WORD(&ec_parms[1].info[1]);
12976                                                if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12977                                                        plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12978                                                if (opt & EC_DETECT_DISABLE_TONE)
12979                                                        plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12980                                                if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12981                                                        plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12982                                                if (ec_parms[1].length >= 4)
12983                                                {
12984                                                        plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12985                                                }
12986                                        }
12987                                        switch (plci->ec_cmd)
12988                                        {
12989                                        case EC_ENABLE_OPERATION:
12990                                                plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12991                                                start_internal_command(Id, plci, ec_command);
12992                                                return (false);
12993
12994                                        case EC_DISABLE_OPERATION:
12995                                                plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12996                                                        LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12997                                                        LEC_RESET_COEFFICIENTS;
12998                                                start_internal_command(Id, plci, ec_command);
12999                                                return (false);
13000
13001                                        default:
13002                                                dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
13003                                                                UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
13004                                                PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13005                                        }
13006                                }
13007                        }
13008                }
13009        }
13010        sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13011              "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13012              PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13013        return (false);
13014}
13015
13016
13017static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
13018{
13019        byte result[8];
13020
13021        dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
13022                        UnMapId(Id), (char *)(FILE_), __LINE__));
13023
13024        if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13025        {
13026                if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13027                {
13028                        result[0] = 2;
13029                        PUT_WORD(&result[1], 0);
13030                        switch (msg[1])
13031                        {
13032                        case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13033                                PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13034                                break;
13035                        case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13036                                PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13037                                break;
13038                        case LEC_DISABLE_RELEASED:
13039                                PUT_WORD(&result[1], EC_BYPASS_RELEASED);
13040                                break;
13041                        }
13042                }
13043                else
13044                {
13045                        result[0] = 5;
13046                        PUT_WORD(&result[1], EC_BYPASS_INDICATION);
13047                        result[3] = 2;
13048                        PUT_WORD(&result[4], 0);
13049                        switch (msg[1])
13050                        {
13051                        case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13052                                PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13053                                break;
13054                        case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13055                                PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13056                                break;
13057                        case LEC_DISABLE_RELEASED:
13058                                PUT_WORD(&result[4], EC_BYPASS_RELEASED);
13059                                break;
13060                        }
13061                }
13062                sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13063                      PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13064        }
13065}
13066
13067
13068
13069/*------------------------------------------------------------------*/
13070/* Advanced voice                                                   */
13071/*------------------------------------------------------------------*/
13072
13073static void adv_voice_write_coefs(PLCI *plci, word write_command)
13074{
13075        DIVA_CAPI_ADAPTER *a;
13076        word i;
13077        byte *p;
13078
13079        word w, n, j, k;
13080        byte ch_map[MIXER_CHANNELS_BRI];
13081
13082        byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13083
13084        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
13085                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13086                        (char *)(FILE_), __LINE__, write_command));
13087
13088        a = plci->adapter;
13089        p = coef_buffer + 1;
13090        *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13091        i = 0;
13092        while (i + sizeof(word) <= a->adv_voice_coef_length)
13093        {
13094                PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
13095                p += 2;
13096                i += 2;
13097        }
13098        while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13099        {
13100                PUT_WORD(p, 0x8000);
13101                p += 2;
13102                i += 2;
13103        }
13104
13105        if (!a->li_pri && (plci->li_bchannel_id == 0))
13106        {
13107                if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13108                {
13109                        plci->li_bchannel_id = 1;
13110                        li_config_table[a->li_base].plci = plci;
13111                        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13112                                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13113                                        (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13114                }
13115                else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13116                {
13117                        plci->li_bchannel_id = 2;
13118                        li_config_table[a->li_base + 1].plci = plci;
13119                        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13120                                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13121                                        (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13122                }
13123        }
13124        if (!a->li_pri && (plci->li_bchannel_id != 0)
13125            && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13126        {
13127                i = a->li_base + (plci->li_bchannel_id - 1);
13128                switch (write_command)
13129                {
13130                case ADV_VOICE_WRITE_ACTIVATION:
13131                        j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13132                        k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13133                        if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13134                        {
13135                                li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13136                                li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13137                        }
13138                        if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13139                        {
13140                                li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13141                                li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13142                                li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13143                                li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13144                        }
13145                        mixer_calculate_coefs(a);
13146                        li_config_table[i].curchnl = li_config_table[i].channel;
13147                        li_config_table[j].curchnl = li_config_table[j].channel;
13148                        if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13149                                li_config_table[k].curchnl = li_config_table[k].channel;
13150                        break;
13151
13152                case ADV_VOICE_WRITE_DEACTIVATION:
13153                        for (j = 0; j < li_total_channels; j++)
13154                        {
13155                                li_config_table[i].flag_table[j] = 0;
13156                                li_config_table[j].flag_table[i] = 0;
13157                        }
13158                        k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13159                        for (j = 0; j < li_total_channels; j++)
13160                        {
13161                                li_config_table[k].flag_table[j] = 0;
13162                                li_config_table[j].flag_table[k] = 0;
13163                        }
13164                        if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13165                        {
13166                                k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13167                                for (j = 0; j < li_total_channels; j++)
13168                                {
13169                                        li_config_table[k].flag_table[j] = 0;
13170                                        li_config_table[j].flag_table[k] = 0;
13171                                }
13172                        }
13173                        mixer_calculate_coefs(a);
13174                        break;
13175                }
13176                if (plci->B1_facilities & B1_FACILITY_MIXER)
13177                {
13178                        w = 0;
13179                        if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13180                                w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13181                        if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13182                                w |= MIXER_FEATURE_ENABLE_TX_DATA;
13183                        if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13184                                w |= MIXER_FEATURE_ENABLE_RX_DATA;
13185                        *(p++) = (byte) w;
13186                        *(p++) = (byte)(w >> 8);
13187                        for (j = 0; j < sizeof(ch_map); j += 2)
13188                        {
13189                                ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13190                                ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13191                        }
13192                        for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13193                        {
13194                                i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13195                                j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13196                                if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13197                                {
13198                                        *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13199                                        w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13200                                        li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13201                                }
13202                                else
13203                                {
13204                                        *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13205                                                a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13206                                }
13207                        }
13208                }
13209                else
13210                {
13211                        for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13212                                *(p++) = a->adv_voice_coef_buffer[i];
13213                }
13214        }
13215        else
13216
13217        {
13218                for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13219                        *(p++) = a->adv_voice_coef_buffer[i];
13220        }
13221        coef_buffer[0] = (p - coef_buffer) - 1;
13222        add_p(plci, FTY, coef_buffer);
13223        sig_req(plci, TEL_CTRL, 0);
13224        send_req(plci);
13225}
13226
13227
13228static void adv_voice_clear_config(PLCI *plci)
13229{
13230        DIVA_CAPI_ADAPTER *a;
13231
13232        word i, j;
13233
13234
13235        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13236                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13237                        (char *)(FILE_), __LINE__));
13238
13239        a = plci->adapter;
13240        if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13241        {
13242                a->adv_voice_coef_length = 0;
13243
13244                if (!a->li_pri && (plci->li_bchannel_id != 0)
13245                    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13246                {
13247                        i = a->li_base + (plci->li_bchannel_id - 1);
13248                        li_config_table[i].curchnl = 0;
13249                        li_config_table[i].channel = 0;
13250                        li_config_table[i].chflags = 0;
13251                        for (j = 0; j < li_total_channels; j++)
13252                        {
13253                                li_config_table[i].flag_table[j] = 0;
13254                                li_config_table[j].flag_table[i] = 0;
13255                                li_config_table[i].coef_table[j] = 0;
13256                                li_config_table[j].coef_table[i] = 0;
13257                        }
13258                        li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13259                        i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13260                        li_config_table[i].curchnl = 0;
13261                        li_config_table[i].channel = 0;
13262                        li_config_table[i].chflags = 0;
13263                        for (j = 0; j < li_total_channels; j++)
13264                        {
13265                                li_config_table[i].flag_table[j] = 0;
13266                                li_config_table[j].flag_table[i] = 0;
13267                                li_config_table[i].coef_table[j] = 0;
13268                                li_config_table[j].coef_table[i] = 0;
13269                        }
13270                        if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13271                        {
13272                                i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13273                                li_config_table[i].curchnl = 0;
13274                                li_config_table[i].channel = 0;
13275                                li_config_table[i].chflags = 0;
13276                                for (j = 0; j < li_total_channels; j++)
13277                                {
13278                                        li_config_table[i].flag_table[j] = 0;
13279                                        li_config_table[j].flag_table[i] = 0;
13280                                        li_config_table[i].coef_table[j] = 0;
13281                                        li_config_table[j].coef_table[i] = 0;
13282                                }
13283                        }
13284                }
13285
13286        }
13287}
13288
13289
13290static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13291{
13292
13293        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13294                        UnMapId(Id), (char *)(FILE_), __LINE__));
13295
13296}
13297
13298
13299static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13300{
13301
13302        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13303                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13304
13305        return (GOOD);
13306}
13307
13308
13309static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13310{
13311        DIVA_CAPI_ADAPTER *a;
13312        word Info;
13313
13314        dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13315                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13316
13317        Info = GOOD;
13318        a = plci->adapter;
13319        if ((plci->B1_facilities & B1_FACILITY_VOICE)
13320            && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13321        {
13322                switch (plci->adjust_b_state)
13323                {
13324                case ADJUST_B_RESTORE_VOICE_1:
13325                        plci->internal_command = plci->adjust_b_command;
13326                        if (plci->sig_req)
13327                        {
13328                                plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13329                                break;
13330                        }
13331                        adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13332                        plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13333                        break;
13334                case ADJUST_B_RESTORE_VOICE_2:
13335                        if ((Rc != OK) && (Rc != OK_FC))
13336                        {
13337                                dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13338                                                UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13339                                Info = _WRONG_STATE;
13340                                break;
13341                        }
13342                        break;
13343                }
13344        }
13345        return (Info);
13346}
13347
13348
13349
13350
13351/*------------------------------------------------------------------*/
13352/* B1 resource switching                                            */
13353/*------------------------------------------------------------------*/
13354
13355static byte b1_facilities_table[] =
13356{
13357        0x00,  /* 0  No bchannel resources      */
13358        0x00,  /* 1  Codec (automatic law)      */
13359        0x00,  /* 2  Codec (A-law)              */
13360        0x00,  /* 3  Codec (y-law)              */
13361        0x00,  /* 4  HDLC for X.21              */
13362        0x00,  /* 5  HDLC                       */
13363        0x00,  /* 6  External Device 0          */
13364        0x00,  /* 7  External Device 1          */
13365        0x00,  /* 8  HDLC 56k                   */
13366        0x00,  /* 9  Transparent                */
13367        0x00,  /* 10 Loopback to network        */
13368        0x00,  /* 11 Test pattern to net        */
13369        0x00,  /* 12 Rate adaptation sync       */
13370        0x00,  /* 13 Rate adaptation async      */
13371        0x00,  /* 14 R-Interface                */
13372        0x00,  /* 15 HDLC 128k leased line      */
13373        0x00,  /* 16 FAX                        */
13374        0x00,  /* 17 Modem async                */
13375        0x00,  /* 18 Modem sync HDLC            */
13376        0x00,  /* 19 V.110 async HDLC           */
13377        0x12,  /* 20 Adv voice (Trans,mixer)    */
13378        0x00,  /* 21 Codec connected to IC      */
13379        0x0c,  /* 22 Trans,DTMF                 */
13380        0x1e,  /* 23 Trans,DTMF+mixer           */
13381        0x1f,  /* 24 Trans,DTMF+mixer+local     */
13382        0x13,  /* 25 Trans,mixer+local          */
13383        0x12,  /* 26 HDLC,mixer                 */
13384        0x12,  /* 27 HDLC 56k,mixer             */
13385        0x2c,  /* 28 Trans,LEC+DTMF             */
13386        0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13387        0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13388        0x2c,  /* 31 RTP,LEC+DTMF               */
13389        0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13390        0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13391        0x00,  /* 34 Signaling task             */
13392        0x00,  /* 35 PIAFS                      */
13393        0x0c,  /* 36 Trans,DTMF+TONE            */
13394        0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13395        0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13396};
13397
13398
13399static word get_b1_facilities(PLCI *plci, byte b1_resource)
13400{
13401        word b1_facilities;
13402
13403        b1_facilities = b1_facilities_table[b1_resource];
13404        if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13405        {
13406
13407                if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13408                      || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13409
13410                {
13411                        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13412                                b1_facilities |= B1_FACILITY_DTMFX;
13413                        if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13414                                b1_facilities |= B1_FACILITY_DTMFR;
13415                }
13416        }
13417        if ((b1_resource == 17) || (b1_resource == 18))
13418        {
13419                if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13420                        b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13421        }
13422/*
13423  dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13424  (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13425  (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13426*/
13427        return (b1_facilities);
13428}
13429
13430
13431static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13432{
13433        byte b;
13434
13435        switch (b1_resource)
13436        {
13437        case 5:
13438        case 26:
13439                if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13440                        b = 26;
13441                else
13442                        b = 5;
13443                break;
13444
13445        case 8:
13446        case 27:
13447                if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13448                        b = 27;
13449                else
13450                        b = 8;
13451                break;
13452
13453        case 9:
13454        case 20:
13455        case 22:
13456        case 23:
13457        case 24:
13458        case 25:
13459        case 28:
13460        case 29:
13461        case 30:
13462        case 36:
13463        case 37:
13464        case 38:
13465                if (b1_facilities & B1_FACILITY_EC)
13466                {
13467                        if (b1_facilities & B1_FACILITY_LOCAL)
13468                                b = 30;
13469                        else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13470                                b = 29;
13471                        else
13472                                b = 28;
13473                }
13474
13475                else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13476                         && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13477                             || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13478                {
13479                        if (b1_facilities & B1_FACILITY_LOCAL)
13480                                b = 38;
13481                        else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13482                                b = 37;
13483                        else
13484                                b = 36;
13485                }
13486
13487                else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13488                          && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13489                         || ((b1_facilities & B1_FACILITY_DTMFR)
13490                             && ((b1_facilities & B1_FACILITY_MIXER)
13491                                 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13492                         || ((b1_facilities & B1_FACILITY_DTMFX)
13493                             && ((b1_facilities & B1_FACILITY_MIXER)
13494                                 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13495                {
13496                        if (b1_facilities & B1_FACILITY_LOCAL)
13497                                b = 24;
13498                        else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13499                                b = 23;
13500                        else
13501                                b = 22;
13502                }
13503                else
13504                {
13505                        if (b1_facilities & B1_FACILITY_LOCAL)
13506                                b = 25;
13507                        else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13508                                b = 20;
13509                        else
13510                                b = 9;
13511                }
13512                break;
13513
13514        case 31:
13515        case 32:
13516        case 33:
13517                if (b1_facilities & B1_FACILITY_LOCAL)
13518                        b = 33;
13519                else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13520                        b = 32;
13521                else
13522                        b = 31;
13523                break;
13524
13525        default:
13526                b = b1_resource;
13527        }
13528        dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13529                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13530                        (char *)(FILE_), __LINE__,
13531                        b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13532        return (b);
13533}
13534
13535
13536static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13537{
13538        word removed_facilities;
13539
13540        dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13541                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13542                        (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13543                        new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13544
13545        new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13546        removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13547
13548        if (removed_facilities & B1_FACILITY_EC)
13549                ec_clear_config(plci);
13550
13551
13552        if (removed_facilities & B1_FACILITY_DTMFR)
13553        {
13554                dtmf_rec_clear_config(plci);
13555                dtmf_parameter_clear_config(plci);
13556        }
13557        if (removed_facilities & B1_FACILITY_DTMFX)
13558                dtmf_send_clear_config(plci);
13559
13560
13561        if (removed_facilities & B1_FACILITY_MIXER)
13562                mixer_clear_config(plci);
13563
13564        if (removed_facilities & B1_FACILITY_VOICE)
13565                adv_voice_clear_config(plci);
13566        plci->B1_facilities = new_b1_facilities;
13567}
13568
13569
13570static void adjust_b_clear(PLCI *plci)
13571{
13572
13573        dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13574                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13575                        (char *)(FILE_), __LINE__));
13576
13577        plci->adjust_b_restore = false;
13578}
13579
13580
13581static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13582{
13583        word Info;
13584        byte b1_resource;
13585        NCCI *ncci_ptr;
13586        API_PARSE bp[2];
13587
13588        dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13589                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13590
13591        Info = GOOD;
13592        switch (plci->adjust_b_state)
13593        {
13594        case ADJUST_B_START:
13595                if ((plci->adjust_b_parms_msg == NULL)
13596                    && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13597                    && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13598                                                 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13599                {
13600                        b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13601                                0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13602                        if (b1_resource == plci->B1_resource)
13603                        {
13604                                adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13605                                break;
13606                        }
13607                        if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13608                        {
13609                                dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13610                                                UnMapId(Id), (char *)(FILE_), __LINE__,
13611                                                plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13612                                Info = _WRONG_STATE;
13613                                break;
13614                        }
13615                }
13616                if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13617                {
13618
13619                        mixer_prepare_switch(Id, plci);
13620
13621
13622                        dtmf_prepare_switch(Id, plci);
13623                        dtmf_parameter_prepare_switch(Id, plci);
13624
13625
13626                        ec_prepare_switch(Id, plci);
13627
13628                        adv_voice_prepare_switch(Id, plci);
13629                }
13630                plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13631                Rc = OK;
13632        case ADJUST_B_SAVE_MIXER_1:
13633                if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13634                {
13635
13636                        Info = mixer_save_config(Id, plci, Rc);
13637                        if ((Info != GOOD) || plci->internal_command)
13638                                break;
13639
13640                }
13641                plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13642                Rc = OK;
13643        case ADJUST_B_SAVE_DTMF_1:
13644                if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13645                {
13646
13647                        Info = dtmf_save_config(Id, plci, Rc);
13648                        if ((Info != GOOD) || plci->internal_command)
13649                                break;
13650
13651                }
13652                plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13653        case ADJUST_B_REMOVE_L23_1:
13654                if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13655                    && plci->NL.Id && !plci->nl_remove_id)
13656                {
13657                        plci->internal_command = plci->adjust_b_command;
13658                        if (plci->adjust_b_ncci != 0)
13659                        {
13660                                ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13661                                while (ncci_ptr->data_pending)
13662                                {
13663                                        plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13664                                        data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13665                                }
13666                                while (ncci_ptr->data_ack_pending)
13667                                        data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13668                        }
13669                        nl_req_ncci(plci, REMOVE,
13670                                    (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13671                        send_req(plci);
13672                        plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13673                        break;
13674                }
13675                plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13676                Rc = OK;
13677        case ADJUST_B_REMOVE_L23_2:
13678                if ((Rc != OK) && (Rc != OK_FC))
13679                {
13680                        dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13681                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13682                        Info = _WRONG_STATE;
13683                        break;
13684                }
13685                if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13686                {
13687                        if (plci_nl_busy(plci))
13688                        {
13689                                plci->internal_command = plci->adjust_b_command;
13690                                break;
13691                        }
13692                }
13693                plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13694                Rc = OK;
13695        case ADJUST_B_SAVE_EC_1:
13696                if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13697                {
13698
13699                        Info = ec_save_config(Id, plci, Rc);
13700                        if ((Info != GOOD) || plci->internal_command)
13701                                break;
13702
13703                }
13704                plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13705                Rc = OK;
13706        case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13707                if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13708                {
13709
13710                        Info = dtmf_parameter_save_config(Id, plci, Rc);
13711                        if ((Info != GOOD) || plci->internal_command)
13712                                break;
13713
13714                }
13715                plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13716                Rc = OK;
13717        case ADJUST_B_SAVE_VOICE_1:
13718                if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13719                {
13720                        Info = adv_voice_save_config(Id, plci, Rc);
13721                        if ((Info != GOOD) || plci->internal_command)
13722                                break;
13723                }
13724                plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13725        case ADJUST_B_SWITCH_L1_1:
13726                if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13727                {
13728                        if (plci->sig_req)
13729                        {
13730                                plci->internal_command = plci->adjust_b_command;
13731                                break;
13732                        }
13733                        if (plci->adjust_b_parms_msg != NULL)
13734                                api_load_msg(plci->adjust_b_parms_msg, bp);
13735                        else
13736                                api_load_msg(&plci->B_protocol, bp);
13737                        Info = add_b1(plci, bp,
13738                                      (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13739                                      plci->adjust_b_facilities);
13740                        if (Info != GOOD)
13741                        {
13742                                dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13743                                                UnMapId(Id), (char *)(FILE_), __LINE__,
13744                                                plci->B1_resource, plci->adjust_b_facilities));
13745                                break;
13746                        }
13747                        plci->internal_command = plci->adjust_b_command;
13748                        sig_req(plci, RESOURCES, 0);
13749                        send_req(plci);
13750                        plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13751                        break;
13752                }
13753                plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13754                Rc = OK;
13755        case ADJUST_B_SWITCH_L1_2:
13756                if ((Rc != OK) && (Rc != OK_FC))
13757                {
13758                        dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13759                                        UnMapId(Id), (char *)(FILE_), __LINE__,
13760                                        Rc, plci->B1_resource, plci->adjust_b_facilities));
13761                        Info = _WRONG_STATE;
13762                        break;
13763                }
13764                plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13765                Rc = OK;
13766        case ADJUST_B_RESTORE_VOICE_1:
13767        case ADJUST_B_RESTORE_VOICE_2:
13768                if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13769                {
13770                        Info = adv_voice_restore_config(Id, plci, Rc);
13771                        if ((Info != GOOD) || plci->internal_command)
13772                                break;
13773                }
13774                plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13775                Rc = OK;
13776        case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13777        case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13778                if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13779                {
13780
13781                        Info = dtmf_parameter_restore_config(Id, plci, Rc);
13782                        if ((Info != GOOD) || plci->internal_command)
13783                                break;
13784
13785                }
13786                plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13787                Rc = OK;
13788        case ADJUST_B_RESTORE_EC_1:
13789        case ADJUST_B_RESTORE_EC_2:
13790                if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13791                {
13792
13793                        Info = ec_restore_config(Id, plci, Rc);
13794                        if ((Info != GOOD) || plci->internal_command)
13795                                break;
13796
13797                }
13798                plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13799        case ADJUST_B_ASSIGN_L23_1:
13800                if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13801                {
13802                        if (plci_nl_busy(plci))
13803                        {
13804                                plci->internal_command = plci->adjust_b_command;
13805                                break;
13806                        }
13807                        if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13808                                plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13809                        if (plci->adjust_b_parms_msg != NULL)
13810                                api_load_msg(plci->adjust_b_parms_msg, bp);
13811                        else
13812                                api_load_msg(&plci->B_protocol, bp);
13813                        Info = add_b23(plci, bp);
13814                        if (Info != GOOD)
13815                        {
13816                                dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13817                                                UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13818                                break;
13819                        }
13820                        plci->internal_command = plci->adjust_b_command;
13821                        nl_req_ncci(plci, ASSIGN, 0);
13822                        send_req(plci);
13823                        plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13824                        break;
13825                }
13826                plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13827                Rc = ASSIGN_OK;
13828        case ADJUST_B_ASSIGN_L23_2:
13829                if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13830                {
13831                        dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13832                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13833                        Info = _WRONG_STATE;
13834                        break;
13835                }
13836                if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13837                {
13838                        if (Rc != ASSIGN_OK)
13839                        {
13840                                plci->internal_command = plci->adjust_b_command;
13841                                break;
13842                        }
13843                }
13844                if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13845                {
13846                        plci->adjust_b_restore = true;
13847                        break;
13848                }
13849                plci->adjust_b_state = ADJUST_B_CONNECT_1;
13850        case ADJUST_B_CONNECT_1:
13851                if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13852                {
13853                        plci->internal_command = plci->adjust_b_command;
13854                        if (plci_nl_busy(plci))
13855                                break;
13856                        nl_req_ncci(plci, N_CONNECT, 0);
13857                        send_req(plci);
13858                        plci->adjust_b_state = ADJUST_B_CONNECT_2;
13859                        break;
13860                }
13861                plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13862                Rc = OK;
13863        case ADJUST_B_CONNECT_2:
13864        case ADJUST_B_CONNECT_3:
13865        case ADJUST_B_CONNECT_4:
13866                if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13867                {
13868                        dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13869                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13870                        Info = _WRONG_STATE;
13871                        break;
13872                }
13873                if (Rc == OK)
13874                {
13875                        if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13876                        {
13877                                get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13878                                Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13879                        }
13880                        if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13881                                plci->adjust_b_state = ADJUST_B_CONNECT_3;
13882                        else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13883                                plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13884                }
13885                else if (Rc == 0)
13886                {
13887                        if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13888                                plci->adjust_b_state = ADJUST_B_CONNECT_4;
13889                        else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13890                                plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13891                }
13892                if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13893                {
13894                        plci->internal_command = plci->adjust_b_command;
13895                        break;
13896                }
13897                Rc = OK;
13898        case ADJUST_B_RESTORE_DTMF_1:
13899        case ADJUST_B_RESTORE_DTMF_2:
13900                if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13901                {
13902
13903                        Info = dtmf_restore_config(Id, plci, Rc);
13904                        if ((Info != GOOD) || plci->internal_command)
13905                                break;
13906
13907                }
13908                plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13909                Rc = OK;
13910        case ADJUST_B_RESTORE_MIXER_1:
13911        case ADJUST_B_RESTORE_MIXER_2:
13912        case ADJUST_B_RESTORE_MIXER_3:
13913        case ADJUST_B_RESTORE_MIXER_4:
13914        case ADJUST_B_RESTORE_MIXER_5:
13915        case ADJUST_B_RESTORE_MIXER_6:
13916        case ADJUST_B_RESTORE_MIXER_7:
13917                if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13918                {
13919
13920                        Info = mixer_restore_config(Id, plci, Rc);
13921                        if ((Info != GOOD) || plci->internal_command)
13922                                break;
13923
13924                }
13925                plci->adjust_b_state = ADJUST_B_END;
13926        case ADJUST_B_END:
13927                break;
13928        }
13929        return (Info);
13930}
13931
13932
13933static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13934{
13935
13936        dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13937                        UnMapId(Id), (char *)(FILE_), __LINE__,
13938                        plci->B1_resource, b1_facilities));
13939
13940        plci->adjust_b_parms_msg = bp_msg;
13941        plci->adjust_b_facilities = b1_facilities;
13942        plci->adjust_b_command = internal_command;
13943        plci->adjust_b_ncci = (word)(Id >> 16);
13944        if ((bp_msg == NULL) && (plci->B1_resource == 0))
13945                plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13946        else
13947                plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13948        plci->adjust_b_state = ADJUST_B_START;
13949        dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13950                        UnMapId(Id), (char *)(FILE_), __LINE__,
13951                        plci->B1_resource, b1_facilities));
13952}
13953
13954
13955static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13956{
13957        word internal_command;
13958
13959        dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13960                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13961
13962        internal_command = plci->internal_command;
13963        plci->internal_command = 0;
13964        switch (internal_command)
13965        {
13966        default:
13967                plci->command = 0;
13968                if (plci->req_in != 0)
13969                {
13970                        plci->internal_command = ADJUST_B_RESTORE_1;
13971                        break;
13972                }
13973                Rc = OK;
13974        case ADJUST_B_RESTORE_1:
13975                if ((Rc != OK) && (Rc != OK_FC))
13976                {
13977                        dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13978                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13979                }
13980                plci->adjust_b_parms_msg = NULL;
13981                plci->adjust_b_facilities = plci->B1_facilities;
13982                plci->adjust_b_command = ADJUST_B_RESTORE_2;
13983                plci->adjust_b_ncci = (word)(Id >> 16);
13984                plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13985                plci->adjust_b_state = ADJUST_B_START;
13986                dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13987                                UnMapId(Id), (char *)(FILE_), __LINE__));
13988        case ADJUST_B_RESTORE_2:
13989                if (adjust_b_process(Id, plci, Rc) != GOOD)
13990                {
13991                        dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13992                                        UnMapId(Id), (char *)(FILE_), __LINE__));
13993                }
13994                if (plci->internal_command)
13995                        break;
13996                break;
13997        }
13998}
13999
14000
14001static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
14002{
14003        word Info;
14004        word internal_command;
14005
14006        dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
14007                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14008
14009        Info = GOOD;
14010        internal_command = plci->internal_command;
14011        plci->internal_command = 0;
14012        switch (internal_command)
14013        {
14014        default:
14015                plci->command = 0;
14016                plci->adjust_b_parms_msg = NULL;
14017                plci->adjust_b_facilities = plci->B1_facilities;
14018                plci->adjust_b_command = RESET_B3_COMMAND_1;
14019                plci->adjust_b_ncci = (word)(Id >> 16);
14020                plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14021                plci->adjust_b_state = ADJUST_B_START;
14022                dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
14023                                UnMapId(Id), (char *)(FILE_), __LINE__));
14024        case RESET_B3_COMMAND_1:
14025                Info = adjust_b_process(Id, plci, Rc);
14026                if (Info != GOOD)
14027                {
14028                        dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
14029                                        UnMapId(Id), (char *)(FILE_), __LINE__));
14030                        break;
14031                }
14032                if (plci->internal_command)
14033                        return;
14034                break;
14035        }
14036/*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14037        sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
14038}
14039
14040
14041static void select_b_command(dword Id, PLCI *plci, byte Rc)
14042{
14043        word Info;
14044        word internal_command;
14045        byte esc_chi[3];
14046
14047        dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
14048                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14049
14050        Info = GOOD;
14051        internal_command = plci->internal_command;
14052        plci->internal_command = 0;
14053        switch (internal_command)
14054        {
14055        default:
14056                plci->command = 0;
14057                plci->adjust_b_parms_msg = &plci->saved_msg;
14058                if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14059                        plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14060                else
14061                        plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14062                plci->adjust_b_command = SELECT_B_COMMAND_1;
14063                plci->adjust_b_ncci = (word)(Id >> 16);
14064                if (plci->saved_msg.parms[0].length == 0)
14065                {
14066                        plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14067                                ADJUST_B_MODE_NO_RESOURCE;
14068                }
14069                else
14070                {
14071                        plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14072                                ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14073                }
14074                plci->adjust_b_state = ADJUST_B_START;
14075                dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
14076                                UnMapId(Id), (char *)(FILE_), __LINE__));
14077        case SELECT_B_COMMAND_1:
14078                Info = adjust_b_process(Id, plci, Rc);
14079                if (Info != GOOD)
14080                {
14081                        dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
14082                                        UnMapId(Id), (char *)(FILE_), __LINE__));
14083                        break;
14084                }
14085                if (plci->internal_command)
14086                        return;
14087                if (plci->tel == ADV_VOICE)
14088                {
14089                        esc_chi[0] = 0x02;
14090                        esc_chi[1] = 0x18;
14091                        esc_chi[2] = plci->b_channel;
14092                        SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14093                }
14094                break;
14095        }
14096        sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14097}
14098
14099
14100static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
14101{
14102        word internal_command;
14103
14104        dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14105                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14106
14107        internal_command = plci->internal_command;
14108        plci->internal_command = 0;
14109        switch (internal_command)
14110        {
14111        default:
14112                plci->command = 0;
14113        case FAX_CONNECT_ACK_COMMAND_1:
14114                if (plci_nl_busy(plci))
14115                {
14116                        plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14117                        return;
14118                }
14119                plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14120                plci->NData[0].P = plci->fax_connect_info_buffer;
14121                plci->NData[0].PLength = plci->fax_connect_info_length;
14122                plci->NL.X = plci->NData;
14123                plci->NL.ReqCh = 0;
14124                plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14125                plci->adapter->request(&plci->NL);
14126                return;
14127        case FAX_CONNECT_ACK_COMMAND_2:
14128                if ((Rc != OK) && (Rc != OK_FC))
14129                {
14130                        dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14131                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14132                        break;
14133                }
14134        }
14135        if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14136            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14137        {
14138                if (plci->B3_prot == 4)
14139                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14140                else
14141                        sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
14142                plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14143        }
14144}
14145
14146
14147static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14148{
14149        word internal_command;
14150
14151        dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14152                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14153
14154        internal_command = plci->internal_command;
14155        plci->internal_command = 0;
14156        switch (internal_command)
14157        {
14158        default:
14159                plci->command = 0;
14160        case FAX_EDATA_ACK_COMMAND_1:
14161                if (plci_nl_busy(plci))
14162                {
14163                        plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14164                        return;
14165                }
14166                plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14167                plci->NData[0].P = plci->fax_connect_info_buffer;
14168                plci->NData[0].PLength = plci->fax_edata_ack_length;
14169                plci->NL.X = plci->NData;
14170                plci->NL.ReqCh = 0;
14171                plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14172                plci->adapter->request(&plci->NL);
14173                return;
14174        case FAX_EDATA_ACK_COMMAND_2:
14175                if ((Rc != OK) && (Rc != OK_FC))
14176                {
14177                        dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14178                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14179                        break;
14180                }
14181        }
14182}
14183
14184
14185static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14186{
14187        word Info;
14188        word internal_command;
14189
14190        dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14191                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14192
14193        Info = GOOD;
14194        internal_command = plci->internal_command;
14195        plci->internal_command = 0;
14196        switch (internal_command)
14197        {
14198        default:
14199                plci->command = 0;
14200        case FAX_CONNECT_INFO_COMMAND_1:
14201                if (plci_nl_busy(plci))
14202                {
14203                        plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14204                        return;
14205                }
14206                plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14207                plci->NData[0].P = plci->fax_connect_info_buffer;
14208                plci->NData[0].PLength = plci->fax_connect_info_length;
14209                plci->NL.X = plci->NData;
14210                plci->NL.ReqCh = 0;
14211                plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14212                plci->adapter->request(&plci->NL);
14213                return;
14214        case FAX_CONNECT_INFO_COMMAND_2:
14215                if ((Rc != OK) && (Rc != OK_FC))
14216                {
14217                        dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14218                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14219                        Info = _WRONG_STATE;
14220                        break;
14221                }
14222                if (plci_nl_busy(plci))
14223                {
14224                        plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14225                        return;
14226                }
14227                plci->command = _CONNECT_B3_R;
14228                nl_req_ncci(plci, N_CONNECT, 0);
14229                send_req(plci);
14230                return;
14231        }
14232        sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14233}
14234
14235
14236static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14237{
14238        word Info;
14239        word internal_command;
14240
14241        dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14242                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14243
14244        Info = GOOD;
14245        internal_command = plci->internal_command;
14246        plci->internal_command = 0;
14247        switch (internal_command)
14248        {
14249        default:
14250                plci->command = 0;
14251                plci->adjust_b_parms_msg = NULL;
14252                plci->adjust_b_facilities = plci->B1_facilities;
14253                plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14254                plci->adjust_b_ncci = (word)(Id >> 16);
14255                plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14256                plci->adjust_b_state = ADJUST_B_START;
14257                dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14258                                UnMapId(Id), (char *)(FILE_), __LINE__));
14259        case FAX_ADJUST_B23_COMMAND_1:
14260                Info = adjust_b_process(Id, plci, Rc);
14261                if (Info != GOOD)
14262                {
14263                        dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14264                                        UnMapId(Id), (char *)(FILE_), __LINE__));
14265                        break;
14266                }
14267                if (plci->internal_command)
14268                        return;
14269        case FAX_ADJUST_B23_COMMAND_2:
14270                if (plci_nl_busy(plci))
14271                {
14272                        plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14273                        return;
14274                }
14275                plci->command = _CONNECT_B3_R;
14276                nl_req_ncci(plci, N_CONNECT, 0);
14277                send_req(plci);
14278                return;
14279        }
14280        sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14281}
14282
14283
14284static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14285{
14286        word internal_command;
14287
14288        dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14289                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14290
14291        internal_command = plci->internal_command;
14292        plci->internal_command = 0;
14293        switch (internal_command)
14294        {
14295        default:
14296                plci->command = 0;
14297                plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14298                return;
14299        case FAX_DISCONNECT_COMMAND_1:
14300        case FAX_DISCONNECT_COMMAND_2:
14301        case FAX_DISCONNECT_COMMAND_3:
14302                if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14303                {
14304                        dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14305                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14306                        break;
14307                }
14308                if (Rc == OK)
14309                {
14310                        if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14311                            || (internal_command == FAX_DISCONNECT_COMMAND_2))
14312                        {
14313                                plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14314                        }
14315                }
14316                else if (Rc == 0)
14317                {
14318                        if (internal_command == FAX_DISCONNECT_COMMAND_1)
14319                                plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14320                }
14321                return;
14322        }
14323}
14324
14325
14326
14327static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14328{
14329        word Info;
14330        word internal_command;
14331
14332        dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14333                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14334
14335        Info = GOOD;
14336        internal_command = plci->internal_command;
14337        plci->internal_command = 0;
14338        switch (internal_command)
14339        {
14340        default:
14341                plci->command = 0;
14342        case RTP_CONNECT_B3_REQ_COMMAND_1:
14343                if (plci_nl_busy(plci))
14344                {
14345                        plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14346                        return;
14347                }
14348                plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14349                nl_req_ncci(plci, N_CONNECT, 0);
14350                send_req(plci);
14351                return;
14352        case RTP_CONNECT_B3_REQ_COMMAND_2:
14353                if ((Rc != OK) && (Rc != OK_FC))
14354                {
14355                        dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14356                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14357                        Info = _WRONG_STATE;
14358                        break;
14359                }
14360                if (plci_nl_busy(plci))
14361                {
14362                        plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14363                        return;
14364                }
14365                plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14366                plci->NData[0].PLength = plci->internal_req_buffer[0];
14367                plci->NData[0].P = plci->internal_req_buffer + 1;
14368                plci->NL.X = plci->NData;
14369                plci->NL.ReqCh = 0;
14370                plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14371                plci->adapter->request(&plci->NL);
14372                break;
14373        case RTP_CONNECT_B3_REQ_COMMAND_3:
14374                return;
14375        }
14376        sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14377}
14378
14379
14380static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14381{
14382        word internal_command;
14383
14384        dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14385                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14386
14387        internal_command = plci->internal_command;
14388        plci->internal_command = 0;
14389        switch (internal_command)
14390        {
14391        default:
14392                plci->command = 0;
14393        case RTP_CONNECT_B3_RES_COMMAND_1:
14394                if (plci_nl_busy(plci))
14395                {
14396                        plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14397                        return;
14398                }
14399                plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14400                nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14401                send_req(plci);
14402                return;
14403        case RTP_CONNECT_B3_RES_COMMAND_2:
14404                if ((Rc != OK) && (Rc != OK_FC))
14405                {
14406                        dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14407                                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14408                        break;
14409                }
14410                if (plci_nl_busy(plci))
14411                {
14412                        plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14413                        return;
14414                }
14415                sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14416                plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14417                plci->NData[0].PLength = plci->internal_req_buffer[0];
14418                plci->NData[0].P = plci->internal_req_buffer + 1;
14419                plci->NL.X = plci->NData;
14420                plci->NL.ReqCh = 0;
14421                plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14422                plci->adapter->request(&plci->NL);
14423                return;
14424        case RTP_CONNECT_B3_RES_COMMAND_3:
14425                return;
14426        }
14427}
14428
14429
14430
14431static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14432{
14433        byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14434        word Info;
14435        word internal_command;
14436
14437        dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14438                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14439
14440        Info = GOOD;
14441        internal_command = plci->internal_command;
14442        plci->internal_command = 0;
14443        switch (internal_command)
14444        {
14445        default:
14446                if (!plci->NL.Id)
14447                        break;
14448                plci->command = 0;
14449                plci->adjust_b_parms_msg = NULL;
14450                plci->adjust_b_facilities = plci->B1_facilities;
14451                plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14452                plci->adjust_b_ncci = (word)(Id >> 16);
14453                plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14454                plci->adjust_b_state = ADJUST_B_START;
14455                dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14456                                UnMapId(Id), (char *)(FILE_), __LINE__));
14457        case HOLD_SAVE_COMMAND_1:
14458                Info = adjust_b_process(Id, plci, Rc);
14459                if (Info != GOOD)
14460                {
14461                        dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14462                                        UnMapId(Id), (char *)(FILE_), __LINE__));
14463                        break;
14464                }
14465                if (plci->internal_command)
14466                        return;
14467        }
14468        sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14469}
14470
14471
14472static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14473{
14474        byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14475        word Info;
14476        word internal_command;
14477
14478        dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14479                        UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14480
14481        Info = GOOD;
14482        internal_command = plci->internal_command;
14483        plci->internal_command = 0;
14484        switch (internal_command)
14485        {
14486        default:
14487                plci->command = 0;
14488                plci->adjust_b_parms_msg = NULL;
14489                plci->adjust_b_facilities = plci->B1_facilities;
14490                plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14491                plci->adjust_b_ncci = (word)(Id >> 16);
14492                plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14493                plci->adjust_b_state = ADJUST_B_START;
14494                dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14495                                UnMapId(Id), (char *)(FILE_), __LINE__));
14496        case RETRIEVE_RESTORE_COMMAND_1:
14497                Info = adjust_b_process(Id, plci, Rc);
14498                if (Info != GOOD)
14499                {
14500                        dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14501                                        UnMapId(Id), (char *)(FILE_), __LINE__));
14502                        break;
14503                }
14504                if (plci->internal_command)
14505                        return;
14506        }
14507        sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14508}
14509
14510
14511static void init_b1_config(PLCI *plci)
14512{
14513
14514        dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14515                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14516                        (char *)(FILE_), __LINE__));
14517
14518        plci->B1_resource = 0;
14519        plci->B1_facilities = 0;
14520
14521        plci->li_bchannel_id = 0;
14522        mixer_clear_config(plci);
14523
14524
14525        ec_clear_config(plci);
14526
14527
14528        dtmf_rec_clear_config(plci);
14529        dtmf_send_clear_config(plci);
14530        dtmf_parameter_clear_config(plci);
14531
14532        adv_voice_clear_config(plci);
14533        adjust_b_clear(plci);
14534}
14535
14536
14537static void clear_b1_config(PLCI *plci)
14538{
14539
14540        dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14541                        (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14542                        (char *)(FILE_), __LINE__));
14543
14544        adv_voice_clear_config(plci);
14545        adjust_b_clear(plci);
14546
14547        ec_clear_config(plci);
14548
14549
14550        dtmf_rec_clear_config(plci);
14551        dtmf_send_clear_config(plci);
14552        dtmf_parameter_clear_config(plci);
14553
14554
14555        if ((plci->li_bchannel_id != 0)
14556            && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14557        {
14558                mixer_clear_config(plci);
14559                li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14560                plci->li_bchannel_id = 0;
14561        }
14562
14563        plci->B1_resource = 0;
14564        plci->B1_facilities = 0;
14565}
14566
14567
14568/* -----------------------------------------------------------------
14569   XON protocol local helpers
14570   ----------------------------------------------------------------- */
14571static void channel_flow_control_remove(PLCI *plci) {
14572        DIVA_CAPI_ADAPTER *a = plci->adapter;
14573        word i;
14574        for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14575                if (a->ch_flow_plci[i] == plci->Id) {
14576                        a->ch_flow_plci[i] = 0;
14577                        a->ch_flow_control[i] = 0;
14578                }
14579        }
14580}
14581
14582static void channel_x_on(PLCI *plci, byte ch) {
14583        DIVA_CAPI_ADAPTER *a = plci->adapter;
14584        if (a->ch_flow_control[ch] & N_XON_SENT) {
14585                a->ch_flow_control[ch] &= ~N_XON_SENT;
14586        }
14587}
14588
14589static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14590        DIVA_CAPI_ADAPTER *a = plci->adapter;
14591        if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14592                a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14593                a->ch_flow_plci[ch] = plci->Id;
14594                a->ch_flow_control_pending++;
14595        }
14596}
14597
14598static void channel_request_xon(PLCI *plci, byte ch) {
14599        DIVA_CAPI_ADAPTER *a = plci->adapter;
14600
14601        if (a->ch_flow_control[ch] & N_CH_XOFF) {
14602                a->ch_flow_control[ch] |= N_XON_REQ;
14603                a->ch_flow_control[ch] &= ~N_CH_XOFF;
14604                a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14605        }
14606}
14607
14608static void channel_xmit_extended_xon(PLCI *plci) {
14609        DIVA_CAPI_ADAPTER *a;
14610        int max_ch = ARRAY_SIZE(a->ch_flow_control);
14611        int i, one_requested = 0;
14612
14613        if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14614                return;
14615        }
14616
14617        for (i = 0; i < max_ch; i++) {
14618                if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14619                    (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14620                    (plci->Id == a->ch_flow_plci[i])) {
14621                        channel_request_xon(plci, (byte)i);
14622                        one_requested = 1;
14623                }
14624        }
14625
14626        if (one_requested) {
14627                channel_xmit_xon(plci);
14628        }
14629}
14630
14631/*
14632  Try to xmit next X_ON
14633*/
14634static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14635        int max_ch = ARRAY_SIZE(a->ch_flow_control);
14636        int i;
14637
14638        if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14639                return (0);
14640        }
14641
14642        if (a->last_flow_control_ch >= max_ch) {
14643                a->last_flow_control_ch = 1;
14644        }
14645        for (i = a->last_flow_control_ch; i < max_ch; i++) {
14646                if ((a->ch_flow_control[i] & N_XON_REQ) &&
14647                    (plci->Id == a->ch_flow_plci[i])) {
14648                        a->last_flow_control_ch = i + 1;
14649                        return (i);
14650                }
14651        }
14652
14653        for (i = 1; i < a->last_flow_control_ch; i++) {
14654                if ((a->ch_flow_control[i] & N_XON_REQ) &&
14655                    (plci->Id == a->ch_flow_plci[i])) {
14656                        a->last_flow_control_ch = i + 1;
14657                        return (i);
14658                }
14659        }
14660
14661        return (0);
14662}
14663
14664static void channel_xmit_xon(PLCI *plci) {
14665        DIVA_CAPI_ADAPTER *a = plci->adapter;
14666        byte ch;
14667
14668        if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14669                return;
14670        }
14671        if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14672                return;
14673        }
14674        a->ch_flow_control[ch] &= ~N_XON_REQ;
14675        a->ch_flow_control[ch] |= N_XON_SENT;
14676
14677        plci->NL.Req = plci->nl_req = (byte)N_XON;
14678        plci->NL.ReqCh         = ch;
14679        plci->NL.X             = plci->NData;
14680        plci->NL.XNum          = 1;
14681        plci->NData[0].P       = &plci->RBuffer[0];
14682        plci->NData[0].PLength = 0;
14683
14684        plci->adapter->request(&plci->NL);
14685}
14686
14687static int channel_can_xon(PLCI *plci, byte ch) {
14688        APPL *APPLptr;
14689        DIVA_CAPI_ADAPTER *a;
14690        word NCCIcode;
14691        dword count;
14692        word Num;
14693        word i;
14694
14695        APPLptr = plci->appl;
14696        a = plci->adapter;
14697
14698        if (!APPLptr)
14699                return (0);
14700
14701        NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14702
14703        /* count all buffers within the Application pool    */
14704        /* belonging to the same NCCI. XON if a first is    */
14705        /* used.                                            */
14706        count = 0;
14707        Num = 0xffff;
14708        for (i = 0; i < APPLptr->MaxBuffer; i++) {
14709                if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14710                if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14711        }
14712        if ((count > 2) || (Num == 0xffff)) {
14713                return (0);
14714        }
14715        return (1);
14716}
14717
14718
14719/*------------------------------------------------------------------*/
14720
14721static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14722{
14723        return 1;
14724}
14725
14726
14727
14728/**********************************************************************************/
14729/* function groups the listening applications according to the CIP mask and the   */
14730/* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14731/* are not multi-instance capable, so they start e.g. 30 applications what causes */
14732/* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14733/* function must be enabled by setting "a->group_optimization_enabled" from the   */
14734/* OS specific part (per adapter).                                                */
14735/**********************************************************************************/
14736static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14737{
14738        word i, j, k, busy, group_found;
14739        dword info_mask_group[MAX_CIP_TYPES];
14740        dword cip_mask_group[MAX_CIP_TYPES];
14741        word appl_number_group_type[MAX_APPL];
14742        PLCI *auxplci;
14743
14744        set_group_ind_mask(plci); /* all APPLs within this inc. call are allowed to dial in */
14745
14746        if (!a->group_optimization_enabled)
14747        {
14748                dbug(1, dprintf("No group optimization"));
14749                return;
14750        }
14751
14752        dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14753
14754        for (i = 0; i < MAX_CIP_TYPES; i++)
14755        {
14756                info_mask_group[i] = 0;
14757                cip_mask_group[i] = 0;
14758        }
14759        for (i = 0; i < MAX_APPL; i++)
14760        {
14761                appl_number_group_type[i] = 0;
14762        }
14763        for (i = 0; i < max_appl; i++) /* check if any multi instance capable application is present */
14764        {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14765                if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14766                {
14767                        dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14768                        return; /* allow good application unfiltered access */
14769                }
14770        }
14771        for (i = 0; i < max_appl; i++) /* Build CIP Groups */
14772        {
14773                if (application[i].Id && a->CIP_Mask[i])
14774                {
14775                        for (k = 0, busy = false; k < a->max_plci; k++)
14776                        {
14777                                if (a->plci[k].Id)
14778                                {
14779                                        auxplci = &a->plci[k];
14780                                        if (auxplci->appl == &application[i]) /* application has a busy PLCI */
14781                                        {
14782                                                busy = true;
14783                                                dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14784                                        }
14785                                        else if (test_c_ind_mask_bit(auxplci, i)) /* application has an incoming call pending */
14786                                        {
14787                                                busy = true;
14788                                                dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14789                                        }
14790                                }
14791                        }
14792
14793                        for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++)     /* build groups with free applications only */
14794                        {
14795                                if (j == MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14796                                {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14797                                        appl_number_group_type[i] = MAX_CIP_TYPES;
14798                                        group_found = true;
14799                                        dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14800                                }
14801                                else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14802                                {                                      /* is group already present ?                  */
14803                                        appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14804                                        group_found = true;
14805                                        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]));
14806                                }
14807                                else if (!info_mask_group[j])
14808                                {                                      /* establish a new group                       */
14809                                        appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14810                                        info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14811                                        cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14812                                        group_found = true;
14813                                        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]));
14814                                }
14815                        }
14816                }
14817        }
14818
14819        for (i = 0; i < max_appl; i++) /* Build group_optimization_mask_table */
14820        {
14821                if (appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14822                {
14823                        if (appl_number_group_type[i] == MAX_CIP_TYPES)
14824                        {
14825                                dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14826                        }
14827                        else
14828                        {
14829                                dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14830                                for (j = i + 1; j < max_appl; j++)   /* search other group members and mark them as busy        */
14831                                {
14832                                        if (appl_number_group_type[i] == appl_number_group_type[j])
14833                                        {
14834                                                dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14835                                                clear_group_ind_mask_bit(plci, j);           /* disable call on other group members */
14836                                                appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14837                                        }
14838                                }
14839                        }
14840                }
14841                else                                                 /* application should not get a call */
14842                {
14843                        clear_group_ind_mask_bit(plci, i);
14844                }
14845        }
14846
14847}
14848
14849
14850
14851/* OS notifies the driver about a application Capi_Register */
14852word CapiRegister(word id)
14853{
14854        word i, j, appls_found;
14855
14856        PLCI *plci;
14857        DIVA_CAPI_ADAPTER *a;
14858
14859        for (i = 0, appls_found = 0; i < max_appl; i++)
14860        {
14861                if (application[i].Id && (application[i].Id != id))
14862                {
14863                        appls_found++;                       /* an application has been found */
14864                }
14865        }
14866
14867        if (appls_found) return true;
14868        for (i = 0; i < max_adapter; i++)                   /* scan all adapters...    */
14869        {
14870                a = &adapter[i];
14871                if (a->request)
14872                {
14873                        if (a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14874                        {
14875                                if (!appls_found)           /* first application does a capi register   */
14876                                {
14877                                        if ((j = get_plci(a)))                    /* activate L1 of all adapters */
14878                                        {
14879                                                plci = &a->plci[j - 1];
14880                                                plci->command = 0;
14881                                                add_p(plci, OAD, "\x01\xfd");
14882                                                add_p(plci, CAI, "\x01\x80");
14883                                                add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14884                                                add_p(plci, SHIFT | 6, NULL);
14885                                                add_p(plci, SIN, "\x02\x00\x00");
14886                                                plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14887                                                sig_req(plci, ASSIGN, DSIG_ID);
14888                                                add_p(plci, FTY, "\x02\xff\x07"); /* l1 start */
14889                                                sig_req(plci, SIG_CTRL, 0);
14890                                                send_req(plci);
14891                                        }
14892                                }
14893                        }
14894                }
14895        }
14896        return false;
14897}
14898
14899/*------------------------------------------------------------------*/
14900
14901/* Functions for virtual Switching e.g. Transfer by join, Conference */
14902
14903static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14904{
14905        word i;
14906        /* Format of vswitch_t:
14907           0 byte length
14908           1 byte VSWITCHIE
14909           2 byte VSWITCH_REQ/VSWITCH_IND
14910           3 byte reserved
14911           4 word VSwitchcommand
14912           6 word returnerror
14913           8... Params
14914        */
14915        if (!plci ||
14916            !plci->appl ||
14917            !plci->State ||
14918            plci->Sig.Ind == NCR_FACILITY
14919                )
14920                return;
14921
14922        for (i = 0; i < MAX_MULTI_IE; i++)
14923        {
14924                if (!parms[i][0]) continue;
14925                if (parms[i][0] < 7)
14926                {
14927                        parms[i][0] = 0; /* kill it */
14928                        continue;
14929                }
14930                dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14931                switch (parms[i][4])
14932                {
14933                case VSJOIN:
14934                        if (!plci->relatedPTYPLCI ||
14935                            (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14936                        { /* Error */
14937                                break;
14938                        }
14939                        /* remember all necessary informations */
14940                        if (parms[i][0] != 11 || parms[i][8] != 3) /* Length Test */
14941                        {
14942                                break;
14943                        }
14944                        if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14945                        {   /* first indication after ECT-Request on Consultation Call */
14946                                plci->vswitchstate = parms[i][9];
14947                                parms[i][9] = 2; /* State */
14948                                /* now ask first Call to join */
14949                        }
14950                        else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14951                        { /* Answer of VSWITCH_REQ from first Call */
14952                                plci->vswitchstate = parms[i][9];
14953                                /* tell consultation call to join
14954                                   and the protocol capabilities of the first call */
14955                        }
14956                        else
14957                        { /* Error */
14958                                break;
14959                        }
14960                        plci->vsprot = parms[i][10]; /* protocol */
14961                        plci->vsprotdialect = parms[i][11]; /* protocoldialect */
14962                        /* send join request to related PLCI */
14963                        parms[i][1] = VSWITCHIE;
14964                        parms[i][2] = VSWITCH_REQ;
14965
14966                        plci->relatedPTYPLCI->command = 0;
14967                        plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14968                        add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14969                        sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14970                        send_req(plci->relatedPTYPLCI);
14971                        break;
14972                case VSTRANSPORT:
14973                default:
14974                        if (plci->relatedPTYPLCI &&
14975                            plci->vswitchstate == 3 &&
14976                            plci->relatedPTYPLCI->vswitchstate == 3)
14977                        {
14978                                add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14979                                sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14980                                send_req(plci->relatedPTYPLCI);
14981                        }
14982                        break;
14983                }
14984                parms[i][0] = 0; /* kill it */
14985        }
14986}
14987
14988
14989/*------------------------------------------------------------------*/
14990
14991static int diva_get_dma_descriptor(PLCI *plci, dword   *dma_magic) {
14992        ENTITY e;
14993        IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14994
14995        if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14996                return (-1);
14997        }
14998
14999        pReq->xdi_dma_descriptor_operation.Req = 0;
15000        pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15001
15002        pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
15003        pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
15004        pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15005        pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15006
15007        e.user[0] = plci->adapter->Id - 1;
15008        plci->adapter->request((ENTITY *)pReq);
15009
15010        if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15011            (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15012            pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15013                *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15014                dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
15015                                plci->adapter->Id,
15016                                pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15017                                *dma_magic));
15018                return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15019        } else {
15020                dbug(1, dprintf("dma_alloc failed"));
15021                return (-1);
15022        }
15023}
15024
15025static void diva_free_dma_descriptor(PLCI *plci, int nr) {
15026        ENTITY e;
15027        IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
15028
15029        if (nr < 0) {
15030                return;
15031        }
15032
15033        pReq->xdi_dma_descriptor_operation.Req = 0;
15034        pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15035
15036        pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15037        pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
15038        pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15039        pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15040
15041        e.user[0] = plci->adapter->Id - 1;
15042        plci->adapter->request((ENTITY *)pReq);
15043
15044        if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15045                dbug(1, dprintf("dma_free(%d)", nr));
15046        } else {
15047                dbug(1, dprintf("dma_free failed (%d)", nr));
15048        }
15049}
15050
15051/*------------------------------------------------------------------*/
15052