GNU Linux-libre 4.14.266-gnu1
[releases.git] / drivers / isdn / hardware / eicon / message.c
1 /*
2  *
3  Copyright (c) Eicon Networks, 2002.
4  *
5  This source file is supplied for the use with
6  Eicon Networks range of DIVA Server Adapters.
7  *
8  Eicon File Revision :    2.1
9  *
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2, or (at your option)
13  any later version.
14  *
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
17  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18  See the GNU General Public License for more details.
19  *
20  You should have received a copy of the GNU General Public License
21  along with this program; if not, write to the Free Software
22  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25
26 #include <linux/bitmap.h>
27
28 #include "platform.h"
29 #include "di_defs.h"
30 #include "pc.h"
31 #include "capi20.h"
32 #include "divacapi.h"
33 #include "mdm_msg.h"
34 #include "divasync.h"
35
36 #define FILE_ "MESSAGE.C"
37 #define dprintf
38
39 /*------------------------------------------------------------------*/
40 /* This is options supported for all adapters that are server by    */
41 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
42 /* and it is not necessary to save it separate for every adapter    */
43 /* Macrose defined here have only local meaning                     */
44 /*------------------------------------------------------------------*/
45 static dword diva_xdi_extended_features = 0;
46
47 #define DIVA_CAPI_USE_CMA                 0x00000001
48 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR  0x00000002
49 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL  0x00000004
50 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA     0x00000008
51
52 /*
53   CAPI can request to process all return codes self only if:
54   protocol code supports this && xdi supports this
55 */
56 #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__)   (((__a__)->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL) && ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) && (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
57
58 /*------------------------------------------------------------------*/
59 /* local function prototypes                                        */
60 /*------------------------------------------------------------------*/
61
62 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci);
63 void AutomaticLaw(DIVA_CAPI_ADAPTER *);
64 word CapiRelease(word);
65 word CapiRegister(word);
66 word api_put(APPL *, CAPI_MSG *);
67 static word api_parse(byte *, word, byte *, API_PARSE *);
68 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out);
69 static void api_load_msg(API_SAVE *in, API_PARSE *out);
70
71 word api_remove_start(void);
72 void api_remove_complete(void);
73
74 static void plci_remove(PLCI *);
75 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a);
76 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *);
77
78 void callback(ENTITY *);
79
80 static void control_rc(PLCI *, byte, byte, byte, byte, byte);
81 static void data_rc(PLCI *, byte);
82 static void data_ack(PLCI *, byte);
83 static void sig_ind(PLCI *);
84 static void SendInfo(PLCI *, dword, byte **, byte);
85 static void SendSetupInfo(APPL *, PLCI *, dword, byte **, byte);
86 static void SendSSExtInd(APPL *, PLCI *plci, dword Id, byte **parms);
87
88 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
89
90 static void nl_ind(PLCI *);
91
92 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
93 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
94 static byte connect_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
95 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
96 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
97 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
98 static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
99 static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
100 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
101 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
102 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
103 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
104 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
105 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
106 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
107 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
108 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
109 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
110 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
111 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
112 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
113 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
114 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
115 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
116
117 static word get_plci(DIVA_CAPI_ADAPTER *);
118 static void add_p(PLCI *, byte, byte *);
119 static void add_s(PLCI *plci, byte code, API_PARSE *p);
120 static void add_ss(PLCI *plci, byte code, API_PARSE *p);
121 static void add_ie(PLCI *plci, byte code, byte *p, word p_length);
122 static void add_d(PLCI *, word, byte *);
123 static void add_ai(PLCI *, API_PARSE *);
124 static word add_b1(PLCI *, API_PARSE *, word, word);
125 static word add_b23(PLCI *, API_PARSE *);
126 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms);
127 static void sig_req(PLCI *, byte, byte);
128 static void nl_req_ncci(PLCI *, byte, byte);
129 static void send_req(PLCI *);
130 static void send_data(PLCI *);
131 static word plci_remove_check(PLCI *);
132 static void listen_check(DIVA_CAPI_ADAPTER *);
133 static byte AddInfo(byte **, byte **, byte *, byte *);
134 static byte getChannel(API_PARSE *);
135 static void IndParse(PLCI *, const word *, byte **, byte);
136 static byte ie_compare(byte *, byte *);
137 static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *);
138 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *, word);
139
140 /*
141   XON protocol helpers
142 */
143 static void channel_flow_control_remove(PLCI *plci);
144 static void channel_x_off(PLCI *plci, byte ch, byte flag);
145 static void channel_x_on(PLCI *plci, byte ch);
146 static void channel_request_xon(PLCI *plci, byte ch);
147 static void channel_xmit_xon(PLCI *plci);
148 static int channel_can_xon(PLCI *plci, byte ch);
149 static void channel_xmit_extended_xon(PLCI *plci);
150
151 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type, dword info_mask, byte setupParse);
152 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte);
153 static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *);
154 static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER *);
155 static void VoiceChannelOff(PLCI *plci);
156 static void adv_voice_write_coefs(PLCI *plci, word write_command);
157 static void adv_voice_clear_config(PLCI *plci);
158
159 static word get_b1_facilities(PLCI *plci, byte b1_resource);
160 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities);
161 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities);
162 static word adjust_b_process(dword Id, PLCI *plci, byte Rc);
163 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command);
164 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc);
165 static void reset_b3_command(dword Id, PLCI *plci, byte Rc);
166 static void select_b_command(dword Id, PLCI *plci, byte Rc);
167 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc);
168 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc);
169 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc);
170 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc);
171 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc);
172 static void hold_save_command(dword Id, PLCI *plci, byte Rc);
173 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc);
174 static void init_b1_config(PLCI *plci);
175 static void clear_b1_config(PLCI *plci);
176
177 static void dtmf_command(dword Id, PLCI *plci, byte Rc);
178 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
179 static void dtmf_confirmation(dword Id, PLCI *plci);
180 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length);
181 static void dtmf_parameter_write(PLCI *plci);
182
183
184 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id);
185 static void mixer_set_bchannel_id(PLCI *plci, byte *chi);
186 static void mixer_clear_config(PLCI *plci);
187 static void mixer_notify_update(PLCI *plci, byte others);
188 static void mixer_command(dword Id, PLCI *plci, byte Rc);
189 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
190 static void mixer_indication_coefs_set(dword Id, PLCI *plci);
191 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length);
192 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length);
193 static void mixer_remove(PLCI *plci);
194
195
196 static void ec_command(dword Id, PLCI *plci, byte Rc);
197 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
198 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length);
199
200
201 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc);
202 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc);
203
204
205 static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic);
206 static void diva_free_dma_descriptor(PLCI *plci, int nr);
207
208 /*------------------------------------------------------------------*/
209 /* external function prototypes                                     */
210 /*------------------------------------------------------------------*/
211
212 extern byte MapController(byte);
213 extern byte UnMapController(byte);
214 #define MapId(Id)(((Id) & 0xffffff00L) | MapController((byte)(Id)))
215 #define UnMapId(Id)(((Id) & 0xffffff00L) | UnMapController((byte)(Id)))
216
217 void sendf(APPL *, word, dword, word, byte *, ...);
218 void *TransmitBufferSet(APPL *appl, dword ref);
219 void *TransmitBufferGet(APPL *appl, void *p);
220 void TransmitBufferFree(APPL *appl, void *p);
221 void *ReceiveBufferGet(APPL *appl, int Num);
222
223 int fax_head_line_time(char *buffer);
224
225
226 /*------------------------------------------------------------------*/
227 /* Global data definitions                                          */
228 /*------------------------------------------------------------------*/
229 extern byte max_adapter;
230 extern byte max_appl;
231 extern DIVA_CAPI_ADAPTER *adapter;
232 extern APPL *application;
233
234
235
236
237
238
239
240 static byte remove_started = false;
241 static PLCI dummy_plci;
242
243
244 static struct _ftable {
245         word command;
246         byte *format;
247         byte (*function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
248 } ftable[] = {
249         {_DATA_B3_R,                          "dwww",         data_b3_req},
250         {_DATA_B3_I | RESPONSE,               "w",            data_b3_res},
251         {_INFO_R,                             "ss",           info_req},
252         {_INFO_I | RESPONSE,                  "",             info_res},
253         {_CONNECT_R,                          "wsssssssss",   connect_req},
254         {_CONNECT_I | RESPONSE,               "wsssss",       connect_res},
255         {_CONNECT_ACTIVE_I | RESPONSE,        "",             connect_a_res},
256         {_DISCONNECT_R,                       "s",            disconnect_req},
257         {_DISCONNECT_I | RESPONSE,            "",             disconnect_res},
258         {_LISTEN_R,                           "dddss",        listen_req},
259         {_ALERT_R,                            "s",            alert_req},
260         {_FACILITY_R,                         "ws",           facility_req},
261         {_FACILITY_I | RESPONSE,              "ws",           facility_res},
262         {_CONNECT_B3_R,                       "s",            connect_b3_req},
263         {_CONNECT_B3_I | RESPONSE,            "ws",           connect_b3_res},
264         {_CONNECT_B3_ACTIVE_I | RESPONSE,     "",             connect_b3_a_res},
265         {_DISCONNECT_B3_R,                    "s",            disconnect_b3_req},
266         {_DISCONNECT_B3_I | RESPONSE,         "",             disconnect_b3_res},
267         {_RESET_B3_R,                         "s",            reset_b3_req},
268         {_RESET_B3_I | RESPONSE,              "",             reset_b3_res},
269         {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "ws",           connect_b3_t90_a_res},
270         {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "",             connect_b3_t90_a_res},
271         {_SELECT_B_REQ,                       "s",            select_b_req},
272         {_MANUFACTURER_R,                     "dws",          manufacturer_req},
273         {_MANUFACTURER_I | RESPONSE,          "dws",          manufacturer_res},
274         {_MANUFACTURER_I | RESPONSE,          "",             manufacturer_res}
275 };
276
277 static byte *cip_bc[29][2] = {
278         { "",                     ""                     }, /* 0 */
279         { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 1 */
280         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 2 */
281         { "\x02\x89\x90",         "\x02\x89\x90"         }, /* 3 */
282         { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 4 */
283         { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 5 */
284         { "\x02\x98\x90",         "\x02\x98\x90"         }, /* 6 */
285         { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
286         { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
287         { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 9 */
288         { "",                     ""                     }, /* 10 */
289         { "",                     ""                     }, /* 11 */
290         { "",                     ""                     }, /* 12 */
291         { "",                     ""                     }, /* 13 */
292         { "",                     ""                     }, /* 14 */
293         { "",                     ""                     }, /* 15 */
294
295         { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 16 */
296         { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 17 */
297         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 18 */
298         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 19 */
299         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 20 */
300         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 21 */
301         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 22 */
302         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 23 */
303         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 24 */
304         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 25 */
305         { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 26 */
306         { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 27 */
307         { "\x02\x88\x90",         "\x02\x88\x90"         }  /* 28 */
308 };
309
310 static byte *cip_hlc[29] = {
311         "",                           /* 0 */
312         "",                           /* 1 */
313         "",                           /* 2 */
314         "",                           /* 3 */
315         "",                           /* 4 */
316         "",                           /* 5 */
317         "",                           /* 6 */
318         "",                           /* 7 */
319         "",                           /* 8 */
320         "",                           /* 9 */
321         "",                           /* 10 */
322         "",                           /* 11 */
323         "",                           /* 12 */
324         "",                           /* 13 */
325         "",                           /* 14 */
326         "",                           /* 15 */
327
328         "\x02\x91\x81",               /* 16 */
329         "\x02\x91\x84",               /* 17 */
330         "\x02\x91\xa1",               /* 18 */
331         "\x02\x91\xa4",               /* 19 */
332         "\x02\x91\xa8",               /* 20 */
333         "\x02\x91\xb1",               /* 21 */
334         "\x02\x91\xb2",               /* 22 */
335         "\x02\x91\xb5",               /* 23 */
336         "\x02\x91\xb8",               /* 24 */
337         "\x02\x91\xc1",               /* 25 */
338         "\x02\x91\x81",               /* 26 */
339         "\x03\x91\xe0\x01",           /* 27 */
340         "\x03\x91\xe0\x02"            /* 28 */
341 };
342
343 /*------------------------------------------------------------------*/
344
345 #define V120_HEADER_LENGTH 1
346 #define V120_HEADER_EXTEND_BIT  0x80
347 #define V120_HEADER_BREAK_BIT   0x40
348 #define V120_HEADER_C1_BIT      0x04
349 #define V120_HEADER_C2_BIT      0x08
350 #define V120_HEADER_FLUSH_COND  (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
351
352 static byte v120_default_header[] =
353 {
354
355         0x83                          /*  Ext, BR , res, res, C2 , C1 , B  , F   */
356
357 };
358
359 static byte v120_break_header[] =
360 {
361
362         0xc3 | V120_HEADER_BREAK_BIT  /*  Ext, BR , res, res, C2 , C1 , B  , F   */
363
364 };
365
366
367 /*------------------------------------------------------------------*/
368 /* API_PUT function                                                 */
369 /*------------------------------------------------------------------*/
370
371 word api_put(APPL *appl, CAPI_MSG *msg)
372 {
373         word i, j, k, l, n;
374         word ret;
375         byte c;
376         byte controller;
377         DIVA_CAPI_ADAPTER *a;
378         PLCI *plci;
379         NCCI *ncci_ptr;
380         word ncci;
381         CAPI_MSG *m;
382         API_PARSE msg_parms[MAX_MSG_PARMS + 1];
383
384         if (msg->header.length < sizeof(msg->header) ||
385             msg->header.length > MAX_MSG_SIZE) {
386                 dbug(1, dprintf("bad len"));
387                 return _BAD_MSG;
388         }
389
390         controller = (byte)((msg->header.controller & 0x7f) - 1);
391
392         /* controller starts with 0 up to (max_adapter - 1) */
393         if (controller >= max_adapter)
394         {
395                 dbug(1, dprintf("invalid ctrl"));
396                 return _BAD_MSG;
397         }
398
399         a = &adapter[controller];
400         plci = NULL;
401         if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
402         {
403                 dbug(1, dprintf("plci=%x", msg->header.plci));
404                 plci = &a->plci[msg->header.plci - 1];
405                 ncci = GET_WORD(&msg->header.ncci);
406                 if (plci->Id
407                     && (plci->appl
408                         || (plci->State == INC_CON_PENDING)
409                         || (plci->State == INC_CON_ALERT)
410                         || (msg->header.command == (_DISCONNECT_I | RESPONSE)))
411                     && ((ncci == 0)
412                         || (msg->header.command == (_DISCONNECT_B3_I | RESPONSE))
413                         || ((ncci < MAX_NCCI + 1) && (a->ncci_plci[ncci] == plci->Id))))
414                 {
415                         i = plci->msg_in_read_pos;
416                         j = plci->msg_in_write_pos;
417                         if (j >= i)
418                         {
419                                 if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
420                                         i += MSG_IN_QUEUE_SIZE - j;
421                                 else
422                                         j = 0;
423                         }
424                         else
425                         {
426
427                                 n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
428
429                                 if (i > MSG_IN_QUEUE_SIZE - n)
430                                         i = MSG_IN_QUEUE_SIZE - n + 1;
431                                 i -= j;
432                         }
433
434                         if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
435
436                         {
437                                 dbug(0, dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
438                                                 msg->header.length, plci->msg_in_write_pos,
439                                                 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
440
441                                 return _QUEUE_FULL;
442                         }
443                         c = false;
444                         if ((((byte *) msg) < ((byte *)(plci->msg_in_queue)))
445                             || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
446                         {
447                                 if (plci->msg_in_write_pos != plci->msg_in_read_pos)
448                                         c = true;
449                         }
450                         if (msg->header.command == _DATA_B3_R)
451                         {
452                                 if (msg->header.length < 20)
453                                 {
454                                         dbug(1, dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
455                                         return _BAD_MSG;
456                                 }
457                                 ncci_ptr = &(a->ncci[ncci]);
458                                 n = ncci_ptr->data_pending;
459                                 l = ncci_ptr->data_ack_pending;
460                                 k = plci->msg_in_read_pos;
461                                 while (k != plci->msg_in_write_pos)
462                                 {
463                                         if (k == plci->msg_in_wrap_pos)
464                                                 k = 0;
465                                         if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
466                                             && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
467                                         {
468                                                 n++;
469                                                 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
470                                                         l++;
471                                         }
472
473                                         k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
474                                               MSG_IN_OVERHEAD + 3) & 0xfffc;
475
476                                 }
477                                 if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
478                                 {
479                                         dbug(0, dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
480                                                         ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
481
482                                         return _QUEUE_FULL;
483                                 }
484                                 if (plci->req_in || plci->internal_command)
485                                 {
486                                         if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
487                                             && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
488                                         {
489                                                 dbug(0, dprintf("Q-FULL3(requeue)"));
490
491                                                 return _QUEUE_FULL;
492                                         }
493                                         c = true;
494                                 }
495                         }
496                         else
497                         {
498                                 if (plci->req_in || plci->internal_command)
499                                         c = true;
500                                 else
501                                 {
502                                         plci->command = msg->header.command;
503                                         plci->number = msg->header.number;
504                                 }
505                         }
506                         if (c)
507                         {
508                                 dbug(1, dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
509                                                 msg->header.command, plci->req_in, plci->internal_command,
510                                                 msg->header.length, plci->msg_in_write_pos,
511                                                 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
512                                 if (j == 0)
513                                         plci->msg_in_wrap_pos = plci->msg_in_write_pos;
514                                 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
515                                 for (i = 0; i < msg->header.length; i++)
516                                         ((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i];
517                                 if (m->header.command == _DATA_B3_R)
518                                 {
519
520                                         m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet(appl, m->info.data_b3_req.Data));
521
522                                 }
523
524                                 j = (j + 3) & 0xfffc;
525
526                                 *((APPL **)(&((byte *)(plci->msg_in_queue))[j])) = appl;
527                                 plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
528                                 return 0;
529                         }
530                 }
531                 else
532                 {
533                         plci = NULL;
534                 }
535         }
536         dbug(1, dprintf("com=%x", msg->header.command));
537
538         for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
539         for (i = 0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
540
541                 if (ftable[i].command == msg->header.command) {
542                         /* break loop if the message is correct, otherwise continue scan  */
543                         /* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */
544                         if (!api_parse(msg->info.b, (word)(msg->header.length - 12), ftable[i].format, msg_parms)) {
545                                 ret = 0;
546                                 break;
547                         }
548                         for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
549                 }
550         }
551         if (ret) {
552                 dbug(1, dprintf("BAD_MSG"));
553                 if (plci) plci->command = 0;
554                 return ret;
555         }
556
557
558         c = ftable[i].function(GET_DWORD(&msg->header.controller),
559                                msg->header.number,
560                                a,
561                                plci,
562                                appl,
563                                msg_parms);
564
565         channel_xmit_extended_xon(plci);
566
567         if (c == 1) send_req(plci);
568         if (c == 2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
569         if (plci && !plci->req_in) plci->command = 0;
570         return 0;
571 }
572
573
574 /*------------------------------------------------------------------*/
575 /* api_parse function, check the format of api messages             */
576 /*------------------------------------------------------------------*/
577
578 static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
579 {
580         word i;
581         word p;
582
583         for (i = 0, p = 0; format[i]; i++) {
584                 if (parms)
585                 {
586                         parms[i].info = &msg[p];
587                 }
588                 switch (format[i]) {
589                 case 'b':
590                         p += 1;
591                         break;
592                 case 'w':
593                         p += 2;
594                         break;
595                 case 'd':
596                         p += 4;
597                         break;
598                 case 's':
599                         if (msg[p] == 0xff) {
600                                 parms[i].info += 2;
601                                 parms[i].length = msg[p + 1] + (msg[p + 2] << 8);
602                                 p += (parms[i].length + 3);
603                         }
604                         else {
605                                 parms[i].length = msg[p];
606                                 p += (parms[i].length + 1);
607                         }
608                         break;
609                 }
610
611                 if (p > length) return true;
612         }
613         if (parms) parms[i].info = NULL;
614         return false;
615 }
616
617 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
618 {
619         word i, j, n = 0;
620         byte *p;
621
622         p = out->info;
623         for (i = 0; format[i] != '\0'; i++)
624         {
625                 out->parms[i].info = p;
626                 out->parms[i].length = in[i].length;
627                 switch (format[i])
628                 {
629                 case 'b':
630                         n = 1;
631                         break;
632                 case 'w':
633                         n = 2;
634                         break;
635                 case 'd':
636                         n = 4;
637                         break;
638                 case 's':
639                         n = in[i].length + 1;
640                         break;
641                 }
642                 for (j = 0; j < n; j++)
643                         *(p++) = in[i].info[j];
644         }
645         out->parms[i].info = NULL;
646         out->parms[i].length = 0;
647 }
648
649 static void api_load_msg(API_SAVE *in, API_PARSE *out)
650 {
651         word i;
652
653         i = 0;
654         do
655         {
656                 out[i].info = in->parms[i].info;
657                 out[i].length = in->parms[i].length;
658         } while (in->parms[i++].info);
659 }
660
661
662 /*------------------------------------------------------------------*/
663 /* CAPI remove function                                             */
664 /*------------------------------------------------------------------*/
665
666 word api_remove_start(void)
667 {
668         word i;
669         word j;
670
671         if (!remove_started) {
672                 remove_started = true;
673                 for (i = 0; i < max_adapter; i++) {
674                         if (adapter[i].request) {
675                                 for (j = 0; j < adapter[i].max_plci; j++) {
676                                         if (adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
677                                 }
678                         }
679                 }
680                 return 1;
681         }
682         else {
683                 for (i = 0; i < max_adapter; i++) {
684                         if (adapter[i].request) {
685                                 for (j = 0; j < adapter[i].max_plci; j++) {
686                                         if (adapter[i].plci[j].Sig.Id) return 1;
687                                 }
688                         }
689                 }
690         }
691         api_remove_complete();
692         return 0;
693 }
694
695
696 /*------------------------------------------------------------------*/
697 /* internal command queue                                           */
698 /*------------------------------------------------------------------*/
699
700 static void init_internal_command_queue(PLCI *plci)
701 {
702         word i;
703
704         dbug(1, dprintf("%s,%d: init_internal_command_queue",
705                         (char *)(FILE_), __LINE__));
706
707         plci->internal_command = 0;
708         for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
709                 plci->internal_command_queue[i] = NULL;
710 }
711
712
713 static void start_internal_command(dword Id, PLCI *plci, t_std_internal_command command_function)
714 {
715         word i;
716
717         dbug(1, dprintf("[%06lx] %s,%d: start_internal_command",
718                         UnMapId(Id), (char *)(FILE_), __LINE__));
719
720         if (plci->internal_command == 0)
721         {
722                 plci->internal_command_queue[0] = command_function;
723                 (*command_function)(Id, plci, OK);
724         }
725         else
726         {
727                 i = 1;
728                 while (plci->internal_command_queue[i] != NULL)
729                         i++;
730                 plci->internal_command_queue[i] = command_function;
731         }
732 }
733
734
735 static void next_internal_command(dword Id, PLCI *plci)
736 {
737         word i;
738
739         dbug(1, dprintf("[%06lx] %s,%d: next_internal_command",
740                         UnMapId(Id), (char *)(FILE_), __LINE__));
741
742         plci->internal_command = 0;
743         plci->internal_command_queue[0] = NULL;
744         while (plci->internal_command_queue[1] != NULL)
745         {
746                 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
747                         plci->internal_command_queue[i] = plci->internal_command_queue[i + 1];
748                 plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
749                 (*(plci->internal_command_queue[0]))(Id, plci, OK);
750                 if (plci->internal_command != 0)
751                         return;
752                 plci->internal_command_queue[0] = NULL;
753         }
754 }
755
756
757 /*------------------------------------------------------------------*/
758 /* NCCI allocate/remove function                                    */
759 /*------------------------------------------------------------------*/
760
761 static dword ncci_mapping_bug = 0;
762
763 static word get_ncci(PLCI *plci, byte ch, word force_ncci)
764 {
765         DIVA_CAPI_ADAPTER *a;
766         word ncci, i, j, k;
767
768         a = plci->adapter;
769         if (!ch || a->ch_ncci[ch])
770         {
771                 ncci_mapping_bug++;
772                 dbug(1, dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
773                                 ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
774                 ncci = ch;
775         }
776         else
777         {
778                 if (force_ncci)
779                         ncci = force_ncci;
780                 else
781                 {
782                         if ((ch < MAX_NCCI + 1) && !a->ncci_ch[ch])
783                                 ncci = ch;
784                         else
785                         {
786                                 ncci = 1;
787                                 while ((ncci < MAX_NCCI + 1) && a->ncci_ch[ncci])
788                                         ncci++;
789                                 if (ncci == MAX_NCCI + 1)
790                                 {
791                                         ncci_mapping_bug++;
792                                         i = 1;
793                                         do
794                                         {
795                                                 j = 1;
796                                                 while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i))
797                                                         j++;
798                                                 k = j;
799                                                 if (j < MAX_NCCI + 1)
800                                                 {
801                                                         do
802                                                         {
803                                                                 j++;
804                                                         } while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i));
805                                                 }
806                                         } while ((i < MAX_NL_CHANNEL + 1) && (j < MAX_NCCI + 1));
807                                         if (i < MAX_NL_CHANNEL + 1)
808                                         {
809                                                 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
810                                                                 ncci_mapping_bug, ch, force_ncci, i, k, j));
811                                         }
812                                         else
813                                         {
814                                                 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x",
815                                                                 ncci_mapping_bug, ch, force_ncci));
816                                         }
817                                         ncci = ch;
818                                 }
819                         }
820                         a->ncci_plci[ncci] = plci->Id;
821                         a->ncci_state[ncci] = IDLE;
822                         if (!plci->ncci_ring_list)
823                                 plci->ncci_ring_list = ncci;
824                         else
825                                 a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
826                         a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
827                 }
828                 a->ncci_ch[ncci] = ch;
829                 a->ch_ncci[ch] = (byte) ncci;
830                 dbug(1, dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
831                                 ncci_mapping_bug, ch, force_ncci, ch, ncci));
832         }
833         return (ncci);
834 }
835
836
837 static void ncci_free_receive_buffers(PLCI *plci, word ncci)
838 {
839         DIVA_CAPI_ADAPTER *a;
840         APPL *appl;
841         word i, ncci_code;
842         dword Id;
843
844         a = plci->adapter;
845         Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
846         if (ncci)
847         {
848                 if (a->ncci_plci[ncci] == plci->Id)
849                 {
850                         if (!plci->appl)
851                         {
852                                 ncci_mapping_bug++;
853                                 dbug(1, dprintf("NCCI mapping appl expected %ld %08lx",
854                                                 ncci_mapping_bug, Id));
855                         }
856                         else
857                         {
858                                 appl = plci->appl;
859                                 ncci_code = ncci | (((word) a->Id) << 8);
860                                 for (i = 0; i < appl->MaxBuffer; i++)
861                                 {
862                                         if ((appl->DataNCCI[i] == ncci_code)
863                                             && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
864                                         {
865                                                 appl->DataNCCI[i] = 0;
866                                         }
867                                 }
868                         }
869                 }
870         }
871         else
872         {
873                 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
874                 {
875                         if (a->ncci_plci[ncci] == plci->Id)
876                         {
877                                 if (!plci->appl)
878                                 {
879                                         ncci_mapping_bug++;
880                                         dbug(1, dprintf("NCCI mapping no appl %ld %08lx",
881                                                         ncci_mapping_bug, Id));
882                                 }
883                                 else
884                                 {
885                                         appl = plci->appl;
886                                         ncci_code = ncci | (((word) a->Id) << 8);
887                                         for (i = 0; i < appl->MaxBuffer; i++)
888                                         {
889                                                 if ((appl->DataNCCI[i] == ncci_code)
890                                                     && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
891                                                 {
892                                                         appl->DataNCCI[i] = 0;
893                                                 }
894                                         }
895                                 }
896                         }
897                 }
898         }
899 }
900
901
902 static void cleanup_ncci_data(PLCI *plci, word ncci)
903 {
904         NCCI *ncci_ptr;
905
906         if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
907         {
908                 ncci_ptr = &(plci->adapter->ncci[ncci]);
909                 if (plci->appl)
910                 {
911                         while (ncci_ptr->data_pending != 0)
912                         {
913                                 if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
914                                         TransmitBufferFree(plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
915                                 (ncci_ptr->data_out)++;
916                                 if (ncci_ptr->data_out == MAX_DATA_B3)
917                                         ncci_ptr->data_out = 0;
918                                 (ncci_ptr->data_pending)--;
919                         }
920                 }
921                 ncci_ptr->data_out = 0;
922                 ncci_ptr->data_pending = 0;
923                 ncci_ptr->data_ack_out = 0;
924                 ncci_ptr->data_ack_pending = 0;
925         }
926 }
927
928
929 static void ncci_remove(PLCI *plci, word ncci, byte preserve_ncci)
930 {
931         DIVA_CAPI_ADAPTER *a;
932         dword Id;
933         word i;
934
935         a = plci->adapter;
936         Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
937         if (!preserve_ncci)
938                 ncci_free_receive_buffers(plci, ncci);
939         if (ncci)
940         {
941                 if (a->ncci_plci[ncci] != plci->Id)
942                 {
943                         ncci_mapping_bug++;
944                         dbug(1, dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
945                                         ncci_mapping_bug, Id, preserve_ncci));
946                 }
947                 else
948                 {
949                         cleanup_ncci_data(plci, ncci);
950                         dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
951                                         ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
952                         a->ch_ncci[a->ncci_ch[ncci]] = 0;
953                         if (!preserve_ncci)
954                         {
955                                 a->ncci_ch[ncci] = 0;
956                                 a->ncci_plci[ncci] = 0;
957                                 a->ncci_state[ncci] = IDLE;
958                                 i = plci->ncci_ring_list;
959                                 while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
960                                         i = a->ncci_next[i];
961                                 if ((i != 0) && (a->ncci_next[i] == ncci))
962                                 {
963                                         if (i == ncci)
964                                                 plci->ncci_ring_list = 0;
965                                         else if (plci->ncci_ring_list == ncci)
966                                                 plci->ncci_ring_list = i;
967                                         a->ncci_next[i] = a->ncci_next[ncci];
968                                 }
969                                 a->ncci_next[ncci] = 0;
970                         }
971                 }
972         }
973         else
974         {
975                 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
976                 {
977                         if (a->ncci_plci[ncci] == plci->Id)
978                         {
979                                 cleanup_ncci_data(plci, ncci);
980                                 dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
981                                                 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
982                                 a->ch_ncci[a->ncci_ch[ncci]] = 0;
983                                 if (!preserve_ncci)
984                                 {
985                                         a->ncci_ch[ncci] = 0;
986                                         a->ncci_plci[ncci] = 0;
987                                         a->ncci_state[ncci] = IDLE;
988                                         a->ncci_next[ncci] = 0;
989                                 }
990                         }
991                 }
992                 if (!preserve_ncci)
993                         plci->ncci_ring_list = 0;
994         }
995 }
996
997
998 /*------------------------------------------------------------------*/
999 /* PLCI remove function                                             */
1000 /*------------------------------------------------------------------*/
1001
1002 static void plci_free_msg_in_queue(PLCI *plci)
1003 {
1004         word i;
1005
1006         if (plci->appl)
1007         {
1008                 i = plci->msg_in_read_pos;
1009                 while (i != plci->msg_in_write_pos)
1010                 {
1011                         if (i == plci->msg_in_wrap_pos)
1012                                 i = 0;
1013                         if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1014                         {
1015
1016                                 TransmitBufferFree(plci->appl,
1017                                                    (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1018
1019                         }
1020
1021                         i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1022                               MSG_IN_OVERHEAD + 3) & 0xfffc;
1023
1024                 }
1025         }
1026         plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1027         plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1028         plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1029 }
1030
1031
1032 static void plci_remove(PLCI *plci)
1033 {
1034
1035         if (!plci) {
1036                 dbug(1, dprintf("plci_remove(no plci)"));
1037                 return;
1038         }
1039         init_internal_command_queue(plci);
1040         dbug(1, dprintf("plci_remove(%x,tel=%x)", plci->Id, plci->tel));
1041         if (plci_remove_check(plci))
1042         {
1043                 return;
1044         }
1045         if (plci->Sig.Id == 0xff)
1046         {
1047                 dbug(1, dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1048                 if (plci->NL.Id && !plci->nl_remove_id)
1049                 {
1050                         nl_req_ncci(plci, REMOVE, 0);
1051                         send_req(plci);
1052                 }
1053         }
1054         else
1055         {
1056                 if (!plci->sig_remove_id
1057                     && (plci->Sig.Id
1058                         || (plci->req_in != plci->req_out)
1059                         || (plci->nl_req || plci->sig_req)))
1060                 {
1061                         sig_req(plci, HANGUP, 0);
1062                         send_req(plci);
1063                 }
1064         }
1065         ncci_remove(plci, 0, false);
1066         plci_free_msg_in_queue(plci);
1067
1068         plci->channels = 0;
1069         plci->appl = NULL;
1070         if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1071                 plci->State = OUTG_DIS_PENDING;
1072 }
1073
1074 /*------------------------------------------------------------------*/
1075 /* translation function for each message                            */
1076 /*------------------------------------------------------------------*/
1077
1078 static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1079                         PLCI *plci, APPL *appl, API_PARSE *parms)
1080 {
1081         word ch;
1082         word i;
1083         word Info;
1084         byte LinkLayer;
1085         API_PARSE *ai;
1086         API_PARSE *bp;
1087         API_PARSE ai_parms[5];
1088         word channel = 0;
1089         dword ch_mask;
1090         byte m;
1091         static byte esc_chi[35] = {0x02, 0x18, 0x01};
1092         static byte lli[2] = {0x01, 0x00};
1093         byte noCh = 0;
1094         word dir = 0;
1095         byte *p_chi = "";
1096
1097         for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1098
1099         dbug(1, dprintf("connect_req(%d)", parms->length));
1100         Info = _WRONG_IDENTIFIER;
1101         if (a)
1102         {
1103                 if (a->adapter_disabled)
1104                 {
1105                         dbug(1, dprintf("adapter disabled"));
1106                         Id = ((word)1 << 8) | a->Id;
1107                         sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
1108                         sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1109                         return false;
1110                 }
1111                 Info = _OUT_OF_PLCI;
1112                 if ((i = get_plci(a)))
1113                 {
1114                         Info = 0;
1115                         plci = &a->plci[i - 1];
1116                         plci->appl = appl;
1117                         plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1118                         /* check 'external controller' bit for codec support */
1119                         if (Id & EXT_CONTROLLER)
1120                         {
1121                                 if (AdvCodecSupport(a, plci, appl, 0))
1122                                 {
1123                                         plci->Id = 0;
1124                                         sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1125                                         return 2;
1126                                 }
1127                         }
1128                         ai = &parms[9];
1129                         bp = &parms[5];
1130                         ch = 0;
1131                         if (bp->length)LinkLayer = bp->info[3];
1132                         else LinkLayer = 0;
1133                         if (ai->length)
1134                         {
1135                                 ch = 0xffff;
1136                                 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1137                                 {
1138                                         ch = 0;
1139                                         if (ai_parms[0].length)
1140                                         {
1141                                                 ch = GET_WORD(ai_parms[0].info + 1);
1142                                                 if (ch > 4) ch = 0; /* safety -> ignore ChannelID */
1143                                                 if (ch == 4) /* explizit CHI in message */
1144                                                 {
1145                                                         /* check length of B-CH struct */
1146                                                         if ((ai_parms[0].info)[3] >= 1)
1147                                                         {
1148                                                                 if ((ai_parms[0].info)[4] == CHI)
1149                                                                 {
1150                                                                         p_chi = &((ai_parms[0].info)[5]);
1151                                                                 }
1152                                                                 else
1153                                                                 {
1154                                                                         p_chi = &((ai_parms[0].info)[3]);
1155                                                                 }
1156                                                                 if (p_chi[0] > 35) /* check length of channel ID */
1157                                                                 {
1158                                                                         Info = _WRONG_MESSAGE_FORMAT;
1159                                                                 }
1160                                                         }
1161                                                         else Info = _WRONG_MESSAGE_FORMAT;
1162                                                 }
1163
1164                                                 if (ch == 3 && ai_parms[0].length >= 7 && ai_parms[0].length <= 36)
1165                                                 {
1166                                                         dir = GET_WORD(ai_parms[0].info + 3);
1167                                                         ch_mask = 0;
1168                                                         m = 0x3f;
1169                                                         for (i = 0; i + 5 <= ai_parms[0].length; i++)
1170                                                         {
1171                                                                 if (ai_parms[0].info[i + 5] != 0)
1172                                                                 {
1173                                                                         if ((ai_parms[0].info[i + 5] | m) != 0xff)
1174                                                                                 Info = _WRONG_MESSAGE_FORMAT;
1175                                                                         else
1176                                                                         {
1177                                                                                 if (ch_mask == 0)
1178                                                                                         channel = i;
1179                                                                                 ch_mask |= 1L << i;
1180                                                                         }
1181                                                                 }
1182                                                                 m = 0;
1183                                                         }
1184                                                         if (ch_mask == 0)
1185                                                                 Info = _WRONG_MESSAGE_FORMAT;
1186                                                         if (!Info)
1187                                                         {
1188                                                                 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1189                                                                 {
1190                                                                         esc_chi[0] = (byte)(ai_parms[0].length - 2);
1191                                                                         for (i = 0; i + 5 <= ai_parms[0].length; i++)
1192                                                                                 esc_chi[i + 3] = ai_parms[0].info[i + 5];
1193                                                                 }
1194                                                                 else
1195                                                                         esc_chi[0] = 2;
1196                                                                 esc_chi[2] = (byte)channel;
1197                                                                 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1198                                                                 add_p(plci, LLI, lli);
1199                                                                 add_p(plci, ESC, esc_chi);
1200                                                                 plci->State = LOCAL_CONNECT;
1201                                                                 if (!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
1202                                                         }
1203                                                 }
1204                                         }
1205                                 }
1206                                 else  Info = _WRONG_MESSAGE_FORMAT;
1207                         }
1208
1209                         dbug(1, dprintf("ch=%x,dir=%x,p_ch=%d", ch, dir, channel));
1210                         plci->command = _CONNECT_R;
1211                         plci->number = Number;
1212                         /* x.31 or D-ch free SAPI in LinkLayer? */
1213                         if (ch == 1 && LinkLayer != 3 && LinkLayer != 12) noCh = true;
1214                         if ((ch == 0 || ch == 2 || noCh || ch == 3 || ch == 4) && !Info)
1215                         {
1216                                 /* B-channel used for B3 connections (ch==0), or no B channel    */
1217                                 /* is used (ch==2) or perm. connection (3) is used  do a CALL    */
1218                                 if (noCh) Info = add_b1(plci, &parms[5], 2, 0);    /* no resource    */
1219                                 else     Info = add_b1(plci, &parms[5], ch, 0);
1220                                 add_s(plci, OAD, &parms[2]);
1221                                 add_s(plci, OSA, &parms[4]);
1222                                 add_s(plci, BC, &parms[6]);
1223                                 add_s(plci, LLC, &parms[7]);
1224                                 add_s(plci, HLC, &parms[8]);
1225                                 if (a->Info_Mask[appl->Id - 1] & 0x200)
1226                                 {
1227                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
1228                                         add_p(plci, LLI, "\x01\x01");
1229                                 }
1230                                 if (GET_WORD(parms[0].info) < 29) {
1231                                         add_p(plci, BC, cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1232                                         add_p(plci, HLC, cip_hlc[GET_WORD(parms[0].info)]);
1233                                 }
1234                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1235                                 sig_req(plci, ASSIGN, DSIG_ID);
1236                         }
1237                         else if (ch == 1) {
1238
1239                                 /* D-Channel used for B3 connections */
1240                                 plci->Sig.Id = 0xff;
1241                                 Info = 0;
1242                         }
1243
1244                         if (!Info && ch != 2 && !noCh) {
1245                                 Info = add_b23(plci, &parms[5]);
1246                                 if (!Info) {
1247                                         if (!(plci->tel && !plci->adv_nl))nl_req_ncci(plci, ASSIGN, 0);
1248                                 }
1249                         }
1250
1251                         if (!Info)
1252                         {
1253                                 if (ch == 0 || ch == 2 || ch == 3 || noCh || ch == 4)
1254                                 {
1255                                         if (plci->spoofed_msg == SPOOFING_REQUIRED)
1256                                         {
1257                                                 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1258                                                 plci->spoofed_msg = CALL_REQ;
1259                                                 plci->internal_command = BLOCK_PLCI;
1260                                                 plci->command = 0;
1261                                                 dbug(1, dprintf("Spoof"));
1262                                                 send_req(plci);
1263                                                 return false;
1264                                         }
1265                                         if (ch == 4)add_p(plci, CHI, p_chi);
1266                                         add_s(plci, CPN, &parms[1]);
1267                                         add_s(plci, DSA, &parms[3]);
1268                                         if (noCh) add_p(plci, ESC, "\x02\x18\xfd");  /* D-channel, no B-L3 */
1269                                         add_ai(plci, &parms[9]);
1270                                         if (!dir)sig_req(plci, CALL_REQ, 0);
1271                                         else
1272                                         {
1273                                                 plci->command = PERM_LIST_REQ;
1274                                                 plci->appl = appl;
1275                                                 sig_req(plci, LISTEN_REQ, 0);
1276                                                 send_req(plci);
1277                                                 return false;
1278                                         }
1279                                 }
1280                                 send_req(plci);
1281                                 return false;
1282                         }
1283                         plci->Id = 0;
1284                 }
1285         }
1286         sendf(appl,
1287               _CONNECT_R | CONFIRM,
1288               Id,
1289               Number,
1290               "w", Info);
1291         return 2;
1292 }
1293
1294 static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1295                         PLCI *plci, APPL *appl, API_PARSE *parms)
1296 {
1297         word i, Info;
1298         word Reject;
1299         static byte cau_t[] = {0, 0, 0x90, 0x91, 0xac, 0x9d, 0x86, 0xd8, 0x9b};
1300         static byte esc_t[] = {0x03, 0x08, 0x00, 0x00};
1301         API_PARSE *ai;
1302         API_PARSE ai_parms[5];
1303         word ch = 0;
1304
1305         if (!plci) {
1306                 dbug(1, dprintf("connect_res(no plci)"));
1307                 return 0;  /* no plci, no send */
1308         }
1309
1310         dbug(1, dprintf("connect_res(State=0x%x)", plci->State));
1311         for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1312         ai = &parms[5];
1313         dbug(1, dprintf("ai->length=%d", ai->length));
1314
1315         if (ai->length)
1316         {
1317                 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1318                 {
1319                         dbug(1, dprintf("ai_parms[0].length=%d/0x%x", ai_parms[0].length, GET_WORD(ai_parms[0].info + 1)));
1320                         ch = 0;
1321                         if (ai_parms[0].length)
1322                         {
1323                                 ch = GET_WORD(ai_parms[0].info + 1);
1324                                 dbug(1, dprintf("BCH-I=0x%x", ch));
1325                         }
1326                 }
1327         }
1328
1329         if (plci->State == INC_CON_CONNECTED_ALERT)
1330         {
1331                 dbug(1, dprintf("Connected Alert Call_Res"));
1332                 if (a->Info_Mask[appl->Id - 1] & 0x200)
1333                 {
1334                         /* early B3 connect (CIP mask bit 9) no release after a disc */
1335                         add_p(plci, LLI, "\x01\x01");
1336                 }
1337                 add_s(plci, CONN_NR, &parms[2]);
1338                 add_s(plci, LLC, &parms[4]);
1339                 add_ai(plci, &parms[5]);
1340                 plci->State = INC_CON_ACCEPT;
1341                 sig_req(plci, CALL_RES, 0);
1342                 return 1;
1343         }
1344         else if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT) {
1345                 __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
1346                 dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
1347                 Reject = GET_WORD(parms[0].info);
1348                 dbug(1, dprintf("Reject=0x%x", Reject));
1349                 if (Reject)
1350                 {
1351                         if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
1352                         {
1353                                 if ((Reject & 0xff00) == 0x3400)
1354                                 {
1355                                         esc_t[2] = ((byte)(Reject & 0x00ff)) | 0x80;
1356                                         add_p(plci, ESC, esc_t);
1357                                         add_ai(plci, &parms[5]);
1358                                         sig_req(plci, REJECT, 0);
1359                                 }
1360                                 else if (Reject == 1 || Reject >= 9)
1361                                 {
1362                                         add_ai(plci, &parms[5]);
1363                                         sig_req(plci, HANGUP, 0);
1364                                 }
1365                                 else
1366                                 {
1367                                         esc_t[2] = cau_t[(Reject&0x000f)];
1368                                         add_p(plci, ESC, esc_t);
1369                                         add_ai(plci, &parms[5]);
1370                                         sig_req(plci, REJECT, 0);
1371                                 }
1372                                 plci->appl = appl;
1373                         }
1374                         else
1375                         {
1376                                 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1377                         }
1378                 }
1379                 else {
1380                         plci->appl = appl;
1381                         if (Id & EXT_CONTROLLER) {
1382                                 if (AdvCodecSupport(a, plci, appl, 0)) {
1383                                         dbug(1, dprintf("connect_res(error from AdvCodecSupport)"));
1384                                         sig_req(plci, HANGUP, 0);
1385                                         return 1;
1386                                 }
1387                                 if (plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1388                                 {
1389                                         Info = add_b23(plci, &parms[1]);
1390                                         if (Info)
1391                                         {
1392                                                 dbug(1, dprintf("connect_res(error from add_b23)"));
1393                                                 sig_req(plci, HANGUP, 0);
1394                                                 return 1;
1395                                         }
1396                                         if (plci->adv_nl)
1397                                         {
1398                                                 nl_req_ncci(plci, ASSIGN, 0);
1399                                         }
1400                                 }
1401                         }
1402                         else
1403                         {
1404                                 plci->tel = 0;
1405                                 if (ch != 2)
1406                                 {
1407                                         Info = add_b23(plci, &parms[1]);
1408                                         if (Info)
1409                                         {
1410                                                 dbug(1, dprintf("connect_res(error from add_b23 2)"));
1411                                                 sig_req(plci, HANGUP, 0);
1412                                                 return 1;
1413                                         }
1414                                 }
1415                                 nl_req_ncci(plci, ASSIGN, 0);
1416                         }
1417
1418                         if (plci->spoofed_msg == SPOOFING_REQUIRED)
1419                         {
1420                                 api_save_msg(parms, "wsssss", &plci->saved_msg);
1421                                 plci->spoofed_msg = CALL_RES;
1422                                 plci->internal_command = BLOCK_PLCI;
1423                                 plci->command = 0;
1424                                 dbug(1, dprintf("Spoof"));
1425                         }
1426                         else
1427                         {
1428                                 add_b1(plci, &parms[1], ch, plci->B1_facilities);
1429                                 if (a->Info_Mask[appl->Id - 1] & 0x200)
1430                                 {
1431                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
1432                                         add_p(plci, LLI, "\x01\x01");
1433                                 }
1434                                 add_s(plci, CONN_NR, &parms[2]);
1435                                 add_s(plci, LLC, &parms[4]);
1436                                 add_ai(plci, &parms[5]);
1437                                 plci->State = INC_CON_ACCEPT;
1438                                 sig_req(plci, CALL_RES, 0);
1439                         }
1440
1441                         for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
1442                                 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1443                 }
1444         }
1445         return 1;
1446 }
1447
1448 static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1449                           PLCI *plci, APPL *appl, API_PARSE *msg)
1450 {
1451         dbug(1, dprintf("connect_a_res"));
1452         return false;
1453 }
1454
1455 static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1456                            PLCI *plci, APPL *appl, API_PARSE *msg)
1457 {
1458         word Info;
1459         word i;
1460
1461         dbug(1, dprintf("disconnect_req"));
1462
1463         Info = _WRONG_IDENTIFIER;
1464
1465         if (plci)
1466         {
1467                 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
1468                 {
1469                         __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
1470                         plci->appl = appl;
1471                         for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
1472                                 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1473                         plci->State = OUTG_DIS_PENDING;
1474                 }
1475                 if (plci->Sig.Id && plci->appl)
1476                 {
1477                         Info = 0;
1478                         if (plci->Sig.Id != 0xff)
1479                         {
1480                                 if (plci->State != INC_DIS_PENDING)
1481                                 {
1482                                         add_ai(plci, &msg[0]);
1483                                         sig_req(plci, HANGUP, 0);
1484                                         plci->State = OUTG_DIS_PENDING;
1485                                         return 1;
1486                                 }
1487                         }
1488                         else
1489                         {
1490                                 if (plci->NL.Id && !plci->nl_remove_id)
1491                                 {
1492                                         mixer_remove(plci);
1493                                         nl_req_ncci(plci, REMOVE, 0);
1494                                         sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
1495                                         sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1496                                         plci->State = INC_DIS_PENDING;
1497                                 }
1498                                 return 1;
1499                         }
1500                 }
1501         }
1502
1503         if (!appl)  return false;
1504         sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", Info);
1505         return false;
1506 }
1507
1508 static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1509                            PLCI *plci, APPL *appl, API_PARSE *msg)
1510 {
1511         dbug(1, dprintf("disconnect_res"));
1512         if (plci)
1513         {
1514                 /* clear ind mask bit, just in case of collsion of          */
1515                 /* DISCONNECT_IND and CONNECT_RES                           */
1516                 __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
1517                 ncci_free_receive_buffers(plci, 0);
1518                 if (plci_remove_check(plci))
1519                 {
1520                         return 0;
1521                 }
1522                 if (plci->State == INC_DIS_PENDING
1523                     || plci->State == SUSPENDING) {
1524                         if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL)) {
1525                                 if (plci->State != SUSPENDING) plci->State = IDLE;
1526                                 dbug(1, dprintf("chs=%d", plci->channels));
1527                                 if (!plci->channels) {
1528                                         plci_remove(plci);
1529                                 }
1530                         }
1531                 }
1532         }
1533         return 0;
1534 }
1535
1536 static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1537                        PLCI *plci, APPL *appl, API_PARSE *parms)
1538 {
1539         word Info;
1540         byte i;
1541
1542         dbug(1, dprintf("listen_req(Appl=0x%x)", appl->Id));
1543
1544         Info = _WRONG_IDENTIFIER;
1545         if (a) {
1546                 Info = 0;
1547                 a->Info_Mask[appl->Id - 1] = GET_DWORD(parms[0].info);
1548                 a->CIP_Mask[appl->Id - 1] = GET_DWORD(parms[1].info);
1549                 dbug(1, dprintf("CIP_MASK=0x%lx", GET_DWORD(parms[1].info)));
1550                 if (a->Info_Mask[appl->Id - 1] & 0x200) { /* early B3 connect provides */
1551                         a->Info_Mask[appl->Id - 1] |=  0x10;   /* call progression infos    */
1552                 }
1553
1554                 /* check if external controller listen and switch listen on or off*/
1555                 if (Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)) {
1556                         if (a->profile.Global_Options & ON_BOARD_CODEC) {
1557                                 dummy_plci.State = IDLE;
1558                                 a->codec_listen[appl->Id - 1] = &dummy_plci;
1559                                 a->TelOAD[0] = (byte)(parms[3].length);
1560                                 for (i = 1; parms[3].length >= i && i < 22; i++) {
1561                                         a->TelOAD[i] = parms[3].info[i];
1562                                 }
1563                                 a->TelOAD[i] = 0;
1564                                 a->TelOSA[0] = (byte)(parms[4].length);
1565                                 for (i = 1; parms[4].length >= i && i < 22; i++) {
1566                                         a->TelOSA[i] = parms[4].info[i];
1567                                 }
1568                                 a->TelOSA[i] = 0;
1569                         }
1570                         else Info = 0x2002; /* wrong controller, codec not supported */
1571                 }
1572                 else{               /* clear listen */
1573                         a->codec_listen[appl->Id - 1] = (PLCI *)0;
1574                 }
1575         }
1576         sendf(appl,
1577               _LISTEN_R | CONFIRM,
1578               Id,
1579               Number,
1580               "w", Info);
1581
1582         if (a) listen_check(a);
1583         return false;
1584 }
1585
1586 static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1587                      PLCI *plci, APPL *appl, API_PARSE *msg)
1588 {
1589         word i;
1590         API_PARSE *ai;
1591         PLCI *rc_plci = NULL;
1592         API_PARSE ai_parms[5];
1593         word Info = 0;
1594
1595         dbug(1, dprintf("info_req"));
1596         for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1597
1598         ai = &msg[1];
1599
1600         if (ai->length)
1601         {
1602                 if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1603                 {
1604                         dbug(1, dprintf("AddInfo wrong"));
1605                         Info = _WRONG_MESSAGE_FORMAT;
1606                 }
1607         }
1608         if (!a) Info = _WRONG_STATE;
1609
1610         if (!Info && plci)
1611         {                /* no fac, with CPN, or KEY */
1612                 rc_plci = plci;
1613                 if (!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length))
1614                 {
1615                         /* overlap sending option */
1616                         dbug(1, dprintf("OvlSnd"));
1617                         add_s(plci, CPN, &msg[0]);
1618                         add_s(plci, KEY, &ai_parms[1]);
1619                         sig_req(plci, INFO_REQ, 0);
1620                         send_req(plci);
1621                         return false;
1622                 }
1623
1624                 if (plci->State && ai_parms[2].length)
1625                 {
1626                         /* User_Info option */
1627                         dbug(1, dprintf("UUI"));
1628                         add_s(plci, UUI, &ai_parms[2]);
1629                         sig_req(plci, USER_DATA, 0);
1630                 }
1631                 else if (plci->State && ai_parms[3].length)
1632                 {
1633                         /* Facility option */
1634                         dbug(1, dprintf("FAC"));
1635                         add_s(plci, CPN, &msg[0]);
1636                         add_ai(plci, &msg[1]);
1637                         sig_req(plci, FACILITY_REQ, 0);
1638                 }
1639                 else
1640                 {
1641                         Info = _WRONG_STATE;
1642                 }
1643         }
1644         else if ((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1645         {
1646                 /* NCR_Facility option -> send UUI and Keypad too */
1647                 dbug(1, dprintf("NCR_FAC"));
1648                 if ((i = get_plci(a)))
1649                 {
1650                         rc_plci = &a->plci[i - 1];
1651                         appl->NullCREnable = true;
1652                         rc_plci->internal_command = C_NCR_FAC_REQ;
1653                         rc_plci->appl = appl;
1654                         add_p(rc_plci, CAI, "\x01\x80");
1655                         add_p(rc_plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1656                         sig_req(rc_plci, ASSIGN, DSIG_ID);
1657                         send_req(rc_plci);
1658                 }
1659                 else
1660                 {
1661                         Info = _OUT_OF_PLCI;
1662                 }
1663
1664                 if (!Info)
1665                 {
1666                         add_s(rc_plci, CPN, &msg[0]);
1667                         add_ai(rc_plci, &msg[1]);
1668                         sig_req(rc_plci, NCR_FACILITY, 0);
1669                         send_req(rc_plci);
1670                         return false;
1671                         /* for application controlled supplementary services    */
1672                 }
1673         }
1674
1675         if (!rc_plci)
1676         {
1677                 Info = _WRONG_MESSAGE_FORMAT;
1678         }
1679
1680         if (!Info)
1681         {
1682                 send_req(rc_plci);
1683         }
1684         else
1685         {  /* appl is not assigned to a PLCI or error condition */
1686                 dbug(1, dprintf("localInfoCon"));
1687                 sendf(appl,
1688                       _INFO_R | CONFIRM,
1689                       Id,
1690                       Number,
1691                       "w", Info);
1692         }
1693         return false;
1694 }
1695
1696 static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1697                      PLCI *plci, APPL *appl, API_PARSE *msg)
1698 {
1699         dbug(1, dprintf("info_res"));
1700         return false;
1701 }
1702
1703 static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1704                       PLCI *plci, APPL *appl, API_PARSE *msg)
1705 {
1706         word Info;
1707         byte ret;
1708
1709         dbug(1, dprintf("alert_req"));
1710
1711         Info = _WRONG_IDENTIFIER;
1712         ret = false;
1713         if (plci) {
1714                 Info = _ALERT_IGNORED;
1715                 if (plci->State != INC_CON_ALERT) {
1716                         Info = _WRONG_STATE;
1717                         if (plci->State == INC_CON_PENDING) {
1718                                 Info = 0;
1719                                 plci->State = INC_CON_ALERT;
1720                                 add_ai(plci, &msg[0]);
1721                                 sig_req(plci, CALL_ALERT, 0);
1722                                 ret = 1;
1723                         }
1724                 }
1725         }
1726         sendf(appl,
1727               _ALERT_R | CONFIRM,
1728               Id,
1729               Number,
1730               "w", Info);
1731         return ret;
1732 }
1733
1734 static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1735                          PLCI *plci, APPL *appl, API_PARSE *msg)
1736 {
1737         word Info = 0;
1738         word i    = 0;
1739
1740         word selector;
1741         word SSreq;
1742         long relatedPLCIvalue;
1743         DIVA_CAPI_ADAPTER *relatedadapter;
1744         byte *SSparms  = "";
1745         byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1746         byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1747         API_PARSE *parms;
1748         API_PARSE ss_parms[11];
1749         PLCI *rplci;
1750         byte cai[15];
1751         dword d;
1752         API_PARSE dummy;
1753
1754         dbug(1, dprintf("facility_req"));
1755         for (i = 0; i < 9; i++) ss_parms[i].length = 0;
1756
1757         parms = &msg[1];
1758
1759         if (!a)
1760         {
1761                 dbug(1, dprintf("wrong Ctrl"));
1762                 Info = _WRONG_IDENTIFIER;
1763         }
1764
1765         selector = GET_WORD(msg[0].info);
1766
1767         if (!Info)
1768         {
1769                 switch (selector)
1770                 {
1771                 case SELECTOR_HANDSET:
1772                         Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1773                         break;
1774
1775                 case SELECTOR_SU_SERV:
1776                         if (!msg[1].length)
1777                         {
1778                                 Info = _WRONG_MESSAGE_FORMAT;
1779                                 break;
1780                         }
1781                         SSreq = GET_WORD(&(msg[1].info[1]));
1782                         PUT_WORD(&RCparms[1], SSreq);
1783                         SSparms = RCparms;
1784                         switch (SSreq)
1785                         {
1786                         case S_GET_SUPPORTED_SERVICES:
1787                                 if ((i = get_plci(a)))
1788                                 {
1789                                         rplci = &a->plci[i - 1];
1790                                         rplci->appl = appl;
1791                                         add_p(rplci, CAI, "\x01\x80");
1792                                         add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1793                                         sig_req(rplci, ASSIGN, DSIG_ID);
1794                                         send_req(rplci);
1795                                 }
1796                                 else
1797                                 {
1798                                         PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1799                                         SSparms = (byte *)SSstruct;
1800                                         break;
1801                                 }
1802                                 rplci->internal_command = GETSERV_REQ_PEND;
1803                                 rplci->number = Number;
1804                                 rplci->appl = appl;
1805                                 sig_req(rplci, S_SUPPORTED, 0);
1806                                 send_req(rplci);
1807                                 return false;
1808                                 break;
1809
1810                         case S_LISTEN:
1811                                 if (parms->length == 7)
1812                                 {
1813                                         if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1814                                         {
1815                                                 dbug(1, dprintf("format wrong"));
1816                                                 Info = _WRONG_MESSAGE_FORMAT;
1817                                                 break;
1818                                         }
1819                                 }
1820                                 else
1821                                 {
1822                                         Info = _WRONG_MESSAGE_FORMAT;
1823                                         break;
1824                                 }
1825                                 a->Notification_Mask[appl->Id - 1] = GET_DWORD(ss_parms[2].info);
1826                                 if (a->Notification_Mask[appl->Id - 1] & SMASK_MWI) /* MWI active? */
1827                                 {
1828                                         if ((i = get_plci(a)))
1829                                         {
1830                                                 rplci = &a->plci[i - 1];
1831                                                 rplci->appl = appl;
1832                                                 add_p(rplci, CAI, "\x01\x80");
1833                                                 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1834                                                 sig_req(rplci, ASSIGN, DSIG_ID);
1835                                                 send_req(rplci);
1836                                         }
1837                                         else
1838                                         {
1839                                                 break;
1840                                         }
1841                                         rplci->internal_command = GET_MWI_STATE;
1842                                         rplci->number = Number;
1843                                         sig_req(rplci, MWI_POLL, 0);
1844                                         send_req(rplci);
1845                                 }
1846                                 break;
1847
1848                         case S_HOLD:
1849                                 api_parse(&parms->info[1], (word)parms->length, "ws", ss_parms);
1850                                 if (plci && plci->State && plci->SuppState == IDLE)
1851                                 {
1852                                         plci->SuppState = HOLD_REQUEST;
1853                                         plci->command = C_HOLD_REQ;
1854                                         add_s(plci, CAI, &ss_parms[1]);
1855                                         sig_req(plci, CALL_HOLD, 0);
1856                                         send_req(plci);
1857                                         return false;
1858                                 }
1859                                 else Info = 0x3010;                    /* wrong state           */
1860                                 break;
1861                         case S_RETRIEVE:
1862                                 if (plci && plci->State && plci->SuppState == CALL_HELD)
1863                                 {
1864                                         if (Id & EXT_CONTROLLER)
1865                                         {
1866                                                 if (AdvCodecSupport(a, plci, appl, 0))
1867                                                 {
1868                                                         Info = 0x3010;                    /* wrong state           */
1869                                                         break;
1870                                                 }
1871                                         }
1872                                         else plci->tel = 0;
1873
1874                                         plci->SuppState = RETRIEVE_REQUEST;
1875                                         plci->command = C_RETRIEVE_REQ;
1876                                         if (plci->spoofed_msg == SPOOFING_REQUIRED)
1877                                         {
1878                                                 plci->spoofed_msg = CALL_RETRIEVE;
1879                                                 plci->internal_command = BLOCK_PLCI;
1880                                                 plci->command = 0;
1881                                                 dbug(1, dprintf("Spoof"));
1882                                                 return false;
1883                                         }
1884                                         else
1885                                         {
1886                                                 sig_req(plci, CALL_RETRIEVE, 0);
1887                                                 send_req(plci);
1888                                                 return false;
1889                                         }
1890                                 }
1891                                 else Info = 0x3010;                    /* wrong state           */
1892                                 break;
1893                         case S_SUSPEND:
1894                                 if (parms->length)
1895                                 {
1896                                         if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
1897                                         {
1898                                                 dbug(1, dprintf("format wrong"));
1899                                                 Info = _WRONG_MESSAGE_FORMAT;
1900                                                 break;
1901                                         }
1902                                 }
1903                                 if (plci && plci->State)
1904                                 {
1905                                         add_s(plci, CAI, &ss_parms[2]);
1906                                         plci->command = SUSPEND_REQ;
1907                                         sig_req(plci, SUSPEND, 0);
1908                                         plci->State = SUSPENDING;
1909                                         send_req(plci);
1910                                 }
1911                                 else Info = 0x3010;                    /* wrong state           */
1912                                 break;
1913
1914                         case S_RESUME:
1915                                 if (!(i = get_plci(a)))
1916                                 {
1917                                         Info = _OUT_OF_PLCI;
1918                                         break;
1919                                 }
1920                                 rplci = &a->plci[i - 1];
1921                                 rplci->appl = appl;
1922                                 rplci->number = Number;
1923                                 rplci->tel = 0;
1924                                 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1925                                 /* check 'external controller' bit for codec support */
1926                                 if (Id & EXT_CONTROLLER)
1927                                 {
1928                                         if (AdvCodecSupport(a, rplci, appl, 0))
1929                                         {
1930                                                 rplci->Id = 0;
1931                                                 Info = 0x300A;
1932                                                 break;
1933                                         }
1934                                 }
1935                                 if (parms->length)
1936                                 {
1937                                         if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
1938                                         {
1939                                                 dbug(1, dprintf("format wrong"));
1940                                                 rplci->Id = 0;
1941                                                 Info = _WRONG_MESSAGE_FORMAT;
1942                                                 break;
1943                                         }
1944                                 }
1945                                 dummy.length = 0;
1946                                 dummy.info = "\x00";
1947                                 add_b1(rplci, &dummy, 0, 0);
1948                                 if (a->Info_Mask[appl->Id - 1] & 0x200)
1949                                 {
1950                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
1951                                         add_p(rplci, LLI, "\x01\x01");
1952                                 }
1953                                 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1954                                 sig_req(rplci, ASSIGN, DSIG_ID);
1955                                 send_req(rplci);
1956                                 add_s(rplci, CAI, &ss_parms[2]);
1957                                 rplci->command = RESUME_REQ;
1958                                 sig_req(rplci, RESUME, 0);
1959                                 rplci->State = RESUMING;
1960                                 send_req(rplci);
1961                                 break;
1962
1963                         case S_CONF_BEGIN: /* Request */
1964                         case S_CONF_DROP:
1965                         case S_CONF_ISOLATE:
1966                         case S_CONF_REATTACH:
1967                                 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1968                                 {
1969                                         dbug(1, dprintf("format wrong"));
1970                                         Info = _WRONG_MESSAGE_FORMAT;
1971                                         break;
1972                                 }
1973                                 if (plci && plci->State && ((plci->SuppState == IDLE) || (plci->SuppState == CALL_HELD)))
1974                                 {
1975                                         d = GET_DWORD(ss_parms[2].info);
1976                                         if (d >= 0x80)
1977                                         {
1978                                                 dbug(1, dprintf("format wrong"));
1979                                                 Info = _WRONG_MESSAGE_FORMAT;
1980                                                 break;
1981                                         }
1982                                         plci->ptyState = (byte)SSreq;
1983                                         plci->command = 0;
1984                                         cai[0] = 2;
1985                                         switch (SSreq)
1986                                         {
1987                                         case S_CONF_BEGIN:
1988                                                 cai[1] = CONF_BEGIN;
1989                                                 plci->internal_command = CONF_BEGIN_REQ_PEND;
1990                                                 break;
1991                                         case S_CONF_DROP:
1992                                                 cai[1] = CONF_DROP;
1993                                                 plci->internal_command = CONF_DROP_REQ_PEND;
1994                                                 break;
1995                                         case S_CONF_ISOLATE:
1996                                                 cai[1] = CONF_ISOLATE;
1997                                                 plci->internal_command = CONF_ISOLATE_REQ_PEND;
1998                                                 break;
1999                                         case S_CONF_REATTACH:
2000                                                 cai[1] = CONF_REATTACH;
2001                                                 plci->internal_command = CONF_REATTACH_REQ_PEND;
2002                                                 break;
2003                                         }
2004                                         cai[2] = (byte)d; /* Conference Size resp. PartyId */
2005                                         add_p(plci, CAI, cai);
2006                                         sig_req(plci, S_SERVICE, 0);
2007                                         send_req(plci);
2008                                         return false;
2009                                 }
2010                                 else Info = 0x3010;                    /* wrong state           */
2011                                 break;
2012
2013                         case S_ECT:
2014                         case S_3PTY_BEGIN:
2015                         case S_3PTY_END:
2016                         case S_CONF_ADD:
2017                                 if (parms->length == 7)
2018                                 {
2019                                         if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2020                                         {
2021                                                 dbug(1, dprintf("format wrong"));
2022                                                 Info = _WRONG_MESSAGE_FORMAT;
2023                                                 break;
2024                                         }
2025                                 }
2026                                 else if (parms->length == 8) /* workaround for the T-View-S */
2027                                 {
2028                                         if (api_parse(&parms->info[1], (word)parms->length, "wbdb", ss_parms))
2029                                         {
2030                                                 dbug(1, dprintf("format wrong"));
2031                                                 Info = _WRONG_MESSAGE_FORMAT;
2032                                                 break;
2033                                         }
2034                                 }
2035                                 else
2036                                 {
2037                                         Info = _WRONG_MESSAGE_FORMAT;
2038                                         break;
2039                                 }
2040                                 if (!msg[1].length)
2041                                 {
2042                                         Info = _WRONG_MESSAGE_FORMAT;
2043                                         break;
2044                                 }
2045                                 if (!plci)
2046                                 {
2047                                         Info = _WRONG_IDENTIFIER;
2048                                         break;
2049                                 }
2050                                 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2051                                 relatedPLCIvalue &= 0x0000FFFF;
2052                                 dbug(1, dprintf("PTY/ECT/addCONF,relPLCI=%lx", relatedPLCIvalue));
2053                                 /* controller starts with 0 up to (max_adapter - 1) */
2054                                 if (((relatedPLCIvalue & 0x7f) == 0)
2055                                     || (MapController((byte)(relatedPLCIvalue & 0x7f)) == 0)
2056                                     || (MapController((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2057                                 {
2058                                         if (SSreq == S_3PTY_END)
2059                                         {
2060                                                 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2061                                                 rplci = plci;
2062                                         }
2063                                         else
2064                                         {
2065                                                 Info = 0x3010;                    /* wrong state           */
2066                                                 break;
2067                                         }
2068                                 }
2069                                 else
2070                                 {
2071                                         relatedadapter = &adapter[MapController((byte)(relatedPLCIvalue & 0x7f)) - 1];
2072                                         relatedPLCIvalue >>= 8;
2073                                         /* find PLCI PTR*/
2074                                         for (i = 0, rplci = NULL; i < relatedadapter->max_plci; i++)
2075                                         {
2076                                                 if (relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2077                                                 {
2078                                                         rplci = &relatedadapter->plci[i];
2079                                                 }
2080                                         }
2081                                         if (!rplci || !relatedPLCIvalue)
2082                                         {
2083                                                 if (SSreq == S_3PTY_END)
2084                                                 {
2085                                                         dbug(1, dprintf("use 2nd PLCI=PLCI"));
2086                                                         rplci = plci;
2087                                                 }
2088                                                 else
2089                                                 {
2090                                                         Info = 0x3010;                    /* wrong state           */
2091                                                         break;
2092                                                 }
2093                                         }
2094                                 }
2095 /*
2096   dbug(1, dprintf("rplci:%x", rplci));
2097   dbug(1, dprintf("plci:%x", plci));
2098   dbug(1, dprintf("rplci->ptyState:%x", rplci->ptyState));
2099   dbug(1, dprintf("plci->ptyState:%x", plci->ptyState));
2100   dbug(1, dprintf("SSreq:%x", SSreq));
2101   dbug(1, dprintf("rplci->internal_command:%x", rplci->internal_command));
2102   dbug(1, dprintf("rplci->appl:%x", rplci->appl));
2103   dbug(1, dprintf("rplci->Id:%x", rplci->Id));
2104 */
2105                                 /* send PTY/ECT req, cannot check all states because of US stuff */
2106                                 if (!rplci->internal_command && rplci->appl)
2107                                 {
2108                                         plci->command = 0;
2109                                         rplci->relatedPTYPLCI = plci;
2110                                         plci->relatedPTYPLCI = rplci;
2111                                         rplci->ptyState = (byte)SSreq;
2112                                         if (SSreq == S_ECT)
2113                                         {
2114                                                 rplci->internal_command = ECT_REQ_PEND;
2115                                                 cai[1] = ECT_EXECUTE;
2116
2117                                                 rplci->vswitchstate = 0;
2118                                                 rplci->vsprot = 0;
2119                                                 rplci->vsprotdialect = 0;
2120                                                 plci->vswitchstate = 0;
2121                                                 plci->vsprot = 0;
2122                                                 plci->vsprotdialect = 0;
2123
2124                                         }
2125                                         else if (SSreq == S_CONF_ADD)
2126                                         {
2127                                                 rplci->internal_command = CONF_ADD_REQ_PEND;
2128                                                 cai[1] = CONF_ADD;
2129                                         }
2130                                         else
2131                                         {
2132                                                 rplci->internal_command = PTY_REQ_PEND;
2133                                                 cai[1] = (byte)(SSreq - 3);
2134                                         }
2135                                         rplci->number = Number;
2136                                         if (plci != rplci) /* explicit invocation */
2137                                         {
2138                                                 cai[0] = 2;
2139                                                 cai[2] = plci->Sig.Id;
2140                                                 dbug(1, dprintf("explicit invocation"));
2141                                         }
2142                                         else
2143                                         {
2144                                                 dbug(1, dprintf("implicit invocation"));
2145                                                 cai[0] = 1;
2146                                         }
2147                                         add_p(rplci, CAI, cai);
2148                                         sig_req(rplci, S_SERVICE, 0);
2149                                         send_req(rplci);
2150                                         return false;
2151                                 }
2152                                 else
2153                                 {
2154                                         dbug(0, dprintf("Wrong line"));
2155                                         Info = 0x3010;                    /* wrong state           */
2156                                         break;
2157                                 }
2158                                 break;
2159
2160                         case S_CALL_DEFLECTION:
2161                                 if (api_parse(&parms->info[1], (word)parms->length, "wbwss", ss_parms))
2162                                 {
2163                                         dbug(1, dprintf("format wrong"));
2164                                         Info = _WRONG_MESSAGE_FORMAT;
2165                                         break;
2166                                 }
2167                                 if (!plci)
2168                                 {
2169                                         Info = _WRONG_IDENTIFIER;
2170                                         break;
2171                                 }
2172                                 /* reuse unused screening indicator */
2173                                 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2174                                 plci->command = 0;
2175                                 plci->internal_command = CD_REQ_PEND;
2176                                 appl->CDEnable = true;
2177                                 cai[0] = 1;
2178                                 cai[1] = CALL_DEFLECTION;
2179                                 add_p(plci, CAI, cai);
2180                                 add_p(plci, CPN, ss_parms[3].info);
2181                                 sig_req(plci, S_SERVICE, 0);
2182                                 send_req(plci);
2183                                 return false;
2184                                 break;
2185
2186                         case S_CALL_FORWARDING_START:
2187                                 if (api_parse(&parms->info[1], (word)parms->length, "wbdwwsss", ss_parms))
2188                                 {
2189                                         dbug(1, dprintf("format wrong"));
2190                                         Info = _WRONG_MESSAGE_FORMAT;
2191                                         break;
2192                                 }
2193
2194                                 if ((i = get_plci(a)))
2195                                 {
2196                                         rplci = &a->plci[i - 1];
2197                                         rplci->appl = appl;
2198                                         add_p(rplci, CAI, "\x01\x80");
2199                                         add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2200                                         sig_req(rplci, ASSIGN, DSIG_ID);
2201                                         send_req(rplci);
2202                                 }
2203                                 else
2204                                 {
2205                                         Info = _OUT_OF_PLCI;
2206                                         break;
2207                                 }
2208
2209                                 /* reuse unused screening indicator */
2210                                 rplci->internal_command = CF_START_PEND;
2211                                 rplci->appl = appl;
2212                                 rplci->number = Number;
2213                                 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2214                                 cai[0] = 2;
2215                                 cai[1] = 0x70 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2216                                 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2217                                 add_p(rplci, CAI, cai);
2218                                 add_p(rplci, OAD, ss_parms[5].info);
2219                                 add_p(rplci, CPN, ss_parms[6].info);
2220                                 sig_req(rplci, S_SERVICE, 0);
2221                                 send_req(rplci);
2222                                 return false;
2223                                 break;
2224
2225                         case S_INTERROGATE_DIVERSION:
2226                         case S_INTERROGATE_NUMBERS:
2227                         case S_CALL_FORWARDING_STOP:
2228                         case S_CCBS_REQUEST:
2229                         case S_CCBS_DEACTIVATE:
2230                         case S_CCBS_INTERROGATE:
2231                                 switch (SSreq)
2232                                 {
2233                                 case S_INTERROGATE_NUMBERS:
2234                                         if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2235                                         {
2236                                                 dbug(0, dprintf("format wrong"));
2237                                                 Info = _WRONG_MESSAGE_FORMAT;
2238                                         }
2239                                         break;
2240                                 case S_CCBS_REQUEST:
2241                                 case S_CCBS_DEACTIVATE:
2242                                         if (api_parse(&parms->info[1], (word)parms->length, "wbdw", ss_parms))
2243                                         {
2244                                                 dbug(0, dprintf("format wrong"));
2245                                                 Info = _WRONG_MESSAGE_FORMAT;
2246                                         }
2247                                         break;
2248                                 case S_CCBS_INTERROGATE:
2249                                         if (api_parse(&parms->info[1], (word)parms->length, "wbdws", ss_parms))
2250                                         {
2251                                                 dbug(0, dprintf("format wrong"));
2252                                                 Info = _WRONG_MESSAGE_FORMAT;
2253                                         }
2254                                         break;
2255                                 default:
2256                                         if (api_parse(&parms->info[1], (word)parms->length, "wbdwws", ss_parms))
2257                                         {
2258                                                 dbug(0, dprintf("format wrong"));
2259                                                 Info = _WRONG_MESSAGE_FORMAT;
2260                                                 break;
2261                                         }
2262                                         break;
2263                                 }
2264
2265                                 if (Info) break;
2266                                 if ((i = get_plci(a)))
2267                                 {
2268                                         rplci = &a->plci[i - 1];
2269                                         switch (SSreq)
2270                                         {
2271                                         case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2272                                                 cai[1] = 0x60 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2273                                                 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2274                                                 break;
2275                                         case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2276                                                 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2277                                                 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2278                                                 break;
2279                                         case S_CALL_FORWARDING_STOP:
2280                                                 rplci->internal_command = CF_STOP_PEND;
2281                                                 cai[1] = 0x80 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2282                                                 break;
2283                                         case S_CCBS_REQUEST:
2284                                                 cai[1] = CCBS_REQUEST;
2285                                                 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2286                                                 break;
2287                                         case S_CCBS_DEACTIVATE:
2288                                                 cai[1] = CCBS_DEACTIVATE;
2289                                                 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2290                                                 break;
2291                                         case S_CCBS_INTERROGATE:
2292                                                 cai[1] = CCBS_INTERROGATE;
2293                                                 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2294                                                 break;
2295                                         default:
2296                                                 cai[1] = 0;
2297                                                 break;
2298                                         }
2299                                         rplci->appl = appl;
2300                                         rplci->number = Number;
2301                                         add_p(rplci, CAI, "\x01\x80");
2302                                         add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2303                                         sig_req(rplci, ASSIGN, DSIG_ID);
2304                                         send_req(rplci);
2305                                 }
2306                                 else
2307                                 {
2308                                         Info = _OUT_OF_PLCI;
2309                                         break;
2310                                 }
2311
2312                                 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2313                                 switch (SSreq)
2314                                 {
2315                                 case S_INTERROGATE_NUMBERS:
2316                                         cai[0] = 1;
2317                                         add_p(rplci, CAI, cai);
2318                                         break;
2319                                 case S_CCBS_REQUEST:
2320                                 case S_CCBS_DEACTIVATE:
2321                                         cai[0] = 3;
2322                                         PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2323                                         add_p(rplci, CAI, cai);
2324                                         break;
2325                                 case S_CCBS_INTERROGATE:
2326                                         cai[0] = 3;
2327                                         PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2328                                         add_p(rplci, CAI, cai);
2329                                         add_p(rplci, OAD, ss_parms[4].info);
2330                                         break;
2331                                 default:
2332                                         cai[0] = 2;
2333                                         cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2334                                         add_p(rplci, CAI, cai);
2335                                         add_p(rplci, OAD, ss_parms[5].info);
2336                                         break;
2337                                 }
2338
2339                                 sig_req(rplci, S_SERVICE, 0);
2340                                 send_req(rplci);
2341                                 return false;
2342                                 break;
2343
2344                         case S_MWI_ACTIVATE:
2345                                 if (api_parse(&parms->info[1], (word)parms->length, "wbwdwwwssss", ss_parms))
2346                                 {
2347                                         dbug(1, dprintf("format wrong"));
2348                                         Info = _WRONG_MESSAGE_FORMAT;
2349                                         break;
2350                                 }
2351                                 if (!plci)
2352                                 {
2353                                         if ((i = get_plci(a)))
2354                                         {
2355                                                 rplci = &a->plci[i - 1];
2356                                                 rplci->appl = appl;
2357                                                 rplci->cr_enquiry = true;
2358                                                 add_p(rplci, CAI, "\x01\x80");
2359                                                 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2360                                                 sig_req(rplci, ASSIGN, DSIG_ID);
2361                                                 send_req(rplci);
2362                                         }
2363                                         else
2364                                         {
2365                                                 Info = _OUT_OF_PLCI;
2366                                                 break;
2367                                         }
2368                                 }
2369                                 else
2370                                 {
2371                                         rplci = plci;
2372                                         rplci->cr_enquiry = false;
2373                                 }
2374
2375                                 rplci->command = 0;
2376                                 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2377                                 rplci->appl = appl;
2378                                 rplci->number = Number;
2379
2380                                 cai[0] = 13;
2381                                 cai[1] = ACTIVATION_MWI; /* Function */
2382                                 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2383                                 PUT_DWORD(&cai[4], GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2384                                 PUT_WORD(&cai[8], GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2385                                 PUT_WORD(&cai[10], GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2386                                 PUT_WORD(&cai[12], GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2387                                 add_p(rplci, CAI, cai);
2388                                 add_p(rplci, CPN, ss_parms[7].info); /* Receiving User Number */
2389                                 add_p(rplci, OAD, ss_parms[8].info); /* Controlling User Number */
2390                                 add_p(rplci, OSA, ss_parms[9].info); /* Controlling User Provided Number */
2391                                 add_p(rplci, UID, ss_parms[10].info); /* Time */
2392                                 sig_req(rplci, S_SERVICE, 0);
2393                                 send_req(rplci);
2394                                 return false;
2395
2396                         case S_MWI_DEACTIVATE:
2397                                 if (api_parse(&parms->info[1], (word)parms->length, "wbwwss", ss_parms))
2398                                 {
2399                                         dbug(1, dprintf("format wrong"));
2400                                         Info = _WRONG_MESSAGE_FORMAT;
2401                                         break;
2402                                 }
2403                                 if (!plci)
2404                                 {
2405                                         if ((i = get_plci(a)))
2406                                         {
2407                                                 rplci = &a->plci[i - 1];
2408                                                 rplci->appl = appl;
2409                                                 rplci->cr_enquiry = true;
2410                                                 add_p(rplci, CAI, "\x01\x80");
2411                                                 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2412                                                 sig_req(rplci, ASSIGN, DSIG_ID);
2413                                                 send_req(rplci);
2414                                         }
2415                                         else
2416                                         {
2417                                                 Info = _OUT_OF_PLCI;
2418                                                 break;
2419                                         }
2420                                 }
2421                                 else
2422                                 {
2423                                         rplci = plci;
2424                                         rplci->cr_enquiry = false;
2425                                 }
2426
2427                                 rplci->command = 0;
2428                                 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2429                                 rplci->appl = appl;
2430                                 rplci->number = Number;
2431
2432                                 cai[0] = 5;
2433                                 cai[1] = DEACTIVATION_MWI; /* Function */
2434                                 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2435                                 PUT_WORD(&cai[4], GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2436                                 add_p(rplci, CAI, cai);
2437                                 add_p(rplci, CPN, ss_parms[4].info); /* Receiving User Number */
2438                                 add_p(rplci, OAD, ss_parms[5].info); /* Controlling User Number */
2439                                 sig_req(rplci, S_SERVICE, 0);
2440                                 send_req(rplci);
2441                                 return false;
2442
2443                         default:
2444                                 Info = 0x300E;  /* not supported */
2445                                 break;
2446                         }
2447                         break; /* case SELECTOR_SU_SERV: end */
2448
2449
2450                 case SELECTOR_DTMF:
2451                         return (dtmf_request(Id, Number, a, plci, appl, msg));
2452
2453
2454
2455                 case SELECTOR_LINE_INTERCONNECT:
2456                         return (mixer_request(Id, Number, a, plci, appl, msg));
2457
2458
2459
2460                 case PRIV_SELECTOR_ECHO_CANCELLER:
2461                         appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2462                         return (ec_request(Id, Number, a, plci, appl, msg));
2463
2464                 case SELECTOR_ECHO_CANCELLER:
2465                         appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2466                         return (ec_request(Id, Number, a, plci, appl, msg));
2467
2468
2469                 case SELECTOR_V42BIS:
2470                 default:
2471                         Info = _FACILITY_NOT_SUPPORTED;
2472                         break;
2473                 } /* end of switch (selector) */
2474         }
2475
2476         dbug(1, dprintf("SendFacRc"));
2477         sendf(appl,
2478               _FACILITY_R | CONFIRM,
2479               Id,
2480               Number,
2481               "wws", Info, selector, SSparms);
2482         return false;
2483 }
2484
2485 static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2486                          PLCI *plci, APPL *appl, API_PARSE *msg)
2487 {
2488         dbug(1, dprintf("facility_res"));
2489         return false;
2490 }
2491
2492 static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2493                            PLCI *plci, APPL *appl, API_PARSE *parms)
2494 {
2495         word Info = 0;
2496         byte req;
2497         byte len;
2498         word w;
2499         word fax_control_bits, fax_feature_bits, fax_info_change;
2500         API_PARSE *ncpi;
2501         byte pvc[2];
2502
2503         API_PARSE fax_parms[9];
2504         word i;
2505
2506
2507         dbug(1, dprintf("connect_b3_req"));
2508         if (plci)
2509         {
2510                 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2511                     || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2512                 {
2513                         Info = _WRONG_STATE;
2514                 }
2515                 else
2516                 {
2517                         /* local reply if assign unsuccessful
2518                            or B3 protocol allows only one layer 3 connection
2519                            and already connected
2520                            or B2 protocol not any LAPD
2521                            and connect_b3_req contradicts originate/answer direction */
2522                         if (!plci->NL.Id
2523                             || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2524                                 && ((plci->channels != 0)
2525                                     || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2526                                         && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2527                         {
2528                                 dbug(1, dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2529                                                 plci->channels, plci->NL.Id, plci->call_dir, plci->SuppState));
2530                                 Info = _WRONG_STATE;
2531                                 sendf(appl,
2532                                       _CONNECT_B3_R | CONFIRM,
2533                                       Id,
2534                                       Number,
2535                                       "w", Info);
2536                                 return false;
2537                         }
2538                         plci->requested_options_conn = 0;
2539
2540                         req = N_CONNECT;
2541                         ncpi = &parms[0];
2542                         if (plci->B3_prot == 2 || plci->B3_prot == 3)
2543                         {
2544                                 if (ncpi->length > 2)
2545                                 {
2546                                         /* check for PVC */
2547                                         if (ncpi->info[2] || ncpi->info[3])
2548                                         {
2549                                                 pvc[0] = ncpi->info[3];
2550                                                 pvc[1] = ncpi->info[2];
2551                                                 add_d(plci, 2, pvc);
2552                                                 req = N_RESET;
2553                                         }
2554                                         else
2555                                         {
2556                                                 if (ncpi->info[1] & 1) req = N_CONNECT | N_D_BIT;
2557                                                 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2558                                         }
2559                                 }
2560                         }
2561                         else if (plci->B3_prot == 5)
2562                         {
2563                                 if (plci->NL.Id && !plci->nl_remove_id)
2564                                 {
2565                                         fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2566                                         fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2567                                         if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2568                                             || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2569                                         {
2570                                                 len = offsetof(T30_INFO, universal_6);
2571                                                 fax_info_change = false;
2572                                                 if (ncpi->length >= 4)
2573                                                 {
2574                                                         w = GET_WORD(&ncpi->info[3]);
2575                                                         if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2576                                                         {
2577                                                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2578                                                                         (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2579                                                                                ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2580                                                                 fax_info_change = true;
2581                                                         }
2582                                                         fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2583                                                         if (w & 0x0002)  /* Fax-polling request */
2584                                                                 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2585                                                         if ((w & 0x0004) /* Request to send / poll another document */
2586                                                             && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2587                                                         {
2588                                                                 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2589                                                         }
2590                                                         if (ncpi->length >= 6)
2591                                                         {
2592                                                                 w = GET_WORD(&ncpi->info[5]);
2593                                                                 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2594                                                                 {
2595                                                                         ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2596                                                                         fax_info_change = true;
2597                                                                 }
2598
2599                                                                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2600                                                                     && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2601                                                                 {
2602                                                                         plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2603                                                                 }
2604                                                                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2605                                                                     && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2606                                                                 {
2607                                                                         plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2608                                                                 }
2609                                                                 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2610                                                                                       T30_CONTROL_BIT_ACCEPT_PASSWORD);
2611                                                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2612                                                                     & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2613                                                                 {
2614                                                                         if (api_parse(&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2615                                                                                 Info = _WRONG_MESSAGE_FORMAT;
2616                                                                         else
2617                                                                         {
2618                                                                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2619                                                                                     & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2620                                                                                 {
2621                                                                                         fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2622                                                                                         if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2623                                                                                                 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2624                                                                                 }
2625                                                                                 w = fax_parms[4].length;
2626                                                                                 if (w > 20)
2627                                                                                         w = 20;
2628                                                                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2629                                                                                 for (i = 0; i < w; i++)
2630                                                                                         ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1 + i];
2631                                                                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2632                                                                                 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2633                                                                                 w = fax_parms[5].length;
2634                                                                                 if (w > 20)
2635                                                                                         w = 20;
2636                                                                                 plci->fax_connect_info_buffer[len++] = (byte) w;
2637                                                                                 for (i = 0; i < w; i++)
2638                                                                                         plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1 + i];
2639                                                                                 w = fax_parms[6].length;
2640                                                                                 if (w > 20)
2641                                                                                         w = 20;
2642                                                                                 plci->fax_connect_info_buffer[len++] = (byte) w;
2643                                                                                 for (i = 0; i < w; i++)
2644                                                                                         plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1 + i];
2645                                                                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2646                                                                                     & (1L << PRIVATE_FAX_NONSTANDARD))
2647                                                                                 {
2648                                                                                         if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2649                                                                                         {
2650                                                                                                 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2651                                                                                                 plci->fax_connect_info_buffer[len++] = 0;
2652                                                                                         }
2653                                                                                         else
2654                                                                                         {
2655                                                                                                 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2656                                                                                                         plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2657                                                                                                 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2658                                                                                                 for (i = 0; i < fax_parms[7].length; i++)
2659                                                                                                         plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2660                                                                                         }
2661                                                                                 }
2662                                                                         }
2663                                                                 }
2664                                                                 else
2665                                                                 {
2666                                                                         len = offsetof(T30_INFO, universal_6);
2667                                                                 }
2668                                                                 fax_info_change = true;
2669
2670                                                         }
2671                                                         if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2672                                                         {
2673                                                                 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2674                                                                 fax_info_change = true;
2675                                                         }
2676                                                 }
2677                                                 if (Info == GOOD)
2678                                                 {
2679                                                         plci->fax_connect_info_length = len;
2680                                                         if (fax_info_change)
2681                                                         {
2682                                                                 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2683                                                                 {
2684                                                                         start_internal_command(Id, plci, fax_connect_info_command);
2685                                                                         return false;
2686                                                                 }
2687                                                                 else
2688                                                                 {
2689                                                                         start_internal_command(Id, plci, fax_adjust_b23_command);
2690                                                                         return false;
2691                                                                 }
2692                                                         }
2693                                                 }
2694                                         }
2695                                         else  Info = _WRONG_STATE;
2696                                 }
2697                                 else  Info = _WRONG_STATE;
2698                         }
2699
2700                         else if (plci->B3_prot == B3_RTP)
2701                         {
2702                                 plci->internal_req_buffer[0] = ncpi->length + 1;
2703                                 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2704                                 for (w = 0; w < ncpi->length; w++)
2705                                         plci->internal_req_buffer[2 + w] = ncpi->info[1 + w];
2706                                 start_internal_command(Id, plci, rtp_connect_b3_req_command);
2707                                 return false;
2708                         }
2709
2710                         if (!Info)
2711                         {
2712                                 nl_req_ncci(plci, req, 0);
2713                                 return 1;
2714                         }
2715                 }
2716         }
2717         else Info = _WRONG_IDENTIFIER;
2718
2719         sendf(appl,
2720               _CONNECT_B3_R | CONFIRM,
2721               Id,
2722               Number,
2723               "w", Info);
2724         return false;
2725 }
2726
2727 static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2728                            PLCI *plci, APPL *appl, API_PARSE *parms)
2729 {
2730         word ncci;
2731         API_PARSE *ncpi;
2732         byte req;
2733
2734         word w;
2735
2736
2737         API_PARSE fax_parms[9];
2738         word i;
2739         byte len;
2740
2741
2742         dbug(1, dprintf("connect_b3_res"));
2743
2744         ncci = (word)(Id >> 16);
2745         if (plci && ncci) {
2746                 if (a->ncci_state[ncci] == INC_CON_PENDING) {
2747                         if (GET_WORD(&parms[0].info[0]) != 0)
2748                         {
2749                                 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2750                                 channel_request_xon(plci, a->ncci_ch[ncci]);
2751                                 channel_xmit_xon(plci);
2752                                 cleanup_ncci_data(plci, ncci);
2753                                 nl_req_ncci(plci, N_DISC, (byte)ncci);
2754                                 return 1;
2755                         }
2756                         a->ncci_state[ncci] = INC_ACT_PENDING;
2757
2758                         req = N_CONNECT_ACK;
2759                         ncpi = &parms[1];
2760                         if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2761                         {
2762
2763                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
2764                                     & (1L << PRIVATE_FAX_NONSTANDARD))
2765                                 {
2766                                         if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2767                                             && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2768                                             && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2769                                         {
2770                                                 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2771                                                 if (plci->fax_connect_info_length < len)
2772                                                 {
2773                                                         ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2774                                                         ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2775                                                 }
2776                                                 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2777                                                 {
2778                                                         dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2779                                                 }
2780                                                 else
2781                                                 {
2782                                                         if (plci->fax_connect_info_length <= len)
2783                                                                 plci->fax_connect_info_buffer[len] = 0;
2784                                                         len += 1 + plci->fax_connect_info_buffer[len];
2785                                                         if (plci->fax_connect_info_length <= len)
2786                                                                 plci->fax_connect_info_buffer[len] = 0;
2787                                                         len += 1 + plci->fax_connect_info_buffer[len];
2788                                                         if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2789                                                                 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2790                                                         plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2791                                                         for (i = 0; i < fax_parms[7].length; i++)
2792                                                                 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2793                                                 }
2794                                                 plci->fax_connect_info_length = len;
2795                                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2796                                                 start_internal_command(Id, plci, fax_connect_ack_command);
2797                                                 return false;
2798                                         }
2799                                 }
2800
2801                                 nl_req_ncci(plci, req, (byte)ncci);
2802                                 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2803                                     && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2804                                 {
2805                                         if (plci->B3_prot == 4)
2806                                                 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2807                                         else
2808                                                 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
2809                                         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2810                                 }
2811                         }
2812
2813                         else if (plci->B3_prot == B3_RTP)
2814                         {
2815                                 plci->internal_req_buffer[0] = ncpi->length + 1;
2816                                 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2817                                 for (w = 0; w < ncpi->length; w++)
2818                                         plci->internal_req_buffer[2 + w] = ncpi->info[1+w];
2819                                 start_internal_command(Id, plci, rtp_connect_b3_res_command);
2820                                 return false;
2821                         }
2822
2823                         else
2824                         {
2825                                 if (ncpi->length > 2) {
2826                                         if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
2827                                         add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2828                                 }
2829                                 nl_req_ncci(plci, req, (byte)ncci);
2830                                 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2831                                 if (plci->adjust_b_restore)
2832                                 {
2833                                         plci->adjust_b_restore = false;
2834                                         start_internal_command(Id, plci, adjust_b_restore);
2835                                 }
2836                         }
2837                         return 1;
2838                 }
2839         }
2840         return false;
2841 }
2842
2843 static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2844                              PLCI *plci, APPL *appl, API_PARSE *parms)
2845 {
2846         word ncci;
2847
2848         ncci = (word)(Id >> 16);
2849         dbug(1, dprintf("connect_b3_a_res(ncci=0x%x)", ncci));
2850
2851         if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2852             && (plci->State != OUTG_DIS_PENDING))
2853         {
2854                 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
2855                         a->ncci_state[ncci] = CONNECTED;
2856                         if (plci->State != INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2857                         channel_request_xon(plci, a->ncci_ch[ncci]);
2858                         channel_xmit_xon(plci);
2859                 }
2860         }
2861         return false;
2862 }
2863
2864 static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2865                               PLCI *plci, APPL *appl, API_PARSE *parms)
2866 {
2867         word Info;
2868         word ncci;
2869         API_PARSE *ncpi;
2870
2871         dbug(1, dprintf("disconnect_b3_req"));
2872
2873         Info = _WRONG_IDENTIFIER;
2874         ncci = (word)(Id >> 16);
2875         if (plci && ncci)
2876         {
2877                 Info = _WRONG_STATE;
2878                 if ((a->ncci_state[ncci] == CONNECTED)
2879                     || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2880                     || (a->ncci_state[ncci] == INC_CON_PENDING)
2881                     || (a->ncci_state[ncci] == INC_ACT_PENDING))
2882                 {
2883                         a->ncci_state[ncci] = OUTG_DIS_PENDING;
2884                         channel_request_xon(plci, a->ncci_ch[ncci]);
2885                         channel_xmit_xon(plci);
2886
2887                         if (a->ncci[ncci].data_pending
2888                             && ((plci->B3_prot == B3_TRANSPARENT)
2889                                 || (plci->B3_prot == B3_T30)
2890                                 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
2891                         {
2892                                 plci->send_disc = (byte)ncci;
2893                                 plci->command = 0;
2894                                 return false;
2895                         }
2896                         else
2897                         {
2898                                 cleanup_ncci_data(plci, ncci);
2899
2900                                 if (plci->B3_prot == 2 || plci->B3_prot == 3)
2901                                 {
2902                                         ncpi = &parms[0];
2903                                         if (ncpi->length > 3)
2904                                         {
2905                                                 add_d(plci, (word)(ncpi->length - 3), (byte *)&(ncpi->info[4]));
2906                                         }
2907                                 }
2908                                 nl_req_ncci(plci, N_DISC, (byte)ncci);
2909                         }
2910                         return 1;
2911                 }
2912         }
2913         sendf(appl,
2914               _DISCONNECT_B3_R | CONFIRM,
2915               Id,
2916               Number,
2917               "w", Info);
2918         return false;
2919 }
2920
2921 static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2922                               PLCI *plci, APPL *appl, API_PARSE *parms)
2923 {
2924         word ncci;
2925         word i;
2926
2927         ncci = (word)(Id >> 16);
2928         dbug(1, dprintf("disconnect_b3_res(ncci=0x%x", ncci));
2929         if (plci && ncci) {
2930                 plci->requested_options_conn = 0;
2931                 plci->fax_connect_info_length = 0;
2932                 plci->ncpi_state = 0x00;
2933                 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2934                     && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
2935                 {
2936                         plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
2937                 }
2938                 for (i = 0; i < MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i] != (byte)ncci; i++);
2939                 if (i < MAX_CHANNELS_PER_PLCI) {
2940                         if (plci->channels)plci->channels--;
2941                         for (; i < MAX_CHANNELS_PER_PLCI - 1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i + 1];
2942                         plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI - 1] = 0;
2943
2944                         ncci_free_receive_buffers(plci, ncci);
2945
2946                         if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
2947                                 if (plci->State == SUSPENDING) {
2948                                         sendf(plci->appl,
2949                                               _FACILITY_I,
2950                                               Id & 0xffffL,
2951                                               0,
2952                                               "ws", (word)3, "\x03\x04\x00\x00");
2953                                         sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
2954                                 }
2955                                 plci_remove(plci);
2956                                 plci->State = IDLE;
2957                         }
2958                 }
2959                 else
2960                 {
2961                         if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
2962                             && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
2963                             && (a->ncci_state[ncci] == INC_DIS_PENDING))
2964                         {
2965                                 ncci_free_receive_buffers(plci, ncci);
2966
2967                                 nl_req_ncci(plci, N_EDATA, (byte)ncci);
2968
2969                                 plci->adapter->ncci_state[ncci] = IDLE;
2970                                 start_internal_command(Id, plci, fax_disconnect_command);
2971                                 return 1;
2972                         }
2973                 }
2974         }
2975         return false;
2976 }
2977
2978 static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2979                         PLCI *plci, APPL *appl, API_PARSE *parms)
2980 {
2981         NCCI *ncci_ptr;
2982         DATA_B3_DESC *data;
2983         word Info;
2984         word ncci;
2985         word i;
2986
2987         dbug(1, dprintf("data_b3_req"));
2988
2989         Info = _WRONG_IDENTIFIER;
2990         ncci = (word)(Id >> 16);
2991         dbug(1, dprintf("ncci=0x%x, plci=0x%x", ncci, plci));
2992
2993         if (plci && ncci)
2994         {
2995                 Info = _WRONG_STATE;
2996                 if ((a->ncci_state[ncci] == CONNECTED)
2997                     || (a->ncci_state[ncci] == INC_ACT_PENDING))
2998                 {
2999                         /* queue data */
3000                         ncci_ptr = &(a->ncci[ncci]);
3001                         i = ncci_ptr->data_out + ncci_ptr->data_pending;
3002                         if (i >= MAX_DATA_B3)
3003                                 i -= MAX_DATA_B3;
3004                         data = &(ncci_ptr->DBuffer[i]);
3005                         data->Number = Number;
3006                         if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3007                             && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3008                         {
3009
3010                                 data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3011
3012                         }
3013                         else
3014                                 data->P = TransmitBufferSet(appl, *(dword *)parms[0].info);
3015                         data->Length = GET_WORD(parms[1].info);
3016                         data->Handle = GET_WORD(parms[2].info);
3017                         data->Flags = GET_WORD(parms[3].info);
3018                         (ncci_ptr->data_pending)++;
3019
3020                         /* check for delivery confirmation */
3021                         if (data->Flags & 0x0004)
3022                         {
3023                                 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3024                                 if (i >= MAX_DATA_ACK)
3025                                         i -= MAX_DATA_ACK;
3026                                 ncci_ptr->DataAck[i].Number = data->Number;
3027                                 ncci_ptr->DataAck[i].Handle = data->Handle;
3028                                 (ncci_ptr->data_ack_pending)++;
3029                         }
3030
3031                         send_data(plci);
3032                         return false;
3033                 }
3034         }
3035         if (appl)
3036         {
3037                 if (plci)
3038                 {
3039                         if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3040                             && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3041                         {
3042
3043                                 TransmitBufferFree(appl, (byte *)(long)(*((dword *)(parms[0].info))));
3044
3045                         }
3046                 }
3047                 sendf(appl,
3048                       _DATA_B3_R | CONFIRM,
3049                       Id,
3050                       Number,
3051                       "ww", GET_WORD(parms[2].info), Info);
3052         }
3053         return false;
3054 }
3055
3056 static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3057                         PLCI *plci, APPL *appl, API_PARSE *parms)
3058 {
3059         word n;
3060         word ncci;
3061         word NCCIcode;
3062
3063         dbug(1, dprintf("data_b3_res"));
3064
3065         ncci = (word)(Id >> 16);
3066         if (plci && ncci) {
3067                 n = GET_WORD(parms[0].info);
3068                 dbug(1, dprintf("free(%d)", n));
3069                 NCCIcode = ncci | (((word) a->Id) << 8);
3070                 if (n < appl->MaxBuffer &&
3071                     appl->DataNCCI[n] == NCCIcode &&
3072                     (byte)(appl->DataFlags[n] >> 8) == plci->Id) {
3073                         dbug(1, dprintf("found"));
3074                         appl->DataNCCI[n] = 0;
3075
3076                         if (channel_can_xon(plci, a->ncci_ch[ncci])) {
3077                                 channel_request_xon(plci, a->ncci_ch[ncci]);
3078                         }
3079                         channel_xmit_xon(plci);
3080
3081                         if (appl->DataFlags[n] & 4) {
3082                                 nl_req_ncci(plci, N_DATA_ACK, (byte)ncci);
3083                                 return 1;
3084                         }
3085                 }
3086         }
3087         return false;
3088 }
3089
3090 static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3091                          PLCI *plci, APPL *appl, API_PARSE *parms)
3092 {
3093         word Info;
3094         word ncci;
3095
3096         dbug(1, dprintf("reset_b3_req"));
3097
3098         Info = _WRONG_IDENTIFIER;
3099         ncci = (word)(Id >> 16);
3100         if (plci && ncci)
3101         {
3102                 Info = _WRONG_STATE;
3103                 switch (plci->B3_prot)
3104                 {
3105                 case B3_ISO8208:
3106                 case B3_X25_DCE:
3107                         if (a->ncci_state[ncci] == CONNECTED)
3108                         {
3109                                 nl_req_ncci(plci, N_RESET, (byte)ncci);
3110                                 send_req(plci);
3111                                 Info = GOOD;
3112                         }
3113                         break;
3114                 case B3_TRANSPARENT:
3115                         if (a->ncci_state[ncci] == CONNECTED)
3116                         {
3117                                 start_internal_command(Id, plci, reset_b3_command);
3118                                 Info = GOOD;
3119                         }
3120                         break;
3121                 }
3122         }
3123         /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3124         sendf(appl,
3125               _RESET_B3_R | CONFIRM,
3126               Id,
3127               Number,
3128               "w", Info);
3129         return false;
3130 }
3131
3132 static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3133                          PLCI *plci, APPL *appl, API_PARSE *parms)
3134 {
3135         word ncci;
3136
3137         dbug(1, dprintf("reset_b3_res"));
3138
3139         ncci = (word)(Id >> 16);
3140         if (plci && ncci) {
3141                 switch (plci->B3_prot)
3142                 {
3143                 case B3_ISO8208:
3144                 case B3_X25_DCE:
3145                         if (a->ncci_state[ncci] == INC_RES_PENDING)
3146                         {
3147                                 a->ncci_state[ncci] = CONNECTED;
3148                                 nl_req_ncci(plci, N_RESET_ACK, (byte)ncci);
3149                                 return true;
3150                         }
3151                         break;
3152                 }
3153         }
3154         return false;
3155 }
3156
3157 static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3158                                  PLCI *plci, APPL *appl, API_PARSE *parms)
3159 {
3160         word ncci;
3161         API_PARSE *ncpi;
3162         byte req;
3163
3164         dbug(1, dprintf("connect_b3_t90_a_res"));
3165
3166         ncci = (word)(Id >> 16);
3167         if (plci && ncci) {
3168                 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
3169                         a->ncci_state[ncci] = CONNECTED;
3170                 }
3171                 else if (a->ncci_state[ncci] == INC_CON_PENDING) {
3172                         a->ncci_state[ncci] = CONNECTED;
3173
3174                         req = N_CONNECT_ACK;
3175
3176                         /* parms[0]==0 for CAPI original message definition! */
3177                         if (parms[0].info) {
3178                                 ncpi = &parms[1];
3179                                 if (ncpi->length > 2) {
3180                                         if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
3181                                         add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
3182                                 }
3183                         }
3184                         nl_req_ncci(plci, req, (byte)ncci);
3185                         return 1;
3186                 }
3187         }
3188         return false;
3189 }
3190
3191
3192 static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3193                          PLCI *plci, APPL *appl, API_PARSE *msg)
3194 {
3195         word Info = 0;
3196         word i;
3197         byte tel;
3198         API_PARSE bp_parms[7];
3199
3200         if (!plci || !msg)
3201         {
3202                 Info = _WRONG_IDENTIFIER;
3203         }
3204         else
3205         {
3206                 dbug(1, dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3207                                 msg->length, plci->Id, plci->tel, plci->NL.Id, plci->appl, plci->SuppState));
3208                 dbug(1, dprintf("PlciState=0x%x", plci->State));
3209                 for (i = 0; i < 7; i++) bp_parms[i].length = 0;
3210
3211                 /* check if no channel is open, no B3 connected only */
3212                 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3213                     || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3214                 {
3215                         Info = _WRONG_STATE;
3216                 }
3217                 /* check message format and fill bp_parms pointer */
3218                 else if (msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3219                 {
3220                         Info = _WRONG_MESSAGE_FORMAT;
3221                 }
3222                 else
3223                 {
3224                         if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT)) /* send alert tone inband to the network, */
3225                         {                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3226                                 if (Id & EXT_CONTROLLER)
3227                                 {
3228                                         sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3229                                         return 0;
3230                                 }
3231                                 plci->State = INC_CON_CONNECTED_ALERT;
3232                                 plci->appl = appl;
3233                                 __clear_bit(appl->Id - 1, plci->c_ind_mask_table);
3234                                 dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
3235                                 /* disconnect the other appls its quasi a connect */
3236                                 for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
3237                                         sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3238                         }
3239
3240                         api_save_msg(msg, "s", &plci->saved_msg);
3241                         tel = plci->tel;
3242                         if (Id & EXT_CONTROLLER)
3243                         {
3244                                 if (tel) /* external controller in use by this PLCI */
3245                                 {
3246                                         if (a->AdvSignalAppl && a->AdvSignalAppl != appl)
3247                                         {
3248                                                 dbug(1, dprintf("Ext_Ctrl in use 1"));
3249                                                 Info = _WRONG_STATE;
3250                                         }
3251                                 }
3252                                 else  /* external controller NOT in use by this PLCI ? */
3253                                 {
3254                                         if (a->AdvSignalPLCI)
3255                                         {
3256                                                 dbug(1, dprintf("Ext_Ctrl in use 2"));
3257                                                 Info = _WRONG_STATE;
3258                                         }
3259                                         else /* activate the codec */
3260                                         {
3261                                                 dbug(1, dprintf("Ext_Ctrl start"));
3262                                                 if (AdvCodecSupport(a, plci, appl, 0))
3263                                                 {
3264                                                         dbug(1, dprintf("Error in codec procedures"));
3265                                                         Info = _WRONG_STATE;
3266                                                 }
3267                                                 else if (plci->spoofed_msg == SPOOFING_REQUIRED) /* wait until codec is active */
3268                                                 {
3269                                                         plci->spoofed_msg = AWAITING_SELECT_B;
3270                                                         plci->internal_command = BLOCK_PLCI; /* lock other commands */
3271                                                         plci->command = 0;
3272                                                         dbug(1, dprintf("continue if codec loaded"));
3273                                                         return false;
3274                                                 }
3275                                         }
3276                                 }
3277                         }
3278                         else /* external controller bit is OFF */
3279                         {
3280                                 if (tel) /* external controller in use, need to switch off */
3281                                 {
3282                                         if (a->AdvSignalAppl == appl)
3283                                         {
3284                                                 CodecIdCheck(a, plci);
3285                                                 plci->tel = 0;
3286                                                 plci->adv_nl = 0;
3287                                                 dbug(1, dprintf("Ext_Ctrl disable"));
3288                                         }
3289                                         else
3290                                         {
3291                                                 dbug(1, dprintf("Ext_Ctrl not requested"));
3292                                         }
3293                                 }
3294                         }
3295                         if (!Info)
3296                         {
3297                                 if (plci->call_dir & CALL_DIR_OUT)
3298                                         plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3299                                 else if (plci->call_dir & CALL_DIR_IN)
3300                                         plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3301                                 start_internal_command(Id, plci, select_b_command);
3302                                 return false;
3303                         }
3304                 }
3305         }
3306         sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", Info);
3307         return false;
3308 }
3309
3310 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3311                              PLCI *plci, APPL *appl, API_PARSE *parms)
3312 {
3313         word command;
3314         word i;
3315         word ncci;
3316         API_PARSE *m;
3317         API_PARSE m_parms[5];
3318         word codec;
3319         byte req;
3320         byte ch;
3321         byte dir;
3322         static byte chi[2] = {0x01, 0x00};
3323         static byte lli[2] = {0x01, 0x00};
3324         static byte codec_cai[2] = {0x01, 0x01};
3325         static byte null_msg = {0};
3326         static API_PARSE null_parms = { 0, &null_msg };
3327         PLCI *v_plci;
3328         word Info = 0;
3329
3330         dbug(1, dprintf("manufacturer_req"));
3331         for (i = 0; i < 5; i++) m_parms[i].length = 0;
3332
3333         if (GET_DWORD(parms[0].info) != _DI_MANU_ID) {
3334                 Info = _WRONG_MESSAGE_FORMAT;
3335         }
3336         command = GET_WORD(parms[1].info);
3337         m = &parms[2];
3338         if (!Info)
3339         {
3340                 switch (command) {
3341                 case _DI_ASSIGN_PLCI:
3342                         if (api_parse(&m->info[1], (word)m->length, "wbbs", m_parms)) {
3343                                 Info = _WRONG_MESSAGE_FORMAT;
3344                                 break;
3345                         }
3346                         codec = GET_WORD(m_parms[0].info);
3347                         ch = m_parms[1].info[0];
3348                         dir = m_parms[2].info[0];
3349                         if ((i = get_plci(a))) {
3350                                 plci = &a->plci[i - 1];
3351                                 plci->appl = appl;
3352                                 plci->command = _MANUFACTURER_R;
3353                                 plci->m_command = command;
3354                                 plci->number = Number;
3355                                 plci->State = LOCAL_CONNECT;
3356                                 Id = (((word)plci->Id << 8) | plci->adapter->Id | 0x80);
3357                                 dbug(1, dprintf("ManCMD,plci=0x%x", Id));
3358
3359                                 if ((ch == 1 || ch == 2) && (dir <= 2)) {
3360                                         chi[1] = (byte)(0x80 | ch);
3361                                         lli[1] = 0;
3362                                         plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3363                                         switch (codec)
3364                                         {
3365                                         case 0:
3366                                                 Info = add_b1(plci, &m_parms[3], 0, 0);
3367                                                 break;
3368                                         case 1:
3369                                                 add_p(plci, CAI, codec_cai);
3370                                                 break;
3371                                                 /* manual 'swich on' to the codec support without signalling */
3372                                                 /* first 'assign plci' with this function, then use */
3373                                         case 2:
3374                                                 if (AdvCodecSupport(a, plci, appl, 0)) {
3375                                                         Info = _RESOURCE_ERROR;
3376                                                 }
3377                                                 else {
3378                                                         Info = add_b1(plci, &null_parms, 0, B1_FACILITY_LOCAL);
3379                                                         lli[1] = 0x10; /* local call codec stream */
3380                                                 }
3381                                                 break;
3382                                         }
3383
3384                                         plci->State = LOCAL_CONNECT;
3385                                         plci->manufacturer = true;
3386                                         plci->command = _MANUFACTURER_R;
3387                                         plci->m_command = command;
3388                                         plci->number = Number;
3389
3390                                         if (!Info)
3391                                         {
3392                                                 add_p(plci, LLI, lli);
3393                                                 add_p(plci, CHI, chi);
3394                                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
3395                                                 sig_req(plci, ASSIGN, DSIG_ID);
3396
3397                                                 if (!codec)
3398                                                 {
3399                                                         Info = add_b23(plci, &m_parms[3]);
3400                                                         if (!Info)
3401                                                         {
3402                                                                 nl_req_ncci(plci, ASSIGN, 0);
3403                                                                 send_req(plci);
3404                                                         }
3405                                                 }
3406                                                 if (!Info)
3407                                                 {
3408                                                         dbug(1, dprintf("dir=0x%x,spoof=0x%x", dir, plci->spoofed_msg));
3409                                                         if (plci->spoofed_msg == SPOOFING_REQUIRED)
3410                                                         {
3411                                                                 api_save_msg(m_parms, "wbbs", &plci->saved_msg);
3412                                                                 plci->spoofed_msg = AWAITING_MANUF_CON;
3413                                                                 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3414                                                                 plci->command = 0;
3415                                                                 send_req(plci);
3416                                                                 return false;
3417                                                         }
3418                                                         if (dir == 1) {
3419                                                                 sig_req(plci, CALL_REQ, 0);
3420                                                         }
3421                                                         else if (!dir) {
3422                                                                 sig_req(plci, LISTEN_REQ, 0);
3423                                                         }
3424                                                         send_req(plci);
3425                                                 }
3426                                                 else
3427                                                 {
3428                                                         sendf(appl,
3429                                                               _MANUFACTURER_R | CONFIRM,
3430                                                               Id,
3431                                                               Number,
3432                                                               "dww", _DI_MANU_ID, command, Info);
3433                                                         return 2;
3434                                                 }
3435                                         }
3436                                 }
3437                         }
3438                         else  Info = _OUT_OF_PLCI;
3439                         break;
3440
3441                 case _DI_IDI_CTRL:
3442                         if (!plci)
3443                         {
3444                                 Info = _WRONG_IDENTIFIER;
3445                                 break;
3446                         }
3447                         if (api_parse(&m->info[1], (word)m->length, "bs", m_parms)) {
3448                                 Info = _WRONG_MESSAGE_FORMAT;
3449                                 break;
3450                         }
3451                         req = m_parms[0].info[0];
3452                         plci->command = _MANUFACTURER_R;
3453                         plci->m_command = command;
3454                         plci->number = Number;
3455                         if (req == CALL_REQ)
3456                         {
3457                                 plci->b_channel = getChannel(&m_parms[1]);
3458                                 mixer_set_bchannel_id_esc(plci, plci->b_channel);
3459                                 if (plci->spoofed_msg == SPOOFING_REQUIRED)
3460                                 {
3461                                         plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3462                                         plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3463                                         plci->command = 0;
3464                                         break;
3465                                 }
3466                         }
3467                         else if (req == LAW_REQ)
3468                         {
3469                                 plci->cr_enquiry = true;
3470                         }
3471                         add_ss(plci, FTY, &m_parms[1]);
3472                         sig_req(plci, req, 0);
3473                         send_req(plci);
3474                         if (req == HANGUP)
3475                         {
3476                                 if (plci->NL.Id && !plci->nl_remove_id)
3477                                 {
3478                                         if (plci->channels)
3479                                         {
3480                                                 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
3481                                                 {
3482                                                         if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3483                                                         {
3484                                                                 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3485                                                                 cleanup_ncci_data(plci, ncci);
3486                                                                 nl_req_ncci(plci, N_DISC, (byte)ncci);
3487                                                         }
3488                                                 }
3489                                         }
3490                                         mixer_remove(plci);
3491                                         nl_req_ncci(plci, REMOVE, 0);
3492                                         send_req(plci);
3493                                 }
3494                         }
3495                         break;
3496
3497                 case _DI_SIG_CTRL:
3498                         /* signalling control for loop activation B-channel */
3499                         if (!plci)
3500                         {
3501                                 Info = _WRONG_IDENTIFIER;
3502                                 break;
3503                         }
3504                         if (m->length) {
3505                                 plci->command = _MANUFACTURER_R;
3506                                 plci->number = Number;
3507                                 add_ss(plci, FTY, m);
3508                                 sig_req(plci, SIG_CTRL, 0);
3509                                 send_req(plci);
3510                         }
3511                         else Info = _WRONG_MESSAGE_FORMAT;
3512                         break;
3513
3514                 case _DI_RXT_CTRL:
3515                         /* activation control for receiver/transmitter B-channel */
3516                         if (!plci)
3517                         {
3518                                 Info = _WRONG_IDENTIFIER;
3519                                 break;
3520                         }
3521                         if (m->length) {
3522                                 plci->command = _MANUFACTURER_R;
3523                                 plci->number = Number;
3524                                 add_ss(plci, FTY, m);
3525                                 sig_req(plci, DSP_CTRL, 0);
3526                                 send_req(plci);
3527                         }
3528                         else Info = _WRONG_MESSAGE_FORMAT;
3529                         break;
3530
3531                 case _DI_ADV_CODEC:
3532                 case _DI_DSP_CTRL:
3533                         /* TEL_CTRL commands to support non standard adjustments: */
3534                         /* Ring on/off, Handset micro volume, external micro vol. */
3535                         /* handset+external speaker volume, receiver+transm. gain,*/
3536                         /* handsfree on (hookinfo off), set mixer command         */
3537
3538                         if (command == _DI_ADV_CODEC)
3539                         {
3540                                 if (!a->AdvCodecPLCI) {
3541                                         Info = _WRONG_STATE;
3542                                         break;
3543                                 }
3544                                 v_plci = a->AdvCodecPLCI;
3545                         }
3546                         else
3547                         {
3548                                 if (plci
3549                                     && (m->length >= 3)
3550                                     && (m->info[1] == 0x1c)
3551                                     && (m->info[2] >= 1))
3552                                 {
3553                                         if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3554                                         {
3555                                                 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3556                                                 {
3557                                                         Info = _WRONG_STATE;
3558                                                         break;
3559                                                 }
3560                                                 a->adv_voice_coef_length = m->info[2] - 1;
3561                                                 if (a->adv_voice_coef_length > m->length - 3)
3562                                                         a->adv_voice_coef_length = (byte)(m->length - 3);
3563                                                 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3564                                                         a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3565                                                 for (i = 0; i < a->adv_voice_coef_length; i++)
3566                                                         a->adv_voice_coef_buffer[i] = m->info[4 + i];
3567                                                 if (plci->B1_facilities & B1_FACILITY_VOICE)
3568                                                         adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
3569                                                 break;
3570                                         }
3571                                         else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3572                                         {
3573                                                 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3574                                                 {
3575                                                         Info = _FACILITY_NOT_SUPPORTED;
3576                                                         break;
3577                                                 }
3578
3579                                                 plci->dtmf_parameter_length = m->info[2] - 1;
3580                                                 if (plci->dtmf_parameter_length > m->length - 3)
3581                                                         plci->dtmf_parameter_length = (byte)(m->length - 3);
3582                                                 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3583                                                         plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3584                                                 for (i = 0; i < plci->dtmf_parameter_length; i++)
3585                                                         plci->dtmf_parameter_buffer[i] = m->info[4 + i];
3586                                                 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3587                                                         dtmf_parameter_write(plci);
3588                                                 break;
3589
3590                                         }
3591                                 }
3592                                 v_plci = plci;
3593                         }
3594
3595                         if (!v_plci)
3596                         {
3597                                 Info = _WRONG_IDENTIFIER;
3598                                 break;
3599                         }
3600                         if (m->length) {
3601                                 add_ss(v_plci, FTY, m);
3602                                 sig_req(v_plci, TEL_CTRL, 0);
3603                                 send_req(v_plci);
3604                         }
3605                         else Info = _WRONG_MESSAGE_FORMAT;
3606
3607                         break;
3608
3609                 case _DI_OPTIONS_REQUEST:
3610                         if (api_parse(&m->info[1], (word)m->length, "d", m_parms)) {
3611                                 Info = _WRONG_MESSAGE_FORMAT;
3612                                 break;
3613                         }
3614                         if (GET_DWORD(m_parms[0].info) & ~a->man_profile.private_options)
3615                         {
3616                                 Info = _FACILITY_NOT_SUPPORTED;
3617                                 break;
3618                         }
3619                         a->requested_options_table[appl->Id - 1] = GET_DWORD(m_parms[0].info);
3620                         break;
3621
3622
3623
3624                 default:
3625                         Info = _WRONG_MESSAGE_FORMAT;
3626                         break;
3627                 }
3628         }
3629
3630         sendf(appl,
3631               _MANUFACTURER_R | CONFIRM,
3632               Id,
3633               Number,
3634               "dww", _DI_MANU_ID, command, Info);
3635         return false;
3636 }
3637
3638
3639 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3640                              PLCI *plci, APPL *appl, API_PARSE *msg)
3641 {
3642         word indication;
3643
3644         API_PARSE m_parms[3];
3645         API_PARSE *ncpi;
3646         API_PARSE fax_parms[9];
3647         word i;
3648         byte len;
3649
3650
3651         dbug(1, dprintf("manufacturer_res"));
3652
3653         if ((msg[0].length == 0)
3654             || (msg[1].length == 0)
3655             || (GET_DWORD(msg[0].info) != _DI_MANU_ID))
3656         {
3657                 return false;
3658         }
3659         indication = GET_WORD(msg[1].info);
3660         switch (indication)
3661         {
3662
3663         case _DI_NEGOTIATE_B3:
3664                 if (!plci)
3665                         break;
3666                 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3667                     || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3668                 {
3669                         dbug(1, dprintf("wrong state for NEGOTIATE_B3 parameters"));
3670                         break;
3671                 }
3672                 if (api_parse(&msg[2].info[1], msg[2].length, "ws", m_parms))
3673                 {
3674                         dbug(1, dprintf("wrong format in NEGOTIATE_B3 parameters"));
3675                         break;
3676                 }
3677                 ncpi = &m_parms[1];
3678                 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
3679                 if (plci->fax_connect_info_length < len)
3680                 {
3681                         ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3682                         ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3683                 }
3684                 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3685                 {
3686                         dbug(1, dprintf("non-standard facilities info missing or wrong format"));
3687                 }
3688                 else
3689                 {
3690                         if (plci->fax_connect_info_length <= len)
3691                                 plci->fax_connect_info_buffer[len] = 0;
3692                         len += 1 + plci->fax_connect_info_buffer[len];
3693                         if (plci->fax_connect_info_length <= len)
3694                                 plci->fax_connect_info_buffer[len] = 0;
3695                         len += 1 + plci->fax_connect_info_buffer[len];
3696                         if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3697                                 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3698                         plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3699                         for (i = 0; i < fax_parms[7].length; i++)
3700                                 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
3701                 }
3702                 plci->fax_connect_info_length = len;
3703                 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3704                 start_internal_command(Id, plci, fax_edata_ack_command);
3705                 break;
3706
3707         }
3708         return false;
3709 }
3710
3711 /*------------------------------------------------------------------*/
3712 /* IDI callback function                                            */
3713 /*------------------------------------------------------------------*/
3714
3715 void callback(ENTITY *e)
3716 {
3717         DIVA_CAPI_ADAPTER *a;
3718         APPL *appl;
3719         PLCI *plci;
3720         CAPI_MSG *m;
3721         word i, j;
3722         byte rc;
3723         byte ch;
3724         byte req;
3725         byte global_req;
3726         int no_cancel_rc;
3727
3728         dbug(1, dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3729                         (e->user[0] + 1) & 0x7fff, e->Id, e->Req, e->Rc, e->Ind));
3730
3731         a = &(adapter[(byte)e->user[0]]);
3732         plci = &(a->plci[e->user[1]]);
3733         no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3734
3735         /*
3736           If new protocol code and new XDI is used then CAPI should work
3737           fully in accordance with IDI cpec an look on callback field instead
3738           of Rc field for return codes.
3739         */
3740         if (((e->complete == 0xff) && no_cancel_rc) ||
3741             (e->Rc && !no_cancel_rc)) {
3742                 rc = e->Rc;
3743                 ch = e->RcCh;
3744                 req = e->Req;
3745                 e->Rc = 0;
3746
3747                 if (e->user[0] & 0x8000)
3748                 {
3749                         /*
3750                           If REMOVE request was sent then we have to wait until
3751                           return code with Id set to zero arrives.
3752                           All other return codes should be ignored.
3753                         */
3754                         if (req == REMOVE)
3755                         {
3756                                 if (e->Id)
3757                                 {
3758                                         dbug(1, dprintf("cancel RC in REMOVE state"));
3759                                         return;
3760                                 }
3761                                 channel_flow_control_remove(plci);
3762                                 for (i = 0; i < 256; i++)
3763                                 {
3764                                         if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3765                                                 a->FlowControlIdTable[i] = 0;
3766                                 }
3767                                 plci->nl_remove_id = 0;
3768                                 if (plci->rx_dma_descriptor > 0) {
3769                                         diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3770                                         plci->rx_dma_descriptor = 0;
3771                                 }
3772                         }
3773                         if (rc == OK_FC)
3774                         {
3775                                 a->FlowControlIdTable[ch] = e->Id;
3776                                 a->FlowControlSkipTable[ch] = 0;
3777
3778                                 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3779                                 a->ch_flow_plci[ch] = plci->Id;
3780                                 plci->nl_req = 0;
3781                         }
3782                         else
3783                         {
3784                                 /*
3785                                   Cancel return codes self, if feature was requested
3786                                 */
3787                                 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3788                                         a->FlowControlIdTable[ch] = 0;
3789                                         if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3790                                                 dbug(3, dprintf("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3791                                                 return;
3792                                         }
3793                                 }
3794
3795                                 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3796                                 {
3797                                         a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3798                                         if (ch == e->ReqCh)
3799                                                 plci->nl_req = 0;
3800                                 }
3801                                 else
3802                                         plci->nl_req = 0;
3803                         }
3804                         if (plci->nl_req)
3805                                 control_rc(plci, 0, rc, ch, 0, true);
3806                         else
3807                         {
3808                                 if (req == N_XON)
3809                                 {
3810                                         channel_x_on(plci, ch);
3811                                         if (plci->internal_command)
3812                                                 control_rc(plci, req, rc, ch, 0, true);
3813                                 }
3814                                 else
3815                                 {
3816                                         if (plci->nl_global_req)
3817                                         {
3818                                                 global_req = plci->nl_global_req;
3819                                                 plci->nl_global_req = 0;
3820                                                 if (rc != ASSIGN_OK) {
3821                                                         e->Id = 0;
3822                                                         if (plci->rx_dma_descriptor > 0) {
3823                                                                 diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3824                                                                 plci->rx_dma_descriptor = 0;
3825                                                         }
3826                                                 }
3827                                                 channel_xmit_xon(plci);
3828                                                 control_rc(plci, 0, rc, ch, global_req, true);
3829                                         }
3830                                         else if (plci->data_sent)
3831                                         {
3832                                                 channel_xmit_xon(plci);
3833                                                 plci->data_sent = false;
3834                                                 plci->NL.XNum = 1;
3835                                                 data_rc(plci, ch);
3836                                                 if (plci->internal_command)
3837                                                         control_rc(plci, req, rc, ch, 0, true);
3838                                         }
3839                                         else
3840                                         {
3841                                                 channel_xmit_xon(plci);
3842                                                 control_rc(plci, req, rc, ch, 0, true);
3843                                         }
3844                                 }
3845                         }
3846                 }
3847                 else
3848                 {
3849                         /*
3850                           If REMOVE request was sent then we have to wait until
3851                           return code with Id set to zero arrives.
3852                           All other return codes should be ignored.
3853                         */
3854                         if (req == REMOVE)
3855                         {
3856                                 if (e->Id)
3857                                 {
3858                                         dbug(1, dprintf("cancel RC in REMOVE state"));
3859                                         return;
3860                                 }
3861                                 plci->sig_remove_id = 0;
3862                         }
3863                         plci->sig_req = 0;
3864                         if (plci->sig_global_req)
3865                         {
3866                                 global_req = plci->sig_global_req;
3867                                 plci->sig_global_req = 0;
3868                                 if (rc != ASSIGN_OK)
3869                                         e->Id = 0;
3870                                 channel_xmit_xon(plci);
3871                                 control_rc(plci, 0, rc, ch, global_req, false);
3872                         }
3873                         else
3874                         {
3875                                 channel_xmit_xon(plci);
3876                                 control_rc(plci, req, rc, ch, 0, false);
3877                         }
3878                 }
3879                 /*
3880                   Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3881                   same callback. Also if new XDI and protocol code used then jump
3882                   direct to finish.
3883                 */
3884                 if (no_cancel_rc) {
3885                         channel_xmit_xon(plci);
3886                         goto capi_callback_suffix;
3887                 }
3888         }
3889
3890         channel_xmit_xon(plci);
3891
3892         if (e->Ind) {
3893                 if (e->user[0] & 0x8000) {
3894                         byte Ind = e->Ind & 0x0f;
3895                         byte Ch = e->IndCh;
3896                         if (((Ind == N_DISC) || (Ind == N_DISC_ACK)) &&
3897                             (a->ch_flow_plci[Ch] == plci->Id)) {
3898                                 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
3899                                         dbug(3, dprintf("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
3900                                 }
3901                                 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
3902                         }
3903                         nl_ind(plci);
3904                         if ((e->RNR != 1) &&
3905                             (a->ch_flow_plci[Ch] == plci->Id) &&
3906                             (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
3907                                 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
3908                                 dbug(3, dprintf("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
3909                         }
3910                 } else {
3911                         sig_ind(plci);
3912                 }
3913                 e->Ind = 0;
3914         }
3915
3916 capi_callback_suffix:
3917
3918         while (!plci->req_in
3919                && !plci->internal_command
3920                && (plci->msg_in_write_pos != plci->msg_in_read_pos))
3921         {
3922                 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
3923
3924                 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
3925
3926                 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
3927                 appl = *((APPL **)(&((byte *)(plci->msg_in_queue))[j + i]));
3928                 dbug(1, dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
3929                                 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
3930                 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
3931                 {
3932                         plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
3933                         plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
3934                 }
3935                 else
3936                 {
3937                         plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
3938                 }
3939                 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
3940                 {
3941                         plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
3942                         plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
3943                 }
3944                 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
3945                 {
3946                         plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
3947                         plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
3948                 }
3949                 i = api_put(appl, m);
3950                 if (i != 0)
3951                 {
3952                         if (m->header.command == _DATA_B3_R)
3953
3954                                 TransmitBufferFree(appl, (byte *)(long)(m->info.data_b3_req.Data));
3955
3956                         dbug(1, dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
3957                         break;
3958                 }
3959
3960                 if (plci->li_notify_update)
3961                 {
3962                         plci->li_notify_update = false;
3963                         mixer_notify_update(plci, false);
3964                 }
3965
3966         }
3967         send_data(plci);
3968         send_req(plci);
3969 }
3970
3971
3972 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
3973                        byte nl_rc)
3974 {
3975         dword Id;
3976         dword rId;
3977         word Number;
3978         word Info = 0;
3979         word i;
3980         word ncci;
3981         DIVA_CAPI_ADAPTER *a;
3982         APPL *appl;
3983         PLCI *rplci;
3984         byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
3985         byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
3986
3987         if (!plci) {
3988                 dbug(0, dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
3989                 return;
3990         }
3991         dbug(1, dprintf("req0_in/out=%d/%d", plci->req_in, plci->req_out));
3992         if (plci->req_in != plci->req_out)
3993         {
3994                 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
3995                 {
3996                         dbug(1, dprintf("req_1return"));
3997                         return;
3998                 }
3999                 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4000         }
4001         plci->req_in = plci->req_in_start = plci->req_out = 0;
4002         dbug(1, dprintf("control_rc"));
4003
4004         appl = plci->appl;
4005         a = plci->adapter;
4006         ncci = a->ch_ncci[ch];
4007         if (appl)
4008         {
4009                 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4010                 if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4011                 Number = plci->number;
4012                 dbug(1, dprintf("Contr_RC-Id=%08lx,plci=%x,tel=%x, entity=0x%x, command=0x%x, int_command=0x%x", Id, plci->Id, plci->tel, plci->Sig.Id, plci->command, plci->internal_command));
4013                 dbug(1, dprintf("channels=0x%x", plci->channels));
4014                 if (plci_remove_check(plci))
4015                         return;
4016                 if (req == REMOVE && rc == ASSIGN_OK)
4017                 {
4018                         sig_req(plci, HANGUP, 0);
4019                         sig_req(plci, REMOVE, 0);
4020                         send_req(plci);
4021                 }
4022                 if (plci->command)
4023                 {
4024                         switch (plci->command)
4025                         {
4026                         case C_HOLD_REQ:
4027                                 dbug(1, dprintf("HoldRC=0x%x", rc));
4028                                 SSparms[1] = (byte)S_HOLD;
4029                                 if (rc != OK)
4030                                 {
4031                                         plci->SuppState = IDLE;
4032                                         Info = 0x2001;
4033                                 }
4034                                 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4035                                 break;
4036
4037                         case C_RETRIEVE_REQ:
4038                                 dbug(1, dprintf("RetrieveRC=0x%x", rc));
4039                                 SSparms[1] = (byte)S_RETRIEVE;
4040                                 if (rc != OK)
4041                                 {
4042                                         plci->SuppState = CALL_HELD;
4043                                         Info = 0x2001;
4044                                 }
4045                                 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4046                                 break;
4047
4048                         case _INFO_R:
4049                                 dbug(1, dprintf("InfoRC=0x%x", rc));
4050                                 if (rc != OK) Info = _WRONG_STATE;
4051                                 sendf(appl, _INFO_R | CONFIRM, Id, Number, "w", Info);
4052                                 break;
4053
4054                         case _CONNECT_R:
4055                                 dbug(1, dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x", req, rc, global_req, nl_rc));
4056                                 if (plci->State == INC_DIS_PENDING)
4057                                         break;
4058                                 if (plci->Sig.Id != 0xff)
4059                                 {
4060                                         if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4061                                             || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4062                                         {
4063                                                 dbug(1, dprintf("No more IDs/Call_Req failed"));
4064                                                 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4065                                                 plci_remove(plci);
4066                                                 plci->State = IDLE;
4067                                                 break;
4068                                         }
4069                                         if (plci->State != LOCAL_CONNECT) plci->State = OUTG_CON_PENDING;
4070                                         sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4071                                 }
4072                                 else /* D-ch activation */
4073                                 {
4074                                         if (rc != ASSIGN_OK)
4075                                         {
4076                                                 dbug(1, dprintf("No more IDs/X.25 Call_Req failed"));
4077                                                 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4078                                                 plci_remove(plci);
4079                                                 plci->State = IDLE;
4080                                                 break;
4081                                         }
4082                                         sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4083                                         sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "sss", "", "", "");
4084                                         plci->State = INC_ACT_PENDING;
4085                                 }
4086                                 break;
4087
4088                         case _CONNECT_I | RESPONSE:
4089                                 if (plci->State != INC_DIS_PENDING)
4090                                         plci->State = INC_CON_ACCEPT;
4091                                 break;
4092
4093                         case _DISCONNECT_R:
4094                                 if (plci->State == INC_DIS_PENDING)
4095                                         break;
4096                                 if (plci->Sig.Id != 0xff)
4097                                 {
4098                                         plci->State = OUTG_DIS_PENDING;
4099                                         sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
4100                                 }
4101                                 break;
4102
4103                         case SUSPEND_REQ:
4104                                 break;
4105
4106                         case RESUME_REQ:
4107                                 break;
4108
4109                         case _CONNECT_B3_R:
4110                                 if (rc != OK)
4111                                 {
4112                                         sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
4113                                         break;
4114                                 }
4115                                 ncci = get_ncci(plci, ch, 0);
4116                                 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4117                                 plci->channels++;
4118                                 if (req == N_RESET)
4119                                 {
4120                                         a->ncci_state[ncci] = INC_ACT_PENDING;
4121                                         sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4122                                         sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
4123                                 }
4124                                 else
4125                                 {
4126                                         a->ncci_state[ncci] = OUTG_CON_PENDING;
4127                                         sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4128                                 }
4129                                 break;
4130
4131                         case _CONNECT_B3_I | RESPONSE:
4132                                 break;
4133
4134                         case _RESET_B3_R:
4135 /*        sendf(appl, _RESET_B3_R | CONFIRM, Id, Number, "w", 0);*/
4136                                 break;
4137
4138                         case _DISCONNECT_B3_R:
4139                                 sendf(appl, _DISCONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4140                                 break;
4141
4142                         case _MANUFACTURER_R:
4143                                 break;
4144
4145                         case PERM_LIST_REQ:
4146                                 if (rc != OK)
4147                                 {
4148                                         Info = _WRONG_IDENTIFIER;
4149                                         sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4150                                         plci_remove(plci);
4151                                 }
4152                                 else
4153                                         sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4154                                 break;
4155
4156                         default:
4157                                 break;
4158                         }
4159                         plci->command = 0;
4160                 }
4161                 else if (plci->internal_command)
4162                 {
4163                         switch (plci->internal_command)
4164                         {
4165                         case BLOCK_PLCI:
4166                                 return;
4167
4168                         case GET_MWI_STATE:
4169                                 if (rc == OK) /* command supported, wait for indication */
4170                                 {
4171                                         return;
4172                                 }
4173                                 plci_remove(plci);
4174                                 break;
4175
4176                                 /* Get Supported Services */
4177                         case GETSERV_REQ_PEND:
4178                                 if (rc == OK) /* command supported, wait for indication */
4179                                 {
4180                                         break;
4181                                 }
4182                                 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4183                                 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", 0, 3, SSstruct);
4184                                 plci_remove(plci);
4185                                 break;
4186
4187                         case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
4188                         case INTERR_NUMBERS_REQ_PEND:
4189                         case CF_START_PEND:                  /* Call Forwarding Start pending */
4190                         case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
4191                         case CCBS_REQUEST_REQ_PEND:
4192                         case CCBS_DEACTIVATE_REQ_PEND:
4193                         case CCBS_INTERROGATE_REQ_PEND:
4194                                 switch (plci->internal_command)
4195                                 {
4196                                 case INTERR_DIVERSION_REQ_PEND:
4197                                         SSparms[1] = S_INTERROGATE_DIVERSION;
4198                                         break;
4199                                 case INTERR_NUMBERS_REQ_PEND:
4200                                         SSparms[1] = S_INTERROGATE_NUMBERS;
4201                                         break;
4202                                 case CF_START_PEND:
4203                                         SSparms[1] = S_CALL_FORWARDING_START;
4204                                         break;
4205                                 case CF_STOP_PEND:
4206                                         SSparms[1] = S_CALL_FORWARDING_STOP;
4207                                         break;
4208                                 case CCBS_REQUEST_REQ_PEND:
4209                                         SSparms[1] = S_CCBS_REQUEST;
4210                                         break;
4211                                 case CCBS_DEACTIVATE_REQ_PEND:
4212                                         SSparms[1] = S_CCBS_DEACTIVATE;
4213                                         break;
4214                                 case CCBS_INTERROGATE_REQ_PEND:
4215                                         SSparms[1] = S_CCBS_INTERROGATE;
4216                                         break;
4217                                 }
4218                                 if (global_req == ASSIGN)
4219                                 {
4220                                         dbug(1, dprintf("AssignDiversion_RC=0x%x/0x%x", req, rc));
4221                                         return;
4222                                 }
4223                                 if (!plci->appl) break;
4224                                 if (rc == ISDN_GUARD_REJ)
4225                                 {
4226                                         Info = _CAPI_GUARD_ERROR;
4227                                 }
4228                                 else if (rc != OK)
4229                                 {
4230                                         Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4231                                 }
4232                                 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7,
4233                                       plci->number, "wws", Info, (word)3, SSparms);
4234                                 if (Info) plci_remove(plci);
4235                                 break;
4236
4237                                 /* 3pty conference pending */
4238                         case PTY_REQ_PEND:
4239                                 if (!plci->relatedPTYPLCI) break;
4240                                 rplci = plci->relatedPTYPLCI;
4241                                 SSparms[1] = plci->ptyState;
4242                                 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4243                                 if (rplci->tel) rId |= EXT_CONTROLLER;
4244                                 if (rc != OK)
4245                                 {
4246                                         Info = 0x300E; /* not supported */
4247                                         plci->relatedPTYPLCI = NULL;
4248                                         plci->ptyState = 0;
4249                                 }
4250                                 sendf(rplci->appl,
4251                                       _FACILITY_R | CONFIRM,
4252                                       rId,
4253                                       plci->number,
4254                                       "wws", Info, (word)3, SSparms);
4255                                 break;
4256
4257                                 /* Explicit Call Transfer pending */
4258                         case ECT_REQ_PEND:
4259                                 dbug(1, dprintf("ECT_RC=0x%x/0x%x", req, rc));
4260                                 if (!plci->relatedPTYPLCI) break;
4261                                 rplci = plci->relatedPTYPLCI;
4262                                 SSparms[1] = S_ECT;
4263                                 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4264                                 if (rplci->tel) rId |= EXT_CONTROLLER;
4265                                 if (rc != OK)
4266                                 {
4267                                         Info = 0x300E; /* not supported */
4268                                         plci->relatedPTYPLCI = NULL;
4269                                         plci->ptyState = 0;
4270                                 }
4271                                 sendf(rplci->appl,
4272                                       _FACILITY_R | CONFIRM,
4273                                       rId,
4274                                       plci->number,
4275                                       "wws", Info, (word)3, SSparms);
4276                                 break;
4277
4278                         case _MANUFACTURER_R:
4279                                 dbug(1, dprintf("_Manufacturer_R=0x%x/0x%x", req, rc));
4280                                 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4281                                 {
4282                                         dbug(1, dprintf("No more IDs"));
4283                                         sendf(appl, _MANUFACTURER_R | CONFIRM, Id, Number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
4284                                         plci_remove(plci);  /* after codec init, internal codec commands pending */
4285                                 }
4286                                 break;
4287
4288                         case _CONNECT_R:
4289                                 dbug(1, dprintf("_Connect_R=0x%x/0x%x", req, rc));
4290                                 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4291                                 {
4292                                         dbug(1, dprintf("No more IDs"));
4293                                         sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4294                                         plci_remove(plci);  /* after codec init, internal codec commands pending */
4295                                 }
4296                                 break;
4297
4298                         case PERM_COD_HOOK:                     /* finished with Hook_Ind */
4299                                 return;
4300
4301                         case PERM_COD_CALL:
4302                                 dbug(1, dprintf("***Codec Connect_Pending A, Rc = 0x%x", rc));
4303                                 plci->internal_command = PERM_COD_CONN_PEND;
4304                                 return;
4305
4306                         case PERM_COD_ASSIGN:
4307                                 dbug(1, dprintf("***Codec Assign A, Rc = 0x%x", rc));
4308                                 if (rc != ASSIGN_OK) break;
4309                                 sig_req(plci, CALL_REQ, 0);
4310                                 send_req(plci);
4311                                 plci->internal_command = PERM_COD_CALL;
4312                                 return;
4313
4314                                 /* Null Call Reference Request pending */
4315                         case C_NCR_FAC_REQ:
4316                                 dbug(1, dprintf("NCR_FAC=0x%x/0x%x", req, rc));
4317                                 if (global_req == ASSIGN)
4318                                 {
4319                                         if (rc == ASSIGN_OK)
4320                                         {
4321                                                 return;
4322                                         }
4323                                         else
4324                                         {
4325                                                 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4326                                                 appl->NullCREnable = false;
4327                                                 plci_remove(plci);
4328                                         }
4329                                 }
4330                                 else if (req == NCR_FACILITY)
4331                                 {
4332                                         if (rc == OK)
4333                                         {
4334                                                 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", 0);
4335                                         }
4336                                         else
4337                                         {
4338                                                 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4339                                                 appl->NullCREnable = false;
4340                                         }
4341                                         plci_remove(plci);
4342                                 }
4343                                 break;
4344
4345                         case HOOK_ON_REQ:
4346                                 if (plci->channels)
4347                                 {
4348                                         if (a->ncci_state[ncci] == CONNECTED)
4349                                         {
4350                                                 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4351                                                 cleanup_ncci_data(plci, ncci);
4352                                                 nl_req_ncci(plci, N_DISC, (byte)ncci);
4353                                         }
4354                                         break;
4355                                 }
4356                                 break;
4357
4358                         case HOOK_OFF_REQ:
4359                                 if (plci->State == INC_DIS_PENDING)
4360                                         break;
4361                                 sig_req(plci, CALL_REQ, 0);
4362                                 send_req(plci);
4363                                 plci->State = OUTG_CON_PENDING;
4364                                 break;
4365
4366
4367                         case MWI_ACTIVATE_REQ_PEND:
4368                         case MWI_DEACTIVATE_REQ_PEND:
4369                                 if (global_req == ASSIGN && rc == ASSIGN_OK)
4370                                 {
4371                                         dbug(1, dprintf("MWI_REQ assigned"));
4372                                         return;
4373                                 }
4374                                 else if (rc != OK)
4375                                 {
4376                                         if (rc == WRONG_IE)
4377                                         {
4378                                                 Info = 0x2007; /* Illegal message parameter coding */
4379                                                 dbug(1, dprintf("MWI_REQ invalid parameter"));
4380                                         }
4381                                         else
4382                                         {
4383                                                 Info = 0x300B; /* not supported */
4384                                                 dbug(1, dprintf("MWI_REQ not supported"));
4385                                         }
4386                                         /* 0x3010: Request not allowed in this state */
4387                                         PUT_WORD(&SSparms[4], 0x300E); /* SS not supported */
4388
4389                                 }
4390                                 if (plci->internal_command == MWI_ACTIVATE_REQ_PEND)
4391                                 {
4392                                         PUT_WORD(&SSparms[1], S_MWI_ACTIVATE);
4393                                 }
4394                                 else PUT_WORD(&SSparms[1], S_MWI_DEACTIVATE);
4395
4396                                 if (plci->cr_enquiry)
4397                                 {
4398                                         sendf(plci->appl,
4399                                               _FACILITY_R | CONFIRM,
4400                                               Id & 0xf,
4401                                               plci->number,
4402                                               "wws", Info, (word)3, SSparms);
4403                                         if (rc != OK) plci_remove(plci);
4404                                 }
4405                                 else
4406                                 {
4407                                         sendf(plci->appl,
4408                                               _FACILITY_R | CONFIRM,
4409                                               Id,
4410                                               plci->number,
4411                                               "wws", Info, (word)3, SSparms);
4412                                 }
4413                                 break;
4414
4415                         case CONF_BEGIN_REQ_PEND:
4416                         case CONF_ADD_REQ_PEND:
4417                         case CONF_SPLIT_REQ_PEND:
4418                         case CONF_DROP_REQ_PEND:
4419                         case CONF_ISOLATE_REQ_PEND:
4420                         case CONF_REATTACH_REQ_PEND:
4421                                 dbug(1, dprintf("CONF_RC=0x%x/0x%x", req, rc));
4422                                 if ((plci->internal_command == CONF_ADD_REQ_PEND) && (!plci->relatedPTYPLCI)) break;
4423                                 rplci = plci;
4424                                 rId = Id;
4425                                 switch (plci->internal_command)
4426                                 {
4427                                 case CONF_BEGIN_REQ_PEND:
4428                                         SSparms[1] = S_CONF_BEGIN;
4429                                         break;
4430                                 case CONF_ADD_REQ_PEND:
4431                                         SSparms[1] = S_CONF_ADD;
4432                                         rplci = plci->relatedPTYPLCI;
4433                                         rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4434                                         break;
4435                                 case CONF_SPLIT_REQ_PEND:
4436                                         SSparms[1] = S_CONF_SPLIT;
4437                                         break;
4438                                 case CONF_DROP_REQ_PEND:
4439                                         SSparms[1] = S_CONF_DROP;
4440                                         break;
4441                                 case CONF_ISOLATE_REQ_PEND:
4442                                         SSparms[1] = S_CONF_ISOLATE;
4443                                         break;
4444                                 case CONF_REATTACH_REQ_PEND:
4445                                         SSparms[1] = S_CONF_REATTACH;
4446                                         break;
4447                                 }
4448
4449                                 if (rc != OK)
4450                                 {
4451                                         Info = 0x300E; /* not supported */
4452                                         plci->relatedPTYPLCI = NULL;
4453                                         plci->ptyState = 0;
4454                                 }
4455                                 sendf(rplci->appl,
4456                                       _FACILITY_R | CONFIRM,
4457                                       rId,
4458                                       plci->number,
4459                                       "wws", Info, (word)3, SSparms);
4460                                 break;
4461
4462                         case VSWITCH_REQ_PEND:
4463                                 if (rc != OK)
4464                                 {
4465                                         if (plci->relatedPTYPLCI)
4466                                         {
4467                                                 plci->relatedPTYPLCI->vswitchstate = 0;
4468                                                 plci->relatedPTYPLCI->vsprot = 0;
4469                                                 plci->relatedPTYPLCI->vsprotdialect = 0;
4470                                         }
4471                                         plci->vswitchstate = 0;
4472                                         plci->vsprot = 0;
4473                                         plci->vsprotdialect = 0;
4474                                 }
4475                                 else
4476                                 {
4477                                         if (plci->relatedPTYPLCI &&
4478                                             plci->vswitchstate == 1 &&
4479                                             plci->relatedPTYPLCI->vswitchstate == 3) /* join complete */
4480                                                 plci->vswitchstate = 3;
4481                                 }
4482                                 break;
4483
4484                                 /* Call Deflection Request pending (SSCT) */
4485                         case CD_REQ_PEND:
4486                                 SSparms[1] = S_CALL_DEFLECTION;
4487                                 if (rc != OK)
4488                                 {
4489                                         Info = 0x300E; /* not supported */
4490                                         plci->appl->CDEnable = 0;
4491                                 }
4492                                 sendf(plci->appl, _FACILITY_R | CONFIRM, Id,
4493                                       plci->number, "wws", Info, (word)3, SSparms);
4494                                 break;
4495
4496                         case RTP_CONNECT_B3_REQ_COMMAND_2:
4497                                 if (rc == OK)
4498                                 {
4499                                         ncci = get_ncci(plci, ch, 0);
4500                                         Id = (Id & 0xffff) | (((dword) ncci) << 16);
4501                                         plci->channels++;
4502                                         a->ncci_state[ncci] = OUTG_CON_PENDING;
4503                                 }
4504
4505                         default:
4506                                 if (plci->internal_command_queue[0])
4507                                 {
4508                                         (*(plci->internal_command_queue[0]))(Id, plci, rc);
4509                                         if (plci->internal_command)
4510                                                 return;
4511                                 }
4512                                 break;
4513                         }
4514                         next_internal_command(Id, plci);
4515                 }
4516         }
4517         else /* appl==0 */
4518         {
4519                 Id = ((word)plci->Id << 8) | plci->adapter->Id;
4520                 if (plci->tel) Id |= EXT_CONTROLLER;
4521
4522                 switch (plci->internal_command)
4523                 {
4524                 case BLOCK_PLCI:
4525                         return;
4526
4527                 case START_L1_SIG_ASSIGN_PEND:
4528                 case REM_L1_SIG_ASSIGN_PEND:
4529                         if (global_req == ASSIGN)
4530                         {
4531                                 break;
4532                         }
4533                         else
4534                         {
4535                                 dbug(1, dprintf("***L1 Req rem PLCI"));
4536                                 plci->internal_command = 0;
4537                                 sig_req(plci, REMOVE, 0);
4538                                 send_req(plci);
4539                         }
4540                         break;
4541
4542                         /* Call Deflection Request pending, just no appl ptr assigned */
4543                 case CD_REQ_PEND:
4544                         SSparms[1] = S_CALL_DEFLECTION;
4545                         if (rc != OK)
4546                         {
4547                                 Info = 0x300E; /* not supported */
4548                         }
4549                         for (i = 0; i < max_appl; i++)
4550                         {
4551                                 if (application[i].CDEnable)
4552                                 {
4553                                         if (!application[i].Id) application[i].CDEnable = 0;
4554                                         else
4555                                         {
4556                                                 sendf(&application[i], _FACILITY_R | CONFIRM, Id,
4557                                                       plci->number, "wws", Info, (word)3, SSparms);
4558                                                 if (Info) application[i].CDEnable = 0;
4559                                         }
4560                                 }
4561                         }
4562                         plci->internal_command = 0;
4563                         break;
4564
4565                 case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4566                         return;
4567
4568                 case PERM_COD_CALL:
4569                         plci->internal_command = PERM_COD_CONN_PEND;
4570                         dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc));
4571                         return;
4572
4573                 case PERM_COD_ASSIGN:
4574                         dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc));
4575                         plci->internal_command = 0;
4576                         if (rc != ASSIGN_OK) break;
4577                         plci->internal_command = PERM_COD_CALL;
4578                         sig_req(plci, CALL_REQ, 0);
4579                         send_req(plci);
4580                         return;
4581
4582                 case LISTEN_SIG_ASSIGN_PEND:
4583                         if (rc == ASSIGN_OK)
4584                         {
4585                                 plci->internal_command = 0;
4586                                 dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci->Sig.Id));
4587                                 add_p(plci, ESC, "\x02\x18\x00");             /* support call waiting */
4588                                 sig_req(plci, INDICATE_REQ, 0);
4589                                 send_req(plci);
4590                         }
4591                         else
4592                         {
4593                                 dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc));
4594                                 a->listen_active--;
4595                                 plci_remove(plci);
4596                                 plci->State = IDLE;
4597                         }
4598                         break;
4599
4600                 case USELAW_REQ:
4601                         if (global_req == ASSIGN)
4602                         {
4603                                 if (rc == ASSIGN_OK)
4604                                 {
4605                                         sig_req(plci, LAW_REQ, 0);
4606                                         send_req(plci);
4607                                         dbug(1, dprintf("Auto-Law assigned"));
4608                                 }
4609                                 else
4610                                 {
4611                                         dbug(1, dprintf("Auto-Law assign failed"));
4612                                         a->automatic_law = 3;
4613                                         plci->internal_command = 0;
4614                                         a->automatic_lawPLCI = NULL;
4615                                 }
4616                                 break;
4617                         }
4618                         else if (req == LAW_REQ && rc == OK)
4619                         {
4620                                 dbug(1, dprintf("Auto-Law initiated"));
4621                                 a->automatic_law = 2;
4622                                 plci->internal_command = 0;
4623                         }
4624                         else
4625                         {
4626                                 dbug(1, dprintf("Auto-Law not supported"));
4627                                 a->automatic_law = 3;
4628                                 plci->internal_command = 0;
4629                                 sig_req(plci, REMOVE, 0);
4630                                 send_req(plci);
4631                                 a->automatic_lawPLCI = NULL;
4632                         }
4633                         break;
4634                 }
4635                 plci_remove_check(plci);
4636         }
4637 }
4638
4639 static void data_rc(PLCI *plci, byte ch)
4640 {
4641         dword Id;
4642         DIVA_CAPI_ADAPTER *a;
4643         NCCI *ncci_ptr;
4644         DATA_B3_DESC *data;
4645         word ncci;
4646
4647         if (plci->appl)
4648         {
4649                 TransmitBufferFree(plci->appl, plci->data_sent_ptr);
4650                 a = plci->adapter;
4651                 ncci = a->ch_ncci[ch];
4652                 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4653                 {
4654                         ncci_ptr = &(a->ncci[ncci]);
4655                         dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr->data_out, ncci_ptr->data_pending));
4656                         if (ncci_ptr->data_pending)
4657                         {
4658                                 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4659                                 if (!(data->Flags & 4) && a->ncci_state[ncci])
4660                                 {
4661                                         Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4662                                         if (plci->tel) Id |= EXT_CONTROLLER;
4663                                         sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, data->Number,
4664                                               "ww", data->Handle, 0);
4665                                 }
4666                                 (ncci_ptr->data_out)++;
4667                                 if (ncci_ptr->data_out == MAX_DATA_B3)
4668                                         ncci_ptr->data_out = 0;
4669                                 (ncci_ptr->data_pending)--;
4670                         }
4671                 }
4672         }
4673 }
4674
4675 static void data_ack(PLCI *plci, byte ch)
4676 {
4677         dword Id;
4678         DIVA_CAPI_ADAPTER *a;
4679         NCCI *ncci_ptr;
4680         word ncci;
4681
4682         a = plci->adapter;
4683         ncci = a->ch_ncci[ch];
4684         ncci_ptr = &(a->ncci[ncci]);
4685         if (ncci_ptr->data_ack_pending)
4686         {
4687                 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4688                 {
4689                         Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4690                         if (plci->tel) Id |= EXT_CONTROLLER;
4691                         sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4692                               "ww", ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle, 0);
4693                 }
4694                 (ncci_ptr->data_ack_out)++;
4695                 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4696                         ncci_ptr->data_ack_out = 0;
4697                 (ncci_ptr->data_ack_pending)--;
4698         }
4699 }
4700
4701 static void sig_ind(PLCI *plci)
4702 {
4703         dword x_Id;
4704         dword Id;
4705         dword rId;
4706         word i;
4707         word cip;
4708         dword cip_mask;
4709         byte *ie;
4710         DIVA_CAPI_ADAPTER *a;
4711         API_PARSE saved_parms[MAX_MSG_PARMS + 1];
4712 #define MAXPARMSIDS 31
4713         byte *parms[MAXPARMSIDS];
4714         byte *add_i[4];
4715         byte *multi_fac_parms[MAX_MULTI_IE];
4716         byte *multi_pi_parms[MAX_MULTI_IE];
4717         byte *multi_ssext_parms[MAX_MULTI_IE];
4718         byte *multi_CiPN_parms[MAX_MULTI_IE];
4719
4720         byte *multi_vswitch_parms[MAX_MULTI_IE];
4721
4722         byte ai_len;
4723         byte *esc_chi = "";
4724         byte *esc_law = "";
4725         byte *pty_cai = "";
4726         byte *esc_cr  = "";
4727         byte *esc_profile = "";
4728
4729         byte facility[256];
4730         PLCI *tplci = NULL;
4731         byte chi[] = "\x02\x18\x01";
4732         byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4733         byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4734         /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4735         /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4736         /* SMSG is situated at the end because its 0 (for compatibility reasons */
4737         /* (see Info_Mask Bit 4, first IE. then the message type)           */
4738         static const word parms_id[] =
4739                 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4740                  UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4741                  RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4742                  CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4743         /* 14 FTY repl by ESC_CHI */
4744         /* 18 PI  repl by ESC_LAW */
4745         /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4746         static const word multi_fac_id[] = {1, FTY};
4747         static const word multi_pi_id[]  = {1, PI};
4748         static const word multi_CiPN_id[]  = {1, OAD};
4749         static const word multi_ssext_id[]  = {1, ESC_SSEXT};
4750
4751         static const word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4752
4753         byte *cau;
4754         word ncci;
4755         byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4756         byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4757         byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4758         byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\x00\x00\x00\x00";
4759         byte force_mt_info = false;
4760         byte dir;
4761         dword d;
4762         word w;
4763
4764         a = plci->adapter;
4765         Id = ((word)plci->Id << 8) | a->Id;
4766         PUT_WORD(&SS_Ind[4], 0x0000);
4767
4768         if (plci->sig_remove_id)
4769         {
4770                 plci->Sig.RNR = 2; /* discard */
4771                 dbug(1, dprintf("SIG discard while remove pending"));
4772                 return;
4773         }
4774         if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4775         dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4776                         Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4777         if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4778         {
4779                 plci->Sig.RNR = 1;
4780                 return;
4781         }
4782         if (plci->Sig.Ind == HANGUP && plci->channels)
4783         {
4784                 plci->Sig.RNR = 1;
4785                 plci->hangup_flow_ctrl_timer++;
4786                 /* recover the network layer after timeout */
4787                 if (plci->hangup_flow_ctrl_timer == 100)
4788                 {
4789                         dbug(1, dprintf("Exceptional disc"));
4790                         plci->Sig.RNR = 0;
4791                         plci->hangup_flow_ctrl_timer = 0;
4792                         for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4793                         {
4794                                 if (a->ncci_plci[ncci] == plci->Id)
4795                                 {
4796                                         cleanup_ncci_data(plci, ncci);
4797                                         if (plci->channels)plci->channels--;
4798                                         if (plci->appl)
4799                                                 sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4800                                 }
4801                         }
4802                         if (plci->appl)
4803                                 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4804                         plci_remove(plci);
4805                         plci->State = IDLE;
4806                 }
4807                 return;
4808         }
4809
4810         /* do first parse the info with no OAD in, because OAD will be converted */
4811         /* first the multiple facility IE, then mult. progress ind.              */
4812         /* then the parameters for the info_ind + conn_ind                       */
4813         IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4814         IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4815         IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4816
4817         IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4818
4819         IndParse(plci, parms_id, parms, 0);
4820         IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4821         esc_chi  = parms[14];
4822         esc_law  = parms[18];
4823         pty_cai  = parms[24];
4824         esc_cr   = parms[25];
4825         esc_profile = parms[27];
4826         if (esc_cr[0] && plci)
4827         {
4828                 if (plci->cr_enquiry && plci->appl)
4829                 {
4830                         plci->cr_enquiry = false;
4831                         /* d = MANU_ID            */
4832                         /* w = m_command          */
4833                         /* b = total length       */
4834                         /* b = indication type    */
4835                         /* b = length of all IEs  */
4836                         /* b = IE1                */
4837                         /* S = IE1 length + cont. */
4838                         /* b = IE2                */
4839                         /* S = IE2 length + cont. */
4840                         sendf(plci->appl,
4841                               _MANUFACTURER_I,
4842                               Id,
4843                               0,
4844                               "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4845                               2 + 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], plci->Sig.Ind, 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], ESC, esc_cr, ESC, esc_law);
4846                 }
4847         }
4848         /* create the additional info structure                                  */
4849         add_i[1] = parms[15]; /* KEY of additional info */
4850         add_i[2] = parms[11]; /* UUI of additional info */
4851         ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4852
4853         /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4854         /* indication returns by the card if requested by the function           */
4855         /* AutomaticLaw() after driver init                                      */
4856         if (a->automatic_law < 4)
4857         {
4858                 if (esc_law[0]) {
4859                         if (esc_law[2]) {
4860                                 dbug(0, dprintf("u-Law selected"));
4861                                 a->u_law = 1;
4862                         }
4863                         else {
4864                                 dbug(0, dprintf("a-Law selected"));
4865                                 a->u_law = 0;
4866                         }
4867                         a->automatic_law = 4;
4868                         if (plci == a->automatic_lawPLCI) {
4869                                 plci->internal_command = 0;
4870                                 sig_req(plci, REMOVE, 0);
4871                                 send_req(plci);
4872                                 a->automatic_lawPLCI = NULL;
4873                         }
4874                 }
4875                 if (esc_profile[0])
4876                 {
4877                         dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4878                                         UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
4879                                         GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
4880                                         GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
4881
4882                         a->profile.Global_Options &= 0x000000ffL;
4883                         a->profile.B1_Protocols &= 0x000003ffL;
4884                         a->profile.B2_Protocols &= 0x00001fdfL;
4885                         a->profile.B3_Protocols &= 0x000000b7L;
4886
4887                         a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
4888                                 GL_BCHANNEL_OPERATION_SUPPORTED;
4889                         a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
4890                         a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
4891                         a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
4892                         a->manufacturer_features = GET_DWORD(&esc_profile[46]);
4893                         a->man_profile.private_options = 0;
4894
4895                         if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
4896                         {
4897                                 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
4898                                 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
4899                         }
4900
4901
4902                         if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
4903                                 a->man_profile.private_options |= 1L << PRIVATE_RTP;
4904                         a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
4905                         a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
4906
4907
4908                         if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
4909                                 a->man_profile.private_options |= 1L << PRIVATE_T38;
4910
4911
4912                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
4913                                 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
4914
4915
4916                         if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
4917                                 a->man_profile.private_options |= 1L << PRIVATE_V18;
4918
4919
4920                         if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
4921                                 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
4922
4923
4924                         if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
4925                                 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
4926
4927
4928                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
4929                                 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
4930
4931
4932                         if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
4933                                 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
4934
4935
4936                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
4937                                 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
4938
4939                 }
4940                 else
4941                 {
4942                         a->profile.Global_Options &= 0x0000007fL;
4943                         a->profile.B1_Protocols &= 0x000003dfL;
4944                         a->profile.B2_Protocols &= 0x00001adfL;
4945                         a->profile.B3_Protocols &= 0x000000b7L;
4946                         a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
4947                 }
4948                 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
4949                                                 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
4950                 {
4951                         a->profile.Global_Options |= GL_DTMF_SUPPORTED;
4952                 }
4953                 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
4954                 dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
4955                                 UnMapController(a->Id), a->profile.Global_Options,
4956                                 a->profile.B1_Protocols, a->profile.B2_Protocols,
4957                                 a->profile.B3_Protocols, a->manufacturer_features));
4958         }
4959         /* codec plci for the handset/hook state support is just an internal id  */
4960         if (plci != a->AdvCodecPLCI)
4961         {
4962                 force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
4963                 force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
4964                 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
4965                 SendInfo(plci, Id, parms, force_mt_info);
4966
4967                 VSwitchReqInd(plci, Id, multi_vswitch_parms);
4968
4969         }
4970
4971         /* switch the codec to the b-channel                                     */
4972         if (esc_chi[0] && plci && !plci->SuppState) {
4973                 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
4974                 mixer_set_bchannel_id_esc(plci, plci->b_channel);
4975                 dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
4976                 if (plci->tel == ADV_VOICE && plci->appl) {
4977                         SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
4978                 }
4979         }
4980
4981         if (plci->appl) plci->appl->Number++;
4982
4983         switch (plci->Sig.Ind) {
4984                 /* Response to Get_Supported_Services request */
4985         case S_SUPPORTED:
4986                 dbug(1, dprintf("S_Supported"));
4987                 if (!plci->appl) break;
4988                 if (pty_cai[0] == 4)
4989                 {
4990                         PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
4991                 }
4992                 else
4993                 {
4994                         PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
4995                 }
4996                 PUT_WORD(&CF_Ind[1], 0);
4997                 PUT_WORD(&CF_Ind[4], 0);
4998                 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
4999                 plci_remove(plci);
5000                 break;
5001
5002                 /* Supplementary Service rejected */
5003         case S_SERVICE_REJ:
5004                 dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5005                 if (!pty_cai[0]) break;
5006                 switch (pty_cai[5])
5007                 {
5008                 case ECT_EXECUTE:
5009                 case THREE_PTY_END:
5010                 case THREE_PTY_BEGIN:
5011                         if (!plci->relatedPTYPLCI) break;
5012                         tplci = plci->relatedPTYPLCI;
5013                         rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5014                         if (tplci->tel) rId |= EXT_CONTROLLER;
5015                         if (pty_cai[5] == ECT_EXECUTE)
5016                         {
5017                                 PUT_WORD(&SS_Ind[1], S_ECT);
5018
5019                                 plci->vswitchstate = 0;
5020                                 plci->relatedPTYPLCI->vswitchstate = 0;
5021
5022                         }
5023                         else
5024                         {
5025                                 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5026                         }
5027                         if (pty_cai[2] != 0xff)
5028                         {
5029                                 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5030                         }
5031                         else
5032                         {
5033                                 PUT_WORD(&SS_Ind[4], 0x300E);
5034                         }
5035                         plci->relatedPTYPLCI = NULL;
5036                         plci->ptyState = 0;
5037                         sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5038                         break;
5039
5040                 case CALL_DEFLECTION:
5041                         if (pty_cai[2] != 0xff)
5042                         {
5043                                 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5044                         }
5045                         else
5046                         {
5047                                 PUT_WORD(&SS_Ind[4], 0x300E);
5048                         }
5049                         PUT_WORD(&SS_Ind[1], pty_cai[5]);
5050                         for (i = 0; i < max_appl; i++)
5051                         {
5052                                 if (application[i].CDEnable)
5053                                 {
5054                                         if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5055                                         application[i].CDEnable = false;
5056                                 }
5057                         }
5058                         break;
5059
5060                 case DEACTIVATION_DIVERSION:
5061                 case ACTIVATION_DIVERSION:
5062                 case DIVERSION_INTERROGATE_CFU:
5063                 case DIVERSION_INTERROGATE_CFB:
5064                 case DIVERSION_INTERROGATE_CFNR:
5065                 case DIVERSION_INTERROGATE_NUM:
5066                 case CCBS_REQUEST:
5067                 case CCBS_DEACTIVATE:
5068                 case CCBS_INTERROGATE:
5069                         if (!plci->appl) break;
5070                         if (pty_cai[2] != 0xff)
5071                         {
5072                                 PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5073                         }
5074                         else
5075                         {
5076                                 PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5077                         }
5078                         switch (pty_cai[5])
5079                         {
5080                         case DEACTIVATION_DIVERSION:
5081                                 dbug(1, dprintf("Deact_Div"));
5082                                 Interr_Err_Ind[0] = 0x9;
5083                                 Interr_Err_Ind[3] = 0x6;
5084                                 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5085                                 break;
5086                         case ACTIVATION_DIVERSION:
5087                                 dbug(1, dprintf("Act_Div"));
5088                                 Interr_Err_Ind[0] = 0x9;
5089                                 Interr_Err_Ind[3] = 0x6;
5090                                 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5091                                 break;
5092                         case DIVERSION_INTERROGATE_CFU:
5093                         case DIVERSION_INTERROGATE_CFB:
5094                         case DIVERSION_INTERROGATE_CFNR:
5095                                 dbug(1, dprintf("Interr_Div"));
5096                                 Interr_Err_Ind[0] = 0xa;
5097                                 Interr_Err_Ind[3] = 0x7;
5098                                 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5099                                 break;
5100                         case DIVERSION_INTERROGATE_NUM:
5101                                 dbug(1, dprintf("Interr_Num"));
5102                                 Interr_Err_Ind[0] = 0xa;
5103                                 Interr_Err_Ind[3] = 0x7;
5104                                 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5105                                 break;
5106                         case CCBS_REQUEST:
5107                                 dbug(1, dprintf("CCBS Request"));
5108                                 Interr_Err_Ind[0] = 0xd;
5109                                 Interr_Err_Ind[3] = 0xa;
5110                                 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5111                                 break;
5112                         case CCBS_DEACTIVATE:
5113                                 dbug(1, dprintf("CCBS Deactivate"));
5114                                 Interr_Err_Ind[0] = 0x9;
5115                                 Interr_Err_Ind[3] = 0x6;
5116                                 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5117                                 break;
5118                         case CCBS_INTERROGATE:
5119                                 dbug(1, dprintf("CCBS Interrogate"));
5120                                 Interr_Err_Ind[0] = 0xb;
5121                                 Interr_Err_Ind[3] = 0x8;
5122                                 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5123                                 break;
5124                         }
5125                         PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5126                         sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5127                         plci_remove(plci);
5128                         break;
5129                 case ACTIVATION_MWI:
5130                 case DEACTIVATION_MWI:
5131                         if (pty_cai[5] == ACTIVATION_MWI)
5132                         {
5133                                 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5134                         }
5135                         else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5136
5137                         if (pty_cai[2] != 0xff)
5138                         {
5139                                 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5140                         }
5141                         else
5142                         {
5143                                 PUT_WORD(&SS_Ind[4], 0x300E);
5144                         }
5145
5146                         if (plci->cr_enquiry)
5147                         {
5148                                 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5149                                 plci_remove(plci);
5150                         }
5151                         else
5152                         {
5153                                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5154                         }
5155                         break;
5156                 case CONF_ADD: /* ERROR */
5157                 case CONF_BEGIN:
5158                 case CONF_DROP:
5159                 case CONF_ISOLATE:
5160                 case CONF_REATTACH:
5161                         CONF_Ind[0] = 9;
5162                         CONF_Ind[3] = 6;
5163                         switch (pty_cai[5])
5164                         {
5165                         case CONF_BEGIN:
5166                                 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5167                                 plci->ptyState = 0;
5168                                 break;
5169                         case CONF_DROP:
5170                                 CONF_Ind[0] = 5;
5171                                 CONF_Ind[3] = 2;
5172                                 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5173                                 plci->ptyState = CONNECTED;
5174                                 break;
5175                         case CONF_ISOLATE:
5176                                 CONF_Ind[0] = 5;
5177                                 CONF_Ind[3] = 2;
5178                                 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5179                                 plci->ptyState = CONNECTED;
5180                                 break;
5181                         case CONF_REATTACH:
5182                                 CONF_Ind[0] = 5;
5183                                 CONF_Ind[3] = 2;
5184                                 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5185                                 plci->ptyState = CONNECTED;
5186                                 break;
5187                         case CONF_ADD:
5188                                 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5189                                 plci->relatedPTYPLCI = NULL;
5190                                 tplci = plci->relatedPTYPLCI;
5191                                 if (tplci) tplci->ptyState = CONNECTED;
5192                                 plci->ptyState = CONNECTED;
5193                                 break;
5194                         }
5195
5196                         if (pty_cai[2] != 0xff)
5197                         {
5198                                 PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5199                         }
5200                         else
5201                         {
5202                                 PUT_WORD(&CONF_Ind[4], 0x3303); /* Time-out: network did not respond
5203                                                                   within the required time */
5204                         }
5205
5206                         PUT_DWORD(&CONF_Ind[6], 0x0);
5207                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5208                         break;
5209                 }
5210                 break;
5211
5212                 /* Supplementary Service indicates success */
5213         case S_SERVICE:
5214                 dbug(1, dprintf("Service_Ind"));
5215                 PUT_WORD(&CF_Ind[4], 0);
5216                 switch (pty_cai[5])
5217                 {
5218                 case THREE_PTY_END:
5219                 case THREE_PTY_BEGIN:
5220                 case ECT_EXECUTE:
5221                         if (!plci->relatedPTYPLCI) break;
5222                         tplci = plci->relatedPTYPLCI;
5223                         rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5224                         if (tplci->tel) rId |= EXT_CONTROLLER;
5225                         if (pty_cai[5] == ECT_EXECUTE)
5226                         {
5227                                 PUT_WORD(&SS_Ind[1], S_ECT);
5228
5229                                 if (plci->vswitchstate != 3)
5230                                 {
5231
5232                                         plci->ptyState = IDLE;
5233                                         plci->relatedPTYPLCI = NULL;
5234                                         plci->ptyState = 0;
5235
5236                                 }
5237
5238                                 dbug(1, dprintf("ECT OK"));
5239                                 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5240
5241
5242
5243                         }
5244                         else
5245                         {
5246                                 switch (plci->ptyState)
5247                                 {
5248                                 case S_3PTY_BEGIN:
5249                                         plci->ptyState = CONNECTED;
5250                                         dbug(1, dprintf("3PTY ON"));
5251                                         break;
5252
5253                                 case S_3PTY_END:
5254                                         plci->ptyState = IDLE;
5255                                         plci->relatedPTYPLCI = NULL;
5256                                         plci->ptyState = 0;
5257                                         dbug(1, dprintf("3PTY OFF"));
5258                                         break;
5259                                 }
5260                                 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5261                                 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5262                         }
5263                         break;
5264
5265                 case CALL_DEFLECTION:
5266                         PUT_WORD(&SS_Ind[1], pty_cai[5]);
5267                         for (i = 0; i < max_appl; i++)
5268                         {
5269                                 if (application[i].CDEnable)
5270                                 {
5271                                         if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5272                                         application[i].CDEnable = false;
5273                                 }
5274                         }
5275                         break;
5276
5277                 case DEACTIVATION_DIVERSION:
5278                 case ACTIVATION_DIVERSION:
5279                         if (!plci->appl) break;
5280                         PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5281                         PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5282                         sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5283                         plci_remove(plci);
5284                         break;
5285
5286                 case DIVERSION_INTERROGATE_CFU:
5287                 case DIVERSION_INTERROGATE_CFB:
5288                 case DIVERSION_INTERROGATE_CFNR:
5289                 case DIVERSION_INTERROGATE_NUM:
5290                 case CCBS_REQUEST:
5291                 case CCBS_DEACTIVATE:
5292                 case CCBS_INTERROGATE:
5293                         if (!plci->appl) break;
5294                         switch (pty_cai[5])
5295                         {
5296                         case DIVERSION_INTERROGATE_CFU:
5297                         case DIVERSION_INTERROGATE_CFB:
5298                         case DIVERSION_INTERROGATE_CFNR:
5299                                 dbug(1, dprintf("Interr_Div"));
5300                                 PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5301                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5302                                 break;
5303                         case DIVERSION_INTERROGATE_NUM:
5304                                 dbug(1, dprintf("Interr_Num"));
5305                                 PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5306                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5307                                 break;
5308                         case CCBS_REQUEST:
5309                                 dbug(1, dprintf("CCBS Request"));
5310                                 PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5311                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5312                                 break;
5313                         case CCBS_DEACTIVATE:
5314                                 dbug(1, dprintf("CCBS Deactivate"));
5315                                 PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5316                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5317                                 break;
5318                         case CCBS_INTERROGATE:
5319                                 dbug(1, dprintf("CCBS Interrogate"));
5320                                 PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5321                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5322                                 break;
5323                         }
5324                         PUT_WORD(&pty_cai[4], 0); /* Supplementary Service Reason */
5325                         PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5326                         sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5327                         plci_remove(plci);
5328                         break;
5329
5330                 case ACTIVATION_MWI:
5331                 case DEACTIVATION_MWI:
5332                         if (pty_cai[5] == ACTIVATION_MWI)
5333                         {
5334                                 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5335                         }
5336                         else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5337                         if (plci->cr_enquiry)
5338                         {
5339                                 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5340                                 plci_remove(plci);
5341                         }
5342                         else
5343                         {
5344                                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5345                         }
5346                         break;
5347                 case MWI_INDICATION:
5348                         if (pty_cai[0] >= 0x12)
5349                         {
5350                                 PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5351                                 pty_cai[2] = pty_cai[0] - 2; /* len Parameter */
5352                                 pty_cai[5] = pty_cai[0] - 5; /* Supplementary Service-specific parameter len */
5353                                 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5354                                 {
5355                                         if (plci->internal_command == GET_MWI_STATE) /* result on Message Waiting Listen */
5356                                         {
5357                                                 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5358                                                 plci_remove(plci);
5359                                                 return;
5360                                         }
5361                                         else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5362                                         pty_cai[0] = 0;
5363                                 }
5364                                 else
5365                                 {
5366                                         for (i = 0; i < max_appl; i++)
5367                                         {
5368                                                 if (a->Notification_Mask[i]&SMASK_MWI)
5369                                                 {
5370                                                         sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5371                                                         pty_cai[0] = 0;
5372                                                 }
5373                                         }
5374                                 }
5375
5376                                 if (!pty_cai[0])
5377                                 { /* acknowledge */
5378                                         facility[2] = 0; /* returncode */
5379                                 }
5380                                 else facility[2] = 0xff;
5381                         }
5382                         else
5383                         {
5384                                 /* reject */
5385                                 facility[2] = 0xff; /* returncode */
5386                         }
5387                         facility[0] = 2;
5388                         facility[1] = MWI_RESPONSE; /* Function */
5389                         add_p(plci, CAI, facility);
5390                         add_p(plci, ESC, multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5391                         sig_req(plci, S_SERVICE, 0);
5392                         send_req(plci);
5393                         plci->command = 0;
5394                         next_internal_command(Id, plci);
5395                         break;
5396                 case CONF_ADD: /* OK */
5397                 case CONF_BEGIN:
5398                 case CONF_DROP:
5399                 case CONF_ISOLATE:
5400                 case CONF_REATTACH:
5401                 case CONF_PARTYDISC:
5402                         CONF_Ind[0] = 9;
5403                         CONF_Ind[3] = 6;
5404                         switch (pty_cai[5])
5405                         {
5406                         case CONF_BEGIN:
5407                                 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5408                                 if (pty_cai[0] == 6)
5409                                 {
5410                                         d = pty_cai[6];
5411                                         PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5412                                 }
5413                                 else
5414                                 {
5415                                         PUT_DWORD(&CONF_Ind[6], 0x0);
5416                                 }
5417                                 break;
5418                         case CONF_ISOLATE:
5419                                 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5420                                 CONF_Ind[0] = 5;
5421                                 CONF_Ind[3] = 2;
5422                                 break;
5423                         case CONF_REATTACH:
5424                                 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5425                                 CONF_Ind[0] = 5;
5426                                 CONF_Ind[3] = 2;
5427                                 break;
5428                         case CONF_DROP:
5429                                 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5430                                 CONF_Ind[0] = 5;
5431                                 CONF_Ind[3] = 2;
5432                                 break;
5433                         case CONF_ADD:
5434                                 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5435                                 d = pty_cai[6];
5436                                 PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5437                                 tplci = plci->relatedPTYPLCI;
5438                                 if (tplci) tplci->ptyState = CONNECTED;
5439                                 break;
5440                         case CONF_PARTYDISC:
5441                                 CONF_Ind[0] = 7;
5442                                 CONF_Ind[3] = 4;
5443                                 PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5444                                 d = pty_cai[6];
5445                                 PUT_DWORD(&CONF_Ind[4], d); /* PartyID */
5446                                 break;
5447                         }
5448                         plci->ptyState = CONNECTED;
5449                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5450                         break;
5451                 case CCBS_INFO_RETAIN:
5452                 case CCBS_ERASECALLLINKAGEID:
5453                 case CCBS_STOP_ALERTING:
5454                         CONF_Ind[0] = 5;
5455                         CONF_Ind[3] = 2;
5456                         switch (pty_cai[5])
5457                         {
5458                         case CCBS_INFO_RETAIN:
5459                                 PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5460                                 break;
5461                         case CCBS_STOP_ALERTING:
5462                                 PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5463                                 break;
5464                         case CCBS_ERASECALLLINKAGEID:
5465                                 PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5466                                 CONF_Ind[0] = 7;
5467                                 CONF_Ind[3] = 4;
5468                                 CONF_Ind[6] = 0;
5469                                 CONF_Ind[7] = 0;
5470                                 break;
5471                         }
5472                         w = pty_cai[6];
5473                         PUT_WORD(&CONF_Ind[4], w); /* PartyID */
5474
5475                         if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5476                         {
5477                                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5478                         }
5479                         else
5480                         {
5481                                 for (i = 0; i < max_appl; i++)
5482                                         if (a->Notification_Mask[i] & SMASK_CCBS)
5483                                                 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5484                         }
5485                         break;
5486                 }
5487                 break;
5488         case CALL_HOLD_REJ:
5489                 cau = parms[7];
5490                 if (cau)
5491                 {
5492                         i = _L3_CAUSE | cau[2];
5493                         if (cau[2] == 0) i = 0x3603;
5494                 }
5495                 else
5496                 {
5497                         i = 0x3603;
5498                 }
5499                 PUT_WORD(&SS_Ind[1], S_HOLD);
5500                 PUT_WORD(&SS_Ind[4], i);
5501                 if (plci->SuppState == HOLD_REQUEST)
5502                 {
5503                         plci->SuppState = IDLE;
5504                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5505                 }
5506                 break;
5507
5508         case CALL_HOLD_ACK:
5509                 if (plci->SuppState == HOLD_REQUEST)
5510                 {
5511                         plci->SuppState = CALL_HELD;
5512                         CodecIdCheck(a, plci);
5513                         start_internal_command(Id, plci, hold_save_command);
5514                 }
5515                 break;
5516
5517         case CALL_RETRIEVE_REJ:
5518                 cau = parms[7];
5519                 if (cau)
5520                 {
5521                         i = _L3_CAUSE | cau[2];
5522                         if (cau[2] == 0) i = 0x3603;
5523                 }
5524                 else
5525                 {
5526                         i = 0x3603;
5527                 }
5528                 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5529                 PUT_WORD(&SS_Ind[4], i);
5530                 if (plci->SuppState == RETRIEVE_REQUEST)
5531                 {
5532                         plci->SuppState = CALL_HELD;
5533                         CodecIdCheck(a, plci);
5534                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5535                 }
5536                 break;
5537
5538         case CALL_RETRIEVE_ACK:
5539                 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5540                 if (plci->SuppState == RETRIEVE_REQUEST)
5541                 {
5542                         plci->SuppState = IDLE;
5543                         plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5544                         plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5545                         if (plci->tel)
5546                         {
5547                                 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5548                                 dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5549                                 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5550                                 if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5551                                 {
5552                                         dbug(1, dprintf("Get B-ch"));
5553                                         start_internal_command(Id, plci, retrieve_restore_command);
5554                                 }
5555                                 else
5556                                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5557                         }
5558                         else
5559                                 start_internal_command(Id, plci, retrieve_restore_command);
5560                 }
5561                 break;
5562
5563         case INDICATE_IND:
5564                 if (plci->State != LISTENING) {
5565                         sig_req(plci, HANGUP, 0);
5566                         send_req(plci);
5567                         break;
5568                 }
5569                 cip = find_cip(a, parms[4], parms[6]);
5570                 cip_mask = 1L << cip;
5571                 dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5572                 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5573                 if (!remove_started && !a->adapter_disabled)
5574                 {
5575                         group_optimization(a, plci);
5576                         for_each_set_bit(i, plci->group_optimization_mask_table, max_appl) {
5577                                 if (application[i].Id
5578                                     && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5579                                     && CPN_filter_ok(parms[0], a, i)) {
5580                                         dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5581                                         __set_bit(i, plci->c_ind_mask_table);
5582                                         dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
5583                                         plci->State = INC_CON_PENDING;
5584                                         plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5585                                                 CALL_DIR_IN | CALL_DIR_ANSWER;
5586                                         if (esc_chi[0]) {
5587                                                 plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5588                                                 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5589                                         }
5590                                         /* if a listen on the ext controller is done, check if hook states */
5591                                         /* are supported or if just a on board codec must be activated     */
5592                                         if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5593                                                 if (a->profile.Global_Options & HANDSET)
5594                                                         plci->tel = ADV_VOICE;
5595                                                 else if (a->profile.Global_Options & ON_BOARD_CODEC)
5596                                                         plci->tel = CODEC;
5597                                                 if (plci->tel) Id |= EXT_CONTROLLER;
5598                                                 a->codec_listen[i] = plci;
5599                                         }
5600
5601                                         sendf(&application[i], _CONNECT_I, Id, 0,
5602                                               "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5603                                               parms[0],    /* CalledPartyNumber   */
5604                                               multi_CiPN_parms[0],    /* CallingPartyNumber  */
5605                                               parms[2],    /* CalledPartySubad    */
5606                                               parms[3],    /* CallingPartySubad   */
5607                                               parms[4],    /* BearerCapability    */
5608                                               parms[5],    /* LowLC               */
5609                                               parms[6],    /* HighLC              */
5610                                               ai_len,      /* nested struct add_i */
5611                                               add_i[0],    /* B channel info    */
5612                                               add_i[1],    /* keypad facility   */
5613                                               add_i[2],    /* user user data    */
5614                                               add_i[3],    /* nested facility   */
5615                                               multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5616                                                 );
5617                                         SendSSExtInd(&application[i],
5618                                                      plci,
5619                                                      Id,
5620                                                      multi_ssext_parms);
5621                                         SendSetupInfo(&application[i],
5622                                                       plci,
5623                                                       Id,
5624                                                       parms,
5625                                                       SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5626                                 }
5627                         }
5628                         dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
5629                 }
5630                 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL)) {
5631                         sig_req(plci, HANGUP, 0);
5632                         send_req(plci);
5633                         plci->State = IDLE;
5634                 }
5635                 plci->notifiedcall = 0;
5636                 a->listen_active--;
5637                 listen_check(a);
5638                 break;
5639
5640         case CALL_PEND_NOTIFY:
5641                 plci->notifiedcall = 1;
5642                 listen_check(a);
5643                 break;
5644
5645         case CALL_IND:
5646         case CALL_CON:
5647                 if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5648                 {
5649                         if (plci->internal_command == PERM_COD_CONN_PEND)
5650                         {
5651                                 if (plci->State == ADVANCED_VOICE_NOSIG)
5652                                 {
5653                                         dbug(1, dprintf("***Codec OK"));
5654                                         if (a->AdvSignalPLCI)
5655                                         {
5656                                                 tplci = a->AdvSignalPLCI;
5657                                                 if (tplci->spoofed_msg)
5658                                                 {
5659                                                         dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5660                                                         tplci->command = 0;
5661                                                         tplci->internal_command = 0;
5662                                                         x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5663                                                         switch (tplci->spoofed_msg)
5664                                                         {
5665                                                         case CALL_RES:
5666                                                                 tplci->command = _CONNECT_I | RESPONSE;
5667                                                                 api_load_msg(&tplci->saved_msg, saved_parms);
5668                                                                 add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5669                                                                 if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5670                                                                 {
5671                                                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
5672                                                                         add_p(tplci, LLI, "\x01\x01");
5673                                                                 }
5674                                                                 add_s(tplci, CONN_NR, &saved_parms[2]);
5675                                                                 add_s(tplci, LLC, &saved_parms[4]);
5676                                                                 add_ai(tplci, &saved_parms[5]);
5677                                                                 tplci->State = INC_CON_ACCEPT;
5678                                                                 sig_req(tplci, CALL_RES, 0);
5679                                                                 send_req(tplci);
5680                                                                 break;
5681
5682                                                         case AWAITING_SELECT_B:
5683                                                                 dbug(1, dprintf("Select_B continue"));
5684                                                                 start_internal_command(x_Id, tplci, select_b_command);
5685                                                                 break;
5686
5687                                                         case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5688                                                                 if (!tplci->Sig.Id)
5689                                                                 {
5690                                                                         dbug(1, dprintf("No SigID!"));
5691                                                                         sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5692                                                                         plci_remove(tplci);
5693                                                                         break;
5694                                                                 }
5695                                                                 tplci->command = _MANUFACTURER_R;
5696                                                                 api_load_msg(&tplci->saved_msg, saved_parms);
5697                                                                 dir = saved_parms[2].info[0];
5698                                                                 if (dir == 1) {
5699                                                                         sig_req(tplci, CALL_REQ, 0);
5700                                                                 }
5701                                                                 else if (!dir) {
5702                                                                         sig_req(tplci, LISTEN_REQ, 0);
5703                                                                 }
5704                                                                 send_req(tplci);
5705                                                                 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5706                                                                 break;
5707
5708                                                         case (CALL_REQ | AWAITING_MANUF_CON):
5709                                                                 sig_req(tplci, CALL_REQ, 0);
5710                                                                 send_req(tplci);
5711                                                                 break;
5712
5713                                                         case CALL_REQ:
5714                                                                 if (!tplci->Sig.Id)
5715                                                                 {
5716                                                                         dbug(1, dprintf("No SigID!"));
5717                                                                         sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5718                                                                         plci_remove(tplci);
5719                                                                         break;
5720                                                                 }
5721                                                                 tplci->command = _CONNECT_R;
5722                                                                 api_load_msg(&tplci->saved_msg, saved_parms);
5723                                                                 add_s(tplci, CPN, &saved_parms[1]);
5724                                                                 add_s(tplci, DSA, &saved_parms[3]);
5725                                                                 add_ai(tplci, &saved_parms[9]);
5726                                                                 sig_req(tplci, CALL_REQ, 0);
5727                                                                 send_req(tplci);
5728                                                                 break;
5729
5730                                                         case CALL_RETRIEVE:
5731                                                                 tplci->command = C_RETRIEVE_REQ;
5732                                                                 sig_req(tplci, CALL_RETRIEVE, 0);
5733                                                                 send_req(tplci);
5734                                                                 break;
5735                                                         }
5736                                                         tplci->spoofed_msg = 0;
5737                                                         if (tplci->internal_command == 0)
5738                                                                 next_internal_command(x_Id, tplci);
5739                                                 }
5740                                         }
5741                                         next_internal_command(Id, plci);
5742                                         break;
5743                                 }
5744                                 dbug(1, dprintf("***Codec Hook Init Req"));
5745                                 plci->internal_command = PERM_COD_HOOK;
5746                                 add_p(plci, FTY, "\x01\x09");             /* Get Hook State*/
5747                                 sig_req(plci, TEL_CTRL, 0);
5748                                 send_req(plci);
5749                         }
5750                 }
5751                 else if (plci->command != _MANUFACTURER_R  /* old style permanent connect */
5752                          && plci->State != INC_ACT_PENDING)
5753                 {
5754                         mixer_set_bchannel_id_esc(plci, plci->b_channel);
5755                         if (plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5756                         {
5757                                 chi[2] = plci->b_channel;
5758                                 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5759                         }
5760                         sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5761                         plci->State = INC_ACT_PENDING;
5762                 }
5763                 break;
5764
5765         case TEL_CTRL:
5766                 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5767                 if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5768                         switch (ie[1] & 0x91) {
5769                         case 0x80:   /* hook off */
5770                         case 0x81:
5771                                 if (plci->internal_command == PERM_COD_HOOK)
5772                                 {
5773                                         dbug(1, dprintf("init:hook_off"));
5774                                         plci->hook_state = ie[1];
5775                                         next_internal_command(Id, plci);
5776                                         break;
5777                                 }
5778                                 else /* ignore doubled hook indications */
5779                                 {
5780                                         if (((plci->hook_state) & 0xf0) == 0x80)
5781                                         {
5782                                                 dbug(1, dprintf("ignore hook"));
5783                                                 break;
5784                                         }
5785                                         plci->hook_state = ie[1]&0x91;
5786                                 }
5787                                 /* check for incoming call pending */
5788                                 /* and signal '+'.Appl must decide */
5789                                 /* with connect_res if call must   */
5790                                 /* accepted or not                 */
5791                                 for (i = 0, tplci = NULL; i < max_appl; i++) {
5792                                         if (a->codec_listen[i]
5793                                             && (a->codec_listen[i]->State == INC_CON_PENDING
5794                                                 || a->codec_listen[i]->State == INC_CON_ALERT)) {
5795                                                 tplci = a->codec_listen[i];
5796                                                 tplci->appl = &application[i];
5797                                         }
5798                                 }
5799                                 /* no incoming call, do outgoing call */
5800                                 /* and signal '+' if outg. setup   */
5801                                 if (!a->AdvSignalPLCI && !tplci) {
5802                                         if ((i = get_plci(a))) {
5803                                                 a->AdvSignalPLCI = &a->plci[i - 1];
5804                                                 tplci = a->AdvSignalPLCI;
5805                                                 tplci->tel  = ADV_VOICE;
5806                                                 PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5807                                                 if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5808                                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
5809                                                         add_p(tplci, LLI, "\x01\x01");
5810                                                 }
5811                                                 add_p(tplci, CAI, voice_cai);
5812                                                 add_p(tplci, OAD, a->TelOAD);
5813                                                 add_p(tplci, OSA, a->TelOSA);
5814                                                 add_p(tplci, SHIFT | 6, NULL);
5815                                                 add_p(tplci, SIN, "\x02\x01\x00");
5816                                                 add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5817                                                 sig_req(tplci, ASSIGN, DSIG_ID);
5818                                                 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5819                                                 a->AdvSignalPLCI->command = 0;
5820                                                 tplci->appl = a->AdvSignalAppl;
5821                                                 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5822                                                 send_req(tplci);
5823                                         }
5824
5825                                 }
5826
5827                                 if (!tplci) break;
5828                                 Id = ((word)tplci->Id << 8) | a->Id;
5829                                 Id |= EXT_CONTROLLER;
5830                                 sendf(tplci->appl,
5831                                       _FACILITY_I,
5832                                       Id,
5833                                       0,
5834                                       "ws", (word)0, "\x01+");
5835                                 break;
5836
5837                         case 0x90:   /* hook on  */
5838                         case 0x91:
5839                                 if (plci->internal_command == PERM_COD_HOOK)
5840                                 {
5841                                         dbug(1, dprintf("init:hook_on"));
5842                                         plci->hook_state = ie[1] & 0x91;
5843                                         next_internal_command(Id, plci);
5844                                         break;
5845                                 }
5846                                 else /* ignore doubled hook indications */
5847                                 {
5848                                         if (((plci->hook_state) & 0xf0) == 0x90) break;
5849                                         plci->hook_state = ie[1] & 0x91;
5850                                 }
5851                                 /* hangup the adv. voice call and signal '-' to the appl */
5852                                 if (a->AdvSignalPLCI) {
5853                                         Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5854                                         if (plci->tel) Id |= EXT_CONTROLLER;
5855                                         sendf(a->AdvSignalAppl,
5856                                               _FACILITY_I,
5857                                               Id,
5858                                               0,
5859                                               "ws", (word)0, "\x01-");
5860                                         a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5861                                         a->AdvSignalPLCI->command = 0;
5862                                         sig_req(a->AdvSignalPLCI, HANGUP, 0);
5863                                         send_req(a->AdvSignalPLCI);
5864                                 }
5865                                 break;
5866                         }
5867                 }
5868                 break;
5869
5870         case RESUME:
5871                 __clear_bit(plci->appl->Id - 1, plci->c_ind_mask_table);
5872                 PUT_WORD(&resume_cau[4], GOOD);
5873                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
5874                 break;
5875
5876         case SUSPEND:
5877                 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5878
5879                 if (plci->NL.Id && !plci->nl_remove_id) {
5880                         mixer_remove(plci);
5881                         nl_req_ncci(plci, REMOVE, 0);
5882                 }
5883                 if (!plci->sig_remove_id) {
5884                         plci->internal_command = 0;
5885                         sig_req(plci, REMOVE, 0);
5886                 }
5887                 send_req(plci);
5888                 if (!plci->channels) {
5889                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
5890                         sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
5891                 }
5892                 break;
5893
5894         case SUSPEND_REJ:
5895                 break;
5896
5897         case HANGUP:
5898                 plci->hangup_flow_ctrl_timer = 0;
5899                 if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
5900                 cau = parms[7];
5901                 if (cau) {
5902                         i = _L3_CAUSE | cau[2];
5903                         if (cau[2] == 0) i = 0;
5904                         else if (cau[2] == 8) i = _L1_ERROR;
5905                         else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
5906                         else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
5907                 }
5908                 else {
5909                         i = _L3_ERROR;
5910                 }
5911
5912                 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
5913                 {
5914                         for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
5915                                 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
5916                 }
5917                 else
5918                 {
5919                         bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5920                 }
5921                 if (!plci->appl)
5922                 {
5923                         if (plci->State == LISTENING)
5924                         {
5925                                 plci->notifiedcall = 0;
5926                                 a->listen_active--;
5927                         }
5928                         plci->State = INC_DIS_PENDING;
5929                         if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
5930                         {
5931                                 plci->State = IDLE;
5932                                 if (plci->NL.Id && !plci->nl_remove_id)
5933                                 {
5934                                         mixer_remove(plci);
5935                                         nl_req_ncci(plci, REMOVE, 0);
5936                                 }
5937                                 if (!plci->sig_remove_id)
5938                                 {
5939                                         plci->internal_command = 0;
5940                                         sig_req(plci, REMOVE, 0);
5941                                 }
5942                                 send_req(plci);
5943                         }
5944                 }
5945                 else
5946                 {
5947                         /* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
5948                         /* result in a second HANGUP! Don't generate another        */
5949                         /* DISCONNECT                                               */
5950                         if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
5951                         {
5952                                 if (plci->State == RESUMING)
5953                                 {
5954                                         PUT_WORD(&resume_cau[4], i);
5955                                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
5956                                 }
5957                                 plci->State = INC_DIS_PENDING;
5958                                 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
5959                         }
5960                 }
5961                 break;
5962
5963         case SSEXT_IND:
5964                 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5965                 break;
5966
5967         case VSWITCH_REQ:
5968                 VSwitchReqInd(plci, Id, multi_vswitch_parms);
5969                 break;
5970         case VSWITCH_IND:
5971                 if (plci->relatedPTYPLCI &&
5972                     plci->vswitchstate == 3 &&
5973                     plci->relatedPTYPLCI->vswitchstate == 3 &&
5974                     parms[MAXPARMSIDS - 1][0])
5975                 {
5976                         add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
5977                         sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
5978                         send_req(plci->relatedPTYPLCI);
5979                 }
5980                 else VSwitchReqInd(plci, Id, multi_vswitch_parms);
5981                 break;
5982
5983         }
5984 }
5985
5986
5987 static void SendSetupInfo(APPL *appl, PLCI *plci, dword Id, byte **parms, byte Info_Sent_Flag)
5988 {
5989         word i;
5990         byte *ie;
5991         word Info_Number;
5992         byte *Info_Element;
5993         word Info_Mask = 0;
5994
5995         dbug(1, dprintf("SetupInfo"));
5996
5997         for (i = 0; i < MAXPARMSIDS; i++) {
5998                 ie = parms[i];
5999                 Info_Number = 0;
6000                 Info_Element = ie;
6001                 if (ie[0]) {
6002                         switch (i) {
6003                         case 0:
6004                                 dbug(1, dprintf("CPN "));
6005                                 Info_Number = 0x0070;
6006                                 Info_Mask = 0x80;
6007                                 Info_Sent_Flag = true;
6008                                 break;
6009                         case 8:  /* display      */
6010                                 dbug(1, dprintf("display(%d)", i));
6011                                 Info_Number = 0x0028;
6012                                 Info_Mask = 0x04;
6013                                 Info_Sent_Flag = true;
6014                                 break;
6015                         case 16: /* Channel Id */
6016                                 dbug(1, dprintf("CHI"));
6017                                 Info_Number = 0x0018;
6018                                 Info_Mask = 0x100;
6019                                 Info_Sent_Flag = true;
6020                                 mixer_set_bchannel_id(plci, Info_Element);
6021                                 break;
6022                         case 19: /* Redirected Number */
6023                                 dbug(1, dprintf("RDN"));
6024                                 Info_Number = 0x0074;
6025                                 Info_Mask = 0x400;
6026                                 Info_Sent_Flag = true;
6027                                 break;
6028                         case 20: /* Redirected Number extended */
6029                                 dbug(1, dprintf("RDX"));
6030                                 Info_Number = 0x0073;
6031                                 Info_Mask = 0x400;
6032                                 Info_Sent_Flag = true;
6033                                 break;
6034                         case 22: /* Redirecing Number  */
6035                                 dbug(1, dprintf("RIN"));
6036                                 Info_Number = 0x0076;
6037                                 Info_Mask = 0x400;
6038                                 Info_Sent_Flag = true;
6039                                 break;
6040                         default:
6041                                 Info_Number = 0;
6042                                 break;
6043                         }
6044                 }
6045
6046                 if (i == MAXPARMSIDS - 2) { /* to indicate the message type "Setup" */
6047                         Info_Number = 0x8000 | 5;
6048                         Info_Mask = 0x10;
6049                         Info_Element = "";
6050                 }
6051
6052                 if (Info_Sent_Flag && Info_Number) {
6053                         if (plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask) {
6054                                 sendf(appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6055                         }
6056                 }
6057         }
6058 }
6059
6060
6061 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6062 {
6063         word i;
6064         word j;
6065         word k;
6066         byte *ie;
6067         word Info_Number;
6068         byte *Info_Element;
6069         word Info_Mask = 0;
6070         static byte charges[5] = {4, 0, 0, 0, 0};
6071         static byte cause[] = {0x02, 0x80, 0x00};
6072         APPL *appl;
6073
6074         dbug(1, dprintf("InfoParse "));
6075
6076         if (
6077                 !plci->appl
6078                 && !plci->State
6079                 && plci->Sig.Ind != NCR_FACILITY
6080                 )
6081         {
6082                 dbug(1, dprintf("NoParse "));
6083                 return;
6084         }
6085         cause[2] = 0;
6086         for (i = 0; i < MAXPARMSIDS; i++) {
6087                 ie = parms[i];
6088                 Info_Number = 0;
6089                 Info_Element = ie;
6090                 if (ie[0]) {
6091                         switch (i) {
6092                         case 0:
6093                                 dbug(1, dprintf("CPN "));
6094                                 Info_Number = 0x0070;
6095                                 Info_Mask   = 0x80;
6096                                 break;
6097                         case 7: /* ESC_CAU */
6098                                 dbug(1, dprintf("cau(0x%x)", ie[2]));
6099                                 Info_Number = 0x0008;
6100                                 Info_Mask = 0x00;
6101                                 cause[2] = ie[2];
6102                                 Info_Element = NULL;
6103                                 break;
6104                         case 8:  /* display      */
6105                                 dbug(1, dprintf("display(%d)", i));
6106                                 Info_Number = 0x0028;
6107                                 Info_Mask = 0x04;
6108                                 break;
6109                         case 9:  /* Date display */
6110                                 dbug(1, dprintf("date(%d)", i));
6111                                 Info_Number = 0x0029;
6112                                 Info_Mask = 0x02;
6113                                 break;
6114                         case 10: /* charges */
6115                                 for (j = 0; j < 4; j++) charges[1 + j] = 0;
6116                                 for (j = 0; j < ie[0] && !(ie[1 + j] & 0x80); j++);
6117                                 for (k = 1, j++; j < ie[0] && k <= 4; j++, k++) charges[k] = ie[1 + j];
6118                                 Info_Number = 0x4000;
6119                                 Info_Mask = 0x40;
6120                                 Info_Element = charges;
6121                                 break;
6122                         case 11: /* user user info */
6123                                 dbug(1, dprintf("uui"));
6124                                 Info_Number = 0x007E;
6125                                 Info_Mask = 0x08;
6126                                 break;
6127                         case 12: /* congestion receiver ready */
6128                                 dbug(1, dprintf("clRDY"));
6129                                 Info_Number = 0x00B0;
6130                                 Info_Mask = 0x08;
6131                                 Info_Element = "";
6132                                 break;
6133                         case 13: /* congestion receiver not ready */
6134                                 dbug(1, dprintf("clNRDY"));
6135                                 Info_Number = 0x00BF;
6136                                 Info_Mask = 0x08;
6137                                 Info_Element = "";
6138                                 break;
6139                         case 15: /* Keypad Facility */
6140                                 dbug(1, dprintf("KEY"));
6141                                 Info_Number = 0x002C;
6142                                 Info_Mask = 0x20;
6143                                 break;
6144                         case 16: /* Channel Id */
6145                                 dbug(1, dprintf("CHI"));
6146                                 Info_Number = 0x0018;
6147                                 Info_Mask = 0x100;
6148                                 mixer_set_bchannel_id(plci, Info_Element);
6149                                 break;
6150                         case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6151                                 dbug(1, dprintf("q9cau(0x%x)", ie[2]));
6152                                 if (!cause[2] || cause[2] < 0x80) break;  /* eg. layer 1 error */
6153                                 Info_Number = 0x0008;
6154                                 Info_Mask = 0x01;
6155                                 if (cause[2] != ie[2]) Info_Element = cause;
6156                                 break;
6157                         case 19: /* Redirected Number */
6158                                 dbug(1, dprintf("RDN"));
6159                                 Info_Number = 0x0074;
6160                                 Info_Mask = 0x400;
6161                                 break;
6162                         case 22: /* Redirecing Number  */
6163                                 dbug(1, dprintf("RIN"));
6164                                 Info_Number = 0x0076;
6165                                 Info_Mask = 0x400;
6166                                 break;
6167                         case 23: /* Notification Indicator  */
6168                                 dbug(1, dprintf("NI"));
6169                                 Info_Number = (word)NI;
6170                                 Info_Mask = 0x210;
6171                                 break;
6172                         case 26: /* Call State  */
6173                                 dbug(1, dprintf("CST"));
6174                                 Info_Number = (word)CST;
6175                                 Info_Mask = 0x01; /* do with cause i.e. for now */
6176                                 break;
6177                         case MAXPARMSIDS - 2:  /* Escape Message Type, must be the last indication */
6178                                 dbug(1, dprintf("ESC/MT[0x%x]", ie[3]));
6179                                 Info_Number = 0x8000 | ie[3];
6180                                 if (iesent) Info_Mask = 0xffff;
6181                                 else  Info_Mask = 0x10;
6182                                 Info_Element = "";
6183                                 break;
6184                         default:
6185                                 Info_Number  = 0;
6186                                 Info_Mask    = 0;
6187                                 Info_Element = "";
6188                                 break;
6189                         }
6190                 }
6191
6192                 if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6193                 {
6194                         for (j = 0; j < max_appl; j++)
6195                         {
6196                                 appl = &application[j];
6197                                 if (Info_Number
6198                                     && appl->Id
6199                                     && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6200                                 {
6201                                         dbug(1, dprintf("NCR_Ind"));
6202                                         iesent = true;
6203                                         sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6204                                 }
6205                         }
6206                 }
6207                 else if (!plci->appl)
6208                 { /* overlap receiving broadcast */
6209                         if (Info_Number == CPN
6210                             || Info_Number == KEY
6211                             || Info_Number == NI
6212                             || Info_Number == DSP
6213                             || Info_Number == UUI)
6214                         {
6215                                 for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
6216                                         dbug(1, dprintf("Ovl_Ind"));
6217                                         iesent = true;
6218                                         sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6219                                 }
6220                         }
6221                 }               /* all other signalling states */
6222                 else if (Info_Number
6223                          && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6224                 {
6225                         dbug(1, dprintf("Std_Ind"));
6226                         iesent = true;
6227                         sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6228                 }
6229         }
6230 }
6231
6232
6233 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6234                         dword info_mask, byte setupParse)
6235 {
6236         word i;
6237         word j;
6238         byte *ie;
6239         word Info_Number;
6240         byte *Info_Element;
6241         APPL *appl;
6242         word Info_Mask = 0;
6243         byte iesent = 0;
6244
6245         if (
6246                 !plci->appl
6247                 && !plci->State
6248                 && plci->Sig.Ind != NCR_FACILITY
6249                 && !setupParse
6250                 )
6251         {
6252                 dbug(1, dprintf("NoM-IEParse "));
6253                 return 0;
6254         }
6255         dbug(1, dprintf("M-IEParse "));
6256
6257         for (i = 0; i < MAX_MULTI_IE; i++)
6258         {
6259                 ie = parms[i];
6260                 Info_Number = 0;
6261                 Info_Element = ie;
6262                 if (ie[0])
6263                 {
6264                         dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci->Sig.Ind, ie_type));
6265                         Info_Number = (word)ie_type;
6266                         Info_Mask = (word)info_mask;
6267                 }
6268
6269                 if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6270                 {
6271                         for (j = 0; j < max_appl; j++)
6272                         {
6273                                 appl = &application[j];
6274                                 if (Info_Number
6275                                     && appl->Id
6276                                     && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6277                                 {
6278                                         iesent = true;
6279                                         dbug(1, dprintf("Mlt_NCR_Ind"));
6280                                         sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6281                                 }
6282                         }
6283                 }
6284                 else if (!plci->appl && Info_Number)
6285                 {                                        /* overlap receiving broadcast */
6286                         for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
6287                                 iesent = true;
6288                                 dbug(1, dprintf("Mlt_Ovl_Ind"));
6289                                 sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6290                         }
6291                 }                                        /* all other signalling states */
6292                 else if (Info_Number
6293                          && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6294                 {
6295                         iesent = true;
6296                         dbug(1, dprintf("Mlt_Std_Ind"));
6297                         sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6298                 }
6299         }
6300         return iesent;
6301 }
6302
6303 static void SendSSExtInd(APPL *appl, PLCI *plci, dword Id, byte **parms)
6304 {
6305         word i;
6306         /* Format of multi_ssext_parms[i][]:
6307            0 byte length
6308            1 byte SSEXTIE
6309            2 byte SSEXT_REQ/SSEXT_IND
6310            3 byte length
6311            4 word SSExtCommand
6312            6... Params
6313         */
6314         if (
6315                 plci
6316                 && plci->State
6317                 && plci->Sig.Ind != NCR_FACILITY
6318                 )
6319                 for (i = 0; i < MAX_MULTI_IE; i++)
6320                 {
6321                         if (parms[i][0] < 6) continue;
6322                         if (parms[i][2] == SSEXT_REQ) continue;
6323
6324                         if (appl)
6325                         {
6326                                 parms[i][0] = 0; /* kill it */
6327                                 sendf(appl, _MANUFACTURER_I,
6328                                       Id,
6329                                       0,
6330                                       "dwS",
6331                                       _DI_MANU_ID,
6332                                       _DI_SSEXT_CTRL,
6333                                       &parms[i][3]);
6334                         }
6335                         else if (plci->appl)
6336                         {
6337                                 parms[i][0] = 0; /* kill it */
6338                                 sendf(plci->appl, _MANUFACTURER_I,
6339                                       Id,
6340                                       0,
6341                                       "dwS",
6342                                       _DI_MANU_ID,
6343                                       _DI_SSEXT_CTRL,
6344                                       &parms[i][3]);
6345                         }
6346                 }
6347 };
6348
6349 static void nl_ind(PLCI *plci)
6350 {
6351         byte ch;
6352         word ncci;
6353         dword Id;
6354         DIVA_CAPI_ADAPTER *a;
6355         word NCCIcode;
6356         APPL *APPLptr;
6357         word count;
6358         word Num;
6359         word i, ncpi_state;
6360         byte len, ncci_state;
6361         word msg;
6362         word info = 0;
6363         word fax_feature_bits;
6364         byte fax_send_edata_ack;
6365         static byte v120_header_buffer[2 + 3];
6366         static word fax_info[] = {
6367                 0,                     /* T30_SUCCESS                        */
6368                 _FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
6369                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
6370                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
6371                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
6372                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
6373                 _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
6374                 _FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
6375                 _FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
6376                 _FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
6377                 _FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
6378                 _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
6379                 _FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
6380                 _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
6381                 _FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
6382                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
6383                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
6384                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
6385                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
6386                 _FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
6387                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
6388                 _FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
6389                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
6390                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
6391                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
6392                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
6393                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
6394                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
6395                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
6396                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
6397                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
6398                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
6399                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
6400                 0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
6401                 0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
6402                 0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
6403                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
6404                 _FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
6405                 _FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
6406                 _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
6407                 _FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
6408                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6409                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
6410                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
6411                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
6412                 _FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
6413                 _FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
6414         };
6415
6416         byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6417
6418
6419         static word rtp_info[] = {
6420                 GOOD,                  /* RTP_SUCCESS                       */
6421                 0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
6422         };
6423
6424         static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6425                 {
6426                         0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6427                         0x00000000, 0x00000000, 0x00000000, 0x00000000
6428                 };
6429
6430         ch = plci->NL.IndCh;
6431         a = plci->adapter;
6432         ncci = a->ch_ncci[ch];
6433         Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6434         if (plci->tel) Id |= EXT_CONTROLLER;
6435         APPLptr = plci->appl;
6436         dbug(1, dprintf("NL_IND-Id(NL:0x%x)=0x%08lx,plci=%x,tel=%x,state=0x%x,ch=0x%x,chs=%d,Ind=%x",
6437                         plci->NL.Id, Id, plci->Id, plci->tel, plci->State, ch, plci->channels, plci->NL.Ind & 0x0f));
6438
6439         /* in the case if no connect_active_Ind was sent to the appl we wait for */
6440
6441         if (plci->nl_remove_id)
6442         {
6443                 plci->NL.RNR = 2; /* discard */
6444                 dbug(1, dprintf("NL discard while remove pending"));
6445                 return;
6446         }
6447         if ((plci->NL.Ind & 0x0f) == N_CONNECT)
6448         {
6449                 if (plci->State == INC_DIS_PENDING
6450                     || plci->State == OUTG_DIS_PENDING
6451                     || plci->State == IDLE)
6452                 {
6453                         plci->NL.RNR = 2; /* discard */
6454                         dbug(1, dprintf("discard n_connect"));
6455                         return;
6456                 }
6457                 if (plci->State < INC_ACT_PENDING)
6458                 {
6459                         plci->NL.RNR = 1; /* flow control */
6460                         channel_x_off(plci, ch, N_XON_CONNECT_IND);
6461                         return;
6462                 }
6463         }
6464
6465         if (!APPLptr)                         /* no application or invalid data */
6466         {                                    /* while reloading the DSP        */
6467                 dbug(1, dprintf("discard1"));
6468                 plci->NL.RNR = 2;
6469                 return;
6470         }
6471
6472         if (((plci->NL.Ind & 0x0f) == N_UDATA)
6473             && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6474                 || (plci->B2_prot == 7)
6475                 || (plci->B3_prot == 7)))
6476         {
6477                 plci->ncpi_buffer[0] = 0;
6478
6479                 ncpi_state = plci->ncpi_state;
6480                 if (plci->NL.complete == 1)
6481                 {
6482                         byte *data = &plci->NL.RBuffer->P[0];
6483
6484                         if ((plci->NL.RBuffer->length >= 12)
6485                             && ((*data == DSP_UDATA_INDICATION_DCD_ON)
6486                                 || (*data == DSP_UDATA_INDICATION_CTS_ON)))
6487                         {
6488                                 word conn_opt, ncpi_opt = 0x00;
6489 /*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6490
6491                                 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6492                                         plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6493                                 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6494                                         plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6495
6496                                 data++;    /* indication code */
6497                                 data += 2; /* timestamp */
6498                                 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6499                                         ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6500                                 data++;    /* connected norm */
6501                                 conn_opt = GET_WORD(data);
6502                                 data += 2; /* connected options */
6503
6504                                 PUT_WORD(&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6505
6506                                 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6507                                 {
6508                                         ncpi_opt |= MDM_NCPI_ECM_V42;
6509                                 }
6510                                 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6511                                 {
6512                                         ncpi_opt |= MDM_NCPI_ECM_MNP;
6513                                 }
6514                                 else
6515                                 {
6516                                         ncpi_opt |= MDM_NCPI_TRANSPARENT;
6517                                 }
6518                                 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6519                                 {
6520                                         ncpi_opt |= MDM_NCPI_COMPRESSED;
6521                                 }
6522                                 PUT_WORD(&(plci->ncpi_buffer[3]), ncpi_opt);
6523                                 plci->ncpi_buffer[0] = 4;
6524
6525                                 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6526                         }
6527                 }
6528                 if (plci->B3_prot == 7)
6529                 {
6530                         if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6531                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6532                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6533                         {
6534                                 a->ncci_state[ncci] = INC_ACT_PENDING;
6535                                 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6536                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6537                         }
6538                 }
6539
6540                 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
6541                       & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6542                     || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6543                     || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6544
6545                 {
6546                         plci->NL.RNR = 2;
6547                         return;
6548                 }
6549         }
6550
6551         if (plci->NL.complete == 2)
6552         {
6553                 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6554                     && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6555                 {
6556                         switch (plci->RData[0].P[0])
6557                         {
6558
6559                         case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6560                                 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6561                                         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01X");
6562                                 break;
6563                         case DTMF_UDATA_INDICATION_ANSWER_TONE:
6564                                 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6565                                         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01Y");
6566                                 break;
6567                         case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6568                                 dtmf_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6569                                 break;
6570                         case DTMF_UDATA_INDICATION_DIGITS_SENT:
6571                                 dtmf_confirmation(Id, plci);
6572                                 break;
6573
6574
6575                         case UDATA_INDICATION_MIXER_TAP_DATA:
6576                                 capidtmf_recv_process_block(&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6577                                 i = capidtmf_indication(&(plci->capidtmf_state), dtmf_code_buffer + 1);
6578                                 if (i != 0)
6579                                 {
6580                                         dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6581                                         dtmf_indication(Id, plci, dtmf_code_buffer, (word)(i + 1));
6582                                 }
6583                                 break;
6584
6585
6586                         case UDATA_INDICATION_MIXER_COEFS_SET:
6587                                 mixer_indication_coefs_set(Id, plci);
6588                                 break;
6589                         case UDATA_INDICATION_XCONNECT_FROM:
6590                                 mixer_indication_xconnect_from(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6591                                 break;
6592                         case UDATA_INDICATION_XCONNECT_TO:
6593                                 mixer_indication_xconnect_to(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6594                                 break;
6595
6596
6597                         case LEC_UDATA_INDICATION_DISABLE_DETECT:
6598                                 ec_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6599                                 break;
6600
6601
6602
6603                         default:
6604                                 break;
6605                         }
6606                 }
6607                 else
6608                 {
6609                         if ((plci->RData[0].PLength != 0)
6610                             && ((plci->B2_prot == B2_V120_ASYNC)
6611                                 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6612                                 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6613                         {
6614
6615                                 sendf(plci->appl, _DATA_B3_I, Id, 0,
6616                                       "dwww",
6617                                       plci->RData[1].P,
6618                                       (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6619                                       plci->RNum,
6620                                       plci->RFlags);
6621
6622                         }
6623                         else
6624                         {
6625
6626                                 sendf(plci->appl, _DATA_B3_I, Id, 0,
6627                                       "dwww",
6628                                       plci->RData[0].P,
6629                                       plci->RData[0].PLength,
6630                                       plci->RNum,
6631                                       plci->RFlags);
6632
6633                         }
6634                 }
6635                 return;
6636         }
6637
6638         fax_feature_bits = 0;
6639         if ((plci->NL.Ind & 0x0f) == N_CONNECT ||
6640             (plci->NL.Ind & 0x0f) == N_CONNECT_ACK ||
6641             (plci->NL.Ind & 0x0f) == N_DISC ||
6642             (plci->NL.Ind & 0x0f) == N_EDATA ||
6643             (plci->NL.Ind & 0x0f) == N_DISC_ACK)
6644         {
6645                 info = 0;
6646                 plci->ncpi_buffer[0] = 0;
6647                 switch (plci->B3_prot) {
6648                 case  0: /*XPARENT*/
6649                 case  1: /*T.90 NL*/
6650                         break;    /* no network control protocol info - jfr */
6651                 case  2: /*ISO8202*/
6652                 case  3: /*X25 DCE*/
6653                         for (i = 0; i < plci->NL.RLength; i++) plci->ncpi_buffer[4 + i] = plci->NL.RBuffer->P[i];
6654                         plci->ncpi_buffer[0] = (byte)(i + 3);
6655                         plci->ncpi_buffer[1] = (byte)(plci->NL.Ind & N_D_BIT ? 1 : 0);
6656                         plci->ncpi_buffer[2] = 0;
6657                         plci->ncpi_buffer[3] = 0;
6658                         break;
6659                 case  4: /*T.30 - FAX*/
6660                 case  5: /*T.30 - FAX*/
6661                         if (plci->NL.RLength >= sizeof(T30_INFO))
6662                         {
6663                                 dbug(1, dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6664                                 len = 9;
6665                                 PUT_WORD(&(plci->ncpi_buffer[1]), ((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6666                                 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6667                                 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6668                                 if (plci->B3_prot == 5)
6669                                 {
6670                                         if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6671                                                 i |= 0x8000; /* This is not an ECM connection */
6672                                         if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6673                                                 i |= 0x4000; /* This is a connection with MMR compression */
6674                                         if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6675                                                 i |= 0x2000; /* This is a connection with MR compression */
6676                                         if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6677                                                 i |= 0x0004; /* More documents */
6678                                         if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6679                                                 i |= 0x0002; /* Fax-polling indication */
6680                                 }
6681                                 dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits, i));
6682                                 PUT_WORD(&(plci->ncpi_buffer[3]), i);
6683                                 PUT_WORD(&(plci->ncpi_buffer[5]), ((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6684                                 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6685                                 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6686                                 plci->ncpi_buffer[len] = 0;
6687                                 if (((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6688                                 {
6689                                         plci->ncpi_buffer[len] = 20;
6690                                         for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6691                                                 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6692                                 }
6693                                 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6694                                 {
6695                                         if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6696                                                 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6697                                         else
6698                                                 info = _FAX_PROTOCOL_ERROR;
6699                                 }
6700
6701                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6702                                     & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6703                                 {
6704                                         i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6705                                         while (i < plci->NL.RBuffer->length)
6706                                                 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6707                                 }
6708
6709                                 plci->ncpi_buffer[0] = len;
6710                                 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6711                                 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6712
6713                                 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6714                                 if (((plci->NL.Ind & 0x0f) == N_CONNECT_ACK)
6715                                     || (((plci->NL.Ind & 0x0f) == N_CONNECT)
6716                                         && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6717                                     || (((plci->NL.Ind & 0x0f) == N_EDATA)
6718                                         && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6719                                             || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6720                                             || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6721                                 {
6722                                         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6723                                 }
6724                                 if (((plci->NL.Ind & 0x0f) == N_DISC)
6725                                     || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)
6726                                     || (((plci->NL.Ind & 0x0f) == N_EDATA)
6727                                         && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6728                                 {
6729                                         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6730                                 }
6731                         }
6732                         break;
6733
6734                 case B3_RTP:
6735                         if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6736                         {
6737                                 if (plci->NL.RLength != 0)
6738                                 {
6739                                         info = rtp_info[plci->NL.RBuffer->P[0]];
6740                                         plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6741                                         for (i = 1; i < plci->NL.RLength; i++)
6742                                                 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6743                                 }
6744                         }
6745                         break;
6746
6747                 }
6748                 plci->NL.RNR = 2;
6749         }
6750         switch (plci->NL.Ind & 0x0f) {
6751         case N_EDATA:
6752                 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6753                 {
6754                         dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6755                                         ((T30_INFO *)plci->NL.RBuffer->P)->code));
6756                         fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6757
6758                         if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6759                             && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6760                             && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6761                             && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6762                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6763                             && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6764                         {
6765                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6766                                 sendf(plci->appl, _MANUFACTURER_I, Id, 0, "dwbS", _DI_MANU_ID, _DI_NEGOTIATE_B3,
6767                                       (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6768                                 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6769                                 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6770                                         fax_send_edata_ack = false;
6771                         }
6772
6773                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6774                         {
6775                                 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6776                                 {
6777                                 case EDATA_T30_DIS:
6778                                         if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6779                                             && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6780                                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6781                                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6782                                         {
6783                                                 a->ncci_state[ncci] = INC_ACT_PENDING;
6784                                                 if (plci->B3_prot == 4)
6785                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6786                                                 else
6787                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6788                                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6789                                         }
6790                                         break;
6791
6792                                 case EDATA_T30_TRAIN_OK:
6793                                         if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6794                                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6795                                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6796                                         {
6797                                                 if (plci->B3_prot == 4)
6798                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6799                                                 else
6800                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6801                                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6802                                         }
6803                                         break;
6804
6805                                 case EDATA_T30_EOP_CAPI:
6806                                         if (a->ncci_state[ncci] == CONNECTED)
6807                                         {
6808                                                 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", GOOD, plci->ncpi_buffer);
6809                                                 a->ncci_state[ncci] = INC_DIS_PENDING;
6810                                                 plci->ncpi_state = 0;
6811                                                 fax_send_edata_ack = false;
6812                                         }
6813                                         break;
6814                                 }
6815                         }
6816                         else
6817                         {
6818                                 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6819                                 {
6820                                 case EDATA_T30_TRAIN_OK:
6821                                         if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6822                                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6823                                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6824                                         {
6825                                                 if (plci->B3_prot == 4)
6826                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6827                                                 else
6828                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6829                                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6830                                         }
6831                                         break;
6832                                 }
6833                         }
6834                         if (fax_send_edata_ack)
6835                         {
6836                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6837                                 plci->fax_edata_ack_length = 1;
6838                                 start_internal_command(Id, plci, fax_edata_ack_command);
6839                         }
6840                 }
6841                 else
6842                 {
6843                         dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6844                 }
6845                 break;
6846         case N_CONNECT:
6847                 if (!a->ch_ncci[ch])
6848                 {
6849                         ncci = get_ncci(plci, ch, 0);
6850                         Id = (Id & 0xffff) | (((dword) ncci) << 16);
6851                 }
6852                 dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6853                                 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6854
6855                 msg = _CONNECT_B3_I;
6856                 if (a->ncci_state[ncci] == IDLE)
6857                         plci->channels++;
6858                 else if (plci->B3_prot == 1)
6859                         msg = _CONNECT_B3_T90_ACTIVE_I;
6860
6861                 a->ncci_state[ncci] = INC_CON_PENDING;
6862                 if (plci->B3_prot == 4)
6863                         sendf(plci->appl, msg, Id, 0, "s", "");
6864                 else
6865                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6866                 break;
6867         case N_CONNECT_ACK:
6868                 dbug(1, dprintf("N_connect_Ack"));
6869                 if (plci->internal_command_queue[0]
6870                     && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6871                         || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6872                         || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6873                 {
6874                         (*(plci->internal_command_queue[0]))(Id, plci, 0);
6875                         if (!plci->internal_command)
6876                                 next_internal_command(Id, plci);
6877                         break;
6878                 }
6879                 msg = _CONNECT_B3_ACTIVE_I;
6880                 if (plci->B3_prot == 1)
6881                 {
6882                         if (a->ncci_state[ncci] != OUTG_CON_PENDING)
6883                                 msg = _CONNECT_B3_T90_ACTIVE_I;
6884                         a->ncci_state[ncci] = INC_ACT_PENDING;
6885                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6886                 }
6887                 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
6888                 {
6889                         if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6890                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6891                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6892                         {
6893                                 a->ncci_state[ncci] = INC_ACT_PENDING;
6894                                 if (plci->B3_prot == 4)
6895                                         sendf(plci->appl, msg, Id, 0, "s", "");
6896                                 else
6897                                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6898                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6899                         }
6900                 }
6901                 else
6902                 {
6903                         a->ncci_state[ncci] = INC_ACT_PENDING;
6904                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6905                 }
6906                 if (plci->adjust_b_restore)
6907                 {
6908                         plci->adjust_b_restore = false;
6909                         start_internal_command(Id, plci, adjust_b_restore);
6910                 }
6911                 break;
6912         case N_DISC:
6913         case N_DISC_ACK:
6914                 if (plci->internal_command_queue[0]
6915                     && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
6916                         || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
6917                         || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
6918                 {
6919                         (*(plci->internal_command_queue[0]))(Id, plci, 0);
6920                         if (!plci->internal_command)
6921                                 next_internal_command(Id, plci);
6922                 }
6923                 ncci_state = a->ncci_state[ncci];
6924                 ncci_remove(plci, ncci, false);
6925
6926                 /* with N_DISC or N_DISC_ACK the IDI frees the respective   */
6927                 /* channel, so we cannot store the state in ncci_state! The */
6928                 /* information which channel we received a N_DISC is thus   */
6929                 /* stored in the inc_dis_ncci_table buffer.                 */
6930                 for (i = 0; plci->inc_dis_ncci_table[i]; i++);
6931                 plci->inc_dis_ncci_table[i] = (byte) ncci;
6932
6933                 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
6934                 if (!plci->channels
6935                     && (plci->B1_resource == 16)
6936                     && (plci->State <= CONNECTED))
6937                 {
6938                         len = 9;
6939                         i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
6940                         PUT_WORD(&plci->ncpi_buffer[1], i);
6941                         PUT_WORD(&plci->ncpi_buffer[3], 0);
6942                         i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
6943                         PUT_WORD(&plci->ncpi_buffer[5], i);
6944                         PUT_WORD(&plci->ncpi_buffer[7], 0);
6945                         plci->ncpi_buffer[len] = 0;
6946                         plci->ncpi_buffer[0] = len;
6947                         if (plci->B3_prot == 4)
6948                                 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "s", "");
6949                         else
6950                         {
6951
6952                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6953                                     & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6954                                 {
6955                                         plci->ncpi_buffer[++len] = 0;
6956                                         plci->ncpi_buffer[++len] = 0;
6957                                         plci->ncpi_buffer[++len] = 0;
6958                                         plci->ncpi_buffer[0] = len;
6959                                 }
6960
6961                                 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "S", plci->ncpi_buffer);
6962                         }
6963                         sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
6964                         plci->ncpi_state = 0;
6965                         sig_req(plci, HANGUP, 0);
6966                         send_req(plci);
6967                         plci->State = OUTG_DIS_PENDING;
6968                         /* disc here */
6969                 }
6970                 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6971                          && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6972                          && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
6973                 {
6974                         if (ncci_state == IDLE)
6975                         {
6976                                 if (plci->channels)
6977                                         plci->channels--;
6978                                 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
6979                                         if (plci->State == SUSPENDING) {
6980                                                 sendf(plci->appl,
6981                                                       _FACILITY_I,
6982                                                       Id & 0xffffL,
6983                                                       0,
6984                                                       "ws", (word)3, "\x03\x04\x00\x00");
6985                                                 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
6986                                         }
6987                                         plci_remove(plci);
6988                                         plci->State = IDLE;
6989                                 }
6990                         }
6991                 }
6992                 else if (plci->channels)
6993                 {
6994                         sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
6995                         plci->ncpi_state = 0;
6996                         if ((ncci_state == OUTG_REJ_PENDING)
6997                             && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
6998                         {
6999                                 sig_req(plci, HANGUP, 0);
7000                                 send_req(plci);
7001                                 plci->State = OUTG_DIS_PENDING;
7002                         }
7003                 }
7004                 break;
7005         case N_RESET:
7006                 a->ncci_state[ncci] = INC_RES_PENDING;
7007                 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7008                 break;
7009         case N_RESET_ACK:
7010                 a->ncci_state[ncci] = CONNECTED;
7011                 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7012                 break;
7013
7014         case N_UDATA:
7015                 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7016                 {
7017                         plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7018                         plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7019                         plci->NL.R = plci->RData;
7020                         plci->NL.RNum = 1;
7021                         return;
7022                 }
7023         case N_BDATA:
7024         case N_DATA:
7025                 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7026                     || (a->ncci_state[ncci] == IDLE)
7027                     || (a->ncci_state[ncci] == INC_DIS_PENDING))
7028                 {
7029                         plci->NL.RNR = 2;
7030                         break;
7031                 }
7032                 if ((a->ncci_state[ncci] != CONNECTED)
7033                     && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7034                     && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7035                 {
7036                         dbug(1, dprintf("flow control"));
7037                         plci->NL.RNR = 1; /* flow control  */
7038                         channel_x_off(plci, ch, 0);
7039                         break;
7040                 }
7041
7042                 NCCIcode = ncci | (((word)a->Id) << 8);
7043
7044                 /* count all buffers within the Application pool    */
7045                 /* belonging to the same NCCI. If this is below the */
7046                 /* number of buffers available per NCCI we accept   */
7047                 /* this packet, otherwise we reject it              */
7048                 count = 0;
7049                 Num = 0xffff;
7050                 for (i = 0; i < APPLptr->MaxBuffer; i++) {
7051                         if (NCCIcode == APPLptr->DataNCCI[i]) count++;
7052                         if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
7053                 }
7054
7055                 if (count >= APPLptr->MaxNCCIData || Num == 0xffff)
7056                 {
7057                         dbug(3, dprintf("Flow-Control"));
7058                         plci->NL.RNR = 1;
7059                         if (++(APPLptr->NCCIDataFlowCtrlTimer) >=
7060                             (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7061                         {
7062                                 plci->NL.RNR = 2;
7063                                 dbug(3, dprintf("DiscardData"));
7064                         } else {
7065                                 channel_x_off(plci, ch, 0);
7066                         }
7067                         break;
7068                 }
7069                 else
7070                 {
7071                         APPLptr->NCCIDataFlowCtrlTimer = 0;
7072                 }
7073
7074                 plci->RData[0].P = ReceiveBufferGet(APPLptr, Num);
7075                 if (!plci->RData[0].P) {
7076                         plci->NL.RNR = 1;
7077                         channel_x_off(plci, ch, 0);
7078                         break;
7079                 }
7080
7081                 APPLptr->DataNCCI[Num] = NCCIcode;
7082                 APPLptr->DataFlags[Num] = (plci->Id << 8) | (plci->NL.Ind >> 4);
7083                 dbug(3, dprintf("Buffer(%d), Max = %d", Num, APPLptr->MaxBuffer));
7084
7085                 plci->RNum = Num;
7086                 plci->RFlags = plci->NL.Ind >> 4;
7087                 plci->RData[0].PLength = APPLptr->MaxDataLength;
7088                 plci->NL.R = plci->RData;
7089                 if ((plci->NL.RLength != 0)
7090                     && ((plci->B2_prot == B2_V120_ASYNC)
7091                         || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7092                         || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7093                 {
7094                         plci->RData[1].P = plci->RData[0].P;
7095                         plci->RData[1].PLength = plci->RData[0].PLength;
7096                         plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7097                         if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7098                                 plci->RData[0].PLength = 1;
7099                         else
7100                                 plci->RData[0].PLength = 2;
7101                         if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7102                                 plci->RFlags |= 0x0010;
7103                         if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7104                                 plci->RFlags |= 0x8000;
7105                         plci->NL.RNum = 2;
7106                 }
7107                 else
7108                 {
7109                         if ((plci->NL.Ind & 0x0f) == N_UDATA)
7110                                 plci->RFlags |= 0x0010;
7111
7112                         else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7113                                 plci->RFlags |= 0x0001;
7114
7115                         plci->NL.RNum = 1;
7116                 }
7117                 break;
7118         case N_DATA_ACK:
7119                 data_ack(plci, ch);
7120                 break;
7121         default:
7122                 plci->NL.RNR = 2;
7123                 break;
7124         }
7125 }
7126
7127 /*------------------------------------------------------------------*/
7128 /* find a free PLCI */
7129 /*------------------------------------------------------------------*/
7130
7131 static word get_plci(DIVA_CAPI_ADAPTER *a)
7132 {
7133         word i, j;
7134         PLCI *plci;
7135
7136         for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
7137         if (i == a->max_plci) {
7138                 dbug(1, dprintf("get_plci: out of PLCIs"));
7139                 return 0;
7140         }
7141         plci = &a->plci[i];
7142         plci->Id = (byte)(i + 1);
7143
7144         plci->Sig.Id = 0;
7145         plci->NL.Id = 0;
7146         plci->sig_req = 0;
7147         plci->nl_req = 0;
7148
7149         plci->appl = NULL;
7150         plci->relatedPTYPLCI = NULL;
7151         plci->State = IDLE;
7152         plci->SuppState = IDLE;
7153         plci->channels = 0;
7154         plci->tel = 0;
7155         plci->B1_resource = 0;
7156         plci->B2_prot = 0;
7157         plci->B3_prot = 0;
7158
7159         plci->command = 0;
7160         plci->m_command = 0;
7161         init_internal_command_queue(plci);
7162         plci->number = 0;
7163         plci->req_in_start = 0;
7164         plci->req_in = 0;
7165         plci->req_out = 0;
7166         plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7167         plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7168         plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7169
7170         plci->data_sent = false;
7171         plci->send_disc = 0;
7172         plci->sig_global_req = 0;
7173         plci->sig_remove_id = 0;
7174         plci->nl_global_req = 0;
7175         plci->nl_remove_id = 0;
7176         plci->adv_nl = 0;
7177         plci->manufacturer = false;
7178         plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7179         plci->spoofed_msg = 0;
7180         plci->ptyState = 0;
7181         plci->cr_enquiry = false;
7182         plci->hangup_flow_ctrl_timer = 0;
7183
7184         plci->ncci_ring_list = 0;
7185         for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
7186         bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
7187         bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
7188         plci->fax_connect_info_length = 0;
7189         plci->nsf_control_bits = 0;
7190         plci->ncpi_state = 0x00;
7191         plci->ncpi_buffer[0] = 0;
7192
7193         plci->requested_options_conn = 0;
7194         plci->requested_options = 0;
7195         plci->notifiedcall = 0;
7196         plci->vswitchstate = 0;
7197         plci->vsprot = 0;
7198         plci->vsprotdialect = 0;
7199         init_b1_config(plci);
7200         dbug(1, dprintf("get_plci(%x)", plci->Id));
7201         return i + 1;
7202 }
7203
7204 /*------------------------------------------------------------------*/
7205 /* put a parameter in the parameter buffer                          */
7206 /*------------------------------------------------------------------*/
7207
7208 static void add_p(PLCI *plci, byte code, byte *p)
7209 {
7210         word p_length;
7211
7212         p_length = 0;
7213         if (p) p_length = p[0];
7214         add_ie(plci, code, p, p_length);
7215 }
7216
7217 /*------------------------------------------------------------------*/
7218 /* put a structure in the parameter buffer                          */
7219 /*------------------------------------------------------------------*/
7220 static void add_s(PLCI *plci, byte code, API_PARSE *p)
7221 {
7222         if (p) add_ie(plci, code, p->info, (word)p->length);
7223 }
7224
7225 /*------------------------------------------------------------------*/
7226 /* put multiple structures in the parameter buffer                  */
7227 /*------------------------------------------------------------------*/
7228 static void add_ss(PLCI *plci, byte code, API_PARSE *p)
7229 {
7230         byte i;
7231
7232         if (p) {
7233                 dbug(1, dprintf("add_ss(%x,len=%d)", code, p->length));
7234                 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7235                         dbug(1, dprintf("add_ss_ie(%x,len=%d)", p->info[i - 1], p->info[i]));
7236                         add_ie(plci, p->info[i - 1], (byte *)&(p->info[i]), (word)p->info[i]);
7237                 }
7238         }
7239 }
7240
7241 /*------------------------------------------------------------------*/
7242 /* return the channel number sent by the application in a esc_chi   */
7243 /*------------------------------------------------------------------*/
7244 static byte getChannel(API_PARSE *p)
7245 {
7246         byte i;
7247
7248         if (p) {
7249                 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7250                         if (p->info[i] == 2) {
7251                                 if (p->info[i - 1] == ESC && p->info[i + 1] == CHI) return (p->info[i + 2]);
7252                         }
7253                 }
7254         }
7255         return 0;
7256 }
7257
7258
7259 /*------------------------------------------------------------------*/
7260 /* put an information element in the parameter buffer               */
7261 /*------------------------------------------------------------------*/
7262
7263 static void add_ie(PLCI *plci, byte code, byte *p, word p_length)
7264 {
7265         word i;
7266
7267         if (!(code & 0x80) && !p_length) return;
7268
7269         if (plci->req_in == plci->req_in_start) {
7270                 plci->req_in += 2;
7271         }
7272         else {
7273                 plci->req_in--;
7274         }
7275         plci->RBuffer[plci->req_in++] = code;
7276
7277         if (p) {
7278                 plci->RBuffer[plci->req_in++] = (byte)p_length;
7279                 for (i = 0; i < p_length; i++) plci->RBuffer[plci->req_in++] = p[1 + i];
7280         }
7281
7282         plci->RBuffer[plci->req_in++] = 0;
7283 }
7284
7285 /*------------------------------------------------------------------*/
7286 /* put a unstructured data into the buffer                          */
7287 /*------------------------------------------------------------------*/
7288
7289 static void add_d(PLCI *plci, word length, byte *p)
7290 {
7291         word i;
7292
7293         if (plci->req_in == plci->req_in_start) {
7294                 plci->req_in += 2;
7295         }
7296         else {
7297                 plci->req_in--;
7298         }
7299         for (i = 0; i < length; i++) plci->RBuffer[plci->req_in++] = p[i];
7300 }
7301
7302 /*------------------------------------------------------------------*/
7303 /* put parameters from the Additional Info parameter in the         */
7304 /* parameter buffer                                                 */
7305 /*------------------------------------------------------------------*/
7306
7307 static void add_ai(PLCI *plci, API_PARSE *ai)
7308 {
7309         word i;
7310         API_PARSE ai_parms[5];
7311
7312         for (i = 0; i < 5; i++) ai_parms[i].length = 0;
7313
7314         if (!ai->length)
7315                 return;
7316         if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7317                 return;
7318
7319         add_s(plci, KEY, &ai_parms[1]);
7320         add_s(plci, UUI, &ai_parms[2]);
7321         add_ss(plci, FTY, &ai_parms[3]);
7322 }
7323
7324 /*------------------------------------------------------------------*/
7325 /* put parameter for b1 protocol in the parameter buffer            */
7326 /*------------------------------------------------------------------*/
7327
7328 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7329                    word b1_facilities)
7330 {
7331         API_PARSE bp_parms[8];
7332         API_PARSE mdm_cfg[9];
7333         API_PARSE global_config[2];
7334         byte cai[256];
7335         byte resource[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7336         byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7337         word i;
7338
7339         API_PARSE mdm_cfg_v18[4];
7340         word j, n, w;
7341         dword d;
7342
7343
7344         for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7345         for (i = 0; i < 2; i++) global_config[i].length = 0;
7346
7347         dbug(1, dprintf("add_b1"));
7348         api_save_msg(bp, "s", &plci->B_protocol);
7349
7350         if (b_channel_info == 2) {
7351                 plci->B1_resource = 0;
7352                 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7353                 add_p(plci, CAI, "\x01\x00");
7354                 dbug(1, dprintf("Cai=1,0 (no resource)"));
7355                 return 0;
7356         }
7357
7358         if (plci->tel == CODEC_PERMANENT) return 0;
7359         else if (plci->tel == CODEC) {
7360                 plci->B1_resource = 1;
7361                 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7362                 add_p(plci, CAI, "\x01\x01");
7363                 dbug(1, dprintf("Cai=1,1 (Codec)"));
7364                 return 0;
7365         }
7366         else if (plci->tel == ADV_VOICE) {
7367                 plci->B1_resource = add_b1_facilities(plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7368                 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7369                 voice_cai[1] = plci->B1_resource;
7370                 PUT_WORD(&voice_cai[5], plci->appl->MaxDataLength);
7371                 add_p(plci, CAI, voice_cai);
7372                 dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai[1]));
7373                 return 0;
7374         }
7375         plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7376         if (plci->call_dir & CALL_DIR_OUT)
7377                 plci->call_dir |= CALL_DIR_ORIGINATE;
7378         else if (plci->call_dir & CALL_DIR_IN)
7379                 plci->call_dir |= CALL_DIR_ANSWER;
7380
7381         if (!bp->length) {
7382                 plci->B1_resource = 0x5;
7383                 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7384                 add_p(plci, CAI, "\x01\x05");
7385                 return 0;
7386         }
7387
7388         dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7389         if (bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7390         if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7391         {
7392                 bp_parms[6].length = 0;
7393                 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7394                 {
7395                         dbug(1, dprintf("b-form.!"));
7396                         return _WRONG_MESSAGE_FORMAT;
7397                 }
7398         }
7399         else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7400         {
7401                 dbug(1, dprintf("b-form.!"));
7402                 return _WRONG_MESSAGE_FORMAT;
7403         }
7404
7405         if (bp_parms[6].length)
7406         {
7407                 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7408                 {
7409                         return _WRONG_MESSAGE_FORMAT;
7410                 }
7411                 switch (GET_WORD(global_config[0].info))
7412                 {
7413                 case 1:
7414                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7415                         break;
7416                 case 2:
7417                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7418                         break;
7419                 }
7420         }
7421         dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7422
7423
7424         if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7425             && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7426         {
7427                 plci->B1_resource = add_b1_facilities(plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7428                 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7429                 cai[1] = plci->B1_resource;
7430                 cai[2] = 0;
7431                 cai[3] = 0;
7432                 cai[4] = 0;
7433                 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7434                 for (i = 0; i < bp_parms[3].length; i++)
7435                         cai[7 + i] = bp_parms[3].info[1 + i];
7436                 cai[0] = 6 + bp_parms[3].length;
7437                 add_p(plci, CAI, cai);
7438                 return 0;
7439         }
7440
7441
7442         if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7443             && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7444         {
7445                 plci->B1_resource = add_b1_facilities(plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7446                 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7447                 cai[1] = plci->B1_resource;
7448                 cai[2] = 0;
7449                 cai[3] = 0;
7450                 cai[4] = 0;
7451                 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7452                 cai[0] = 6;
7453                 add_p(plci, CAI, cai);
7454                 return 0;
7455         }
7456
7457
7458         if ((GET_WORD(bp_parms[0].info) >= 32)
7459             || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7460                 && ((GET_WORD(bp_parms[0].info) != 3)
7461                     || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7462                     || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7463         {
7464                 return _B1_NOT_SUPPORTED;
7465         }
7466         plci->B1_resource = add_b1_facilities(plci, resource[GET_WORD(bp_parms[0].info)],
7467                                               (word)(b1_facilities & ~B1_FACILITY_VOICE));
7468         adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7469         cai[0] = 6;
7470         cai[1] = plci->B1_resource;
7471         for (i = 2; i < sizeof(cai); i++) cai[i] = 0;
7472
7473         if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7474             || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7475             || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7476         { /* B1 - modem */
7477                 for (i = 0; i < 7; i++) mdm_cfg[i].length = 0;
7478
7479                 if (bp_parms[3].length)
7480                 {
7481                         if (api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwww", mdm_cfg))
7482                         {
7483                                 return (_WRONG_MESSAGE_FORMAT);
7484                         }
7485
7486                         cai[2] = 0; /* Bit rate for adaptation */
7487
7488                         dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7489
7490                         PUT_WORD(&cai[13], 0);                          /* Min Tx speed */
7491                         PUT_WORD(&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7492                         PUT_WORD(&cai[17], 0);                          /* Min Rx speed */
7493                         PUT_WORD(&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7494
7495                         cai[3] = 0; /* Async framing parameters */
7496                         switch (GET_WORD(mdm_cfg[2].info))
7497                         {       /* Parity     */
7498                         case 1: /* odd parity */
7499                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7500                                 dbug(1, dprintf("MDM: odd parity"));
7501                                 break;
7502
7503                         case 2: /* even parity */
7504                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7505                                 dbug(1, dprintf("MDM: even parity"));
7506                                 break;
7507
7508                         default:
7509                                 dbug(1, dprintf("MDM: no parity"));
7510                                 break;
7511                         }
7512
7513                         switch (GET_WORD(mdm_cfg[3].info))
7514                         {       /* stop bits   */
7515                         case 1: /* 2 stop bits */
7516                                 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7517                                 dbug(1, dprintf("MDM: 2 stop bits"));
7518                                 break;
7519
7520                         default:
7521                                 dbug(1, dprintf("MDM: 1 stop bit"));
7522                                 break;
7523                         }
7524
7525                         switch (GET_WORD(mdm_cfg[1].info))
7526                         {     /* char length */
7527                         case 5:
7528                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7529                                 dbug(1, dprintf("MDM: 5 bits"));
7530                                 break;
7531
7532                         case 6:
7533                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7534                                 dbug(1, dprintf("MDM: 6 bits"));
7535                                 break;
7536
7537                         case 7:
7538                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7539                                 dbug(1, dprintf("MDM: 7 bits"));
7540                                 break;
7541
7542                         default:
7543                                 dbug(1, dprintf("MDM: 8 bits"));
7544                                 break;
7545                         }
7546
7547                         cai[7] = 0; /* Line taking options */
7548                         cai[8] = 0; /* Modulation negotiation options */
7549                         cai[9] = 0; /* Modulation options */
7550
7551                         if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7552                         {
7553                                 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7554                                 dbug(1, dprintf("MDM: Reverse direction"));
7555                         }
7556
7557                         if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7558                         {
7559                                 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7560                                 dbug(1, dprintf("MDM: Disable retrain"));
7561                         }
7562
7563                         if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7564                         {
7565                                 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7566                                 dbug(1, dprintf("MDM: Disable ring tone"));
7567                         }
7568
7569                         if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7570                         {
7571                                 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7572                                 dbug(1, dprintf("MDM: 1800 guard tone"));
7573                         }
7574                         else if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_550)
7575                         {
7576                                 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7577                                 dbug(1, dprintf("MDM: 550 guard tone"));
7578                         }
7579
7580                         if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7581                         {
7582                                 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7583                                 dbug(1, dprintf("MDM: V100"));
7584                         }
7585                         else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7586                         {
7587                                 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7588                                 dbug(1, dprintf("MDM: IN CLASS"));
7589                         }
7590                         else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7591                         {
7592                                 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7593                                 dbug(1, dprintf("MDM: DISABLED"));
7594                         }
7595                         cai[0] = 20;
7596
7597                         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7598                             && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7599                         {
7600                                 plci->requested_options |= 1L << PRIVATE_V18;
7601                         }
7602                         if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7603                                 plci->requested_options |= 1L << PRIVATE_VOWN;
7604
7605                         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
7606                             & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7607                         {
7608                                 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwws", mdm_cfg))
7609                                 {
7610                                         i = 27;
7611                                         if (mdm_cfg[6].length >= 4)
7612                                         {
7613                                                 d = GET_DWORD(&mdm_cfg[6].info[1]);
7614                                                 cai[7] |= (byte) d;          /* line taking options */
7615                                                 cai[9] |= (byte)(d >> 8);    /* modulation options */
7616                                                 cai[++i] = (byte)(d >> 16);  /* vown modulation options */
7617                                                 cai[++i] = (byte)(d >> 24);
7618                                                 if (mdm_cfg[6].length >= 8)
7619                                                 {
7620                                                         d = GET_DWORD(&mdm_cfg[6].info[5]);
7621                                                         cai[10] |= (byte) d;        /* disabled modulations mask */
7622                                                         cai[11] |= (byte)(d >> 8);
7623                                                         if (mdm_cfg[6].length >= 12)
7624                                                         {
7625                                                                 d = GET_DWORD(&mdm_cfg[6].info[9]);
7626                                                                 cai[12] = (byte) d;          /* enabled modulations mask */
7627                                                                 cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */
7628                                                                 cai[++i] = (byte)(d >> 16);
7629                                                                 cai[++i] = (byte)(d >> 24);
7630                                                                 cai[++i] = 0;
7631                                                                 if (mdm_cfg[6].length >= 14)
7632                                                                 {
7633                                                                         w = GET_WORD(&mdm_cfg[6].info[13]);
7634                                                                         if (w != 0)
7635                                                                                 PUT_WORD(&cai[13], w);  /* min tx speed */
7636                                                                         if (mdm_cfg[6].length >= 16)
7637                                                                         {
7638                                                                                 w = GET_WORD(&mdm_cfg[6].info[15]);
7639                                                                                 if (w != 0)
7640                                                                                         PUT_WORD(&cai[15], w);  /* max tx speed */
7641                                                                                 if (mdm_cfg[6].length >= 18)
7642                                                                                 {
7643                                                                                         w = GET_WORD(&mdm_cfg[6].info[17]);
7644                                                                                         if (w != 0)
7645                                                                                                 PUT_WORD(&cai[17], w);  /* min rx speed */
7646                                                                                         if (mdm_cfg[6].length >= 20)
7647                                                                                         {
7648                                                                                                 w = GET_WORD(&mdm_cfg[6].info[19]);
7649                                                                                                 if (w != 0)
7650                                                                                                         PUT_WORD(&cai[19], w);  /* max rx speed */
7651                                                                                                 if (mdm_cfg[6].length >= 22)
7652                                                                                                 {
7653                                                                                                         w = GET_WORD(&mdm_cfg[6].info[21]);
7654                                                                                                         cai[23] = (byte)(-((short) w));  /* transmit level */
7655                                                                                                         if (mdm_cfg[6].length >= 24)
7656                                                                                                         {
7657                                                                                                                 w = GET_WORD(&mdm_cfg[6].info[23]);
7658                                                                                                                 cai[22] |= (byte) w;        /* info options mask */
7659                                                                                                                 cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */
7660                                                                                                         }
7661                                                                                                 }
7662                                                                                         }
7663                                                                                 }
7664                                                                         }
7665                                                                 }
7666                                                         }
7667                                                 }
7668                                         }
7669                                         cai[27] = i - 27;
7670                                         i++;
7671                                         if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwwss", mdm_cfg))
7672                                         {
7673                                                 if (!api_parse(&mdm_cfg[7].info[1], (word)mdm_cfg[7].length, "sss", mdm_cfg_v18))
7674                                                 {
7675                                                         for (n = 0; n < 3; n++)
7676                                                         {
7677                                                                 cai[i] = (byte)(mdm_cfg_v18[n].length);
7678                                                                 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7679                                                                         cai[i + j] = mdm_cfg_v18[n].info[j];
7680                                                                 i += cai[i] + 1;
7681                                                         }
7682                                                 }
7683                                         }
7684                                         cai[0] = (byte)(i - 1);
7685                                 }
7686                         }
7687
7688                 }
7689         }
7690         if (GET_WORD(bp_parms[0].info) == 2 ||                         /* V.110 async */
7691             GET_WORD(bp_parms[0].info) == 3)                           /* V.110 sync */
7692         {
7693                 if (bp_parms[3].length) {
7694                         dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms[3].info[1])));
7695                         switch (GET_WORD(&bp_parms[3].info[1])) {                 /* Rate */
7696                         case 0:
7697                         case 56000:
7698                                 if (GET_WORD(bp_parms[0].info) == 3) {                  /* V.110 sync 56k */
7699                                         dbug(1, dprintf("56k sync HSCX"));
7700                                         cai[1] = 8;
7701                                         cai[2] = 0;
7702                                         cai[3] = 0;
7703                                 }
7704                                 else if (GET_WORD(bp_parms[0].info) == 2) {
7705                                         dbug(1, dprintf("56k async DSP"));
7706                                         cai[2] = 9;
7707                                 }
7708                                 break;
7709                         case 50:     cai[2] = 1;  break;
7710                         case 75:     cai[2] = 1;  break;
7711                         case 110:    cai[2] = 1;  break;
7712                         case 150:    cai[2] = 1;  break;
7713                         case 200:    cai[2] = 1;  break;
7714                         case 300:    cai[2] = 1;  break;
7715                         case 600:    cai[2] = 1;  break;
7716                         case 1200:   cai[2] = 2;  break;
7717                         case 2400:   cai[2] = 3;  break;
7718                         case 4800:   cai[2] = 4;  break;
7719                         case 7200:   cai[2] = 10; break;
7720                         case 9600:   cai[2] = 5;  break;
7721                         case 12000:  cai[2] = 13; break;
7722                         case 24000:  cai[2] = 0;  break;
7723                         case 14400:  cai[2] = 11; break;
7724                         case 19200:  cai[2] = 6;  break;
7725                         case 28800:  cai[2] = 12; break;
7726                         case 38400:  cai[2] = 7;  break;
7727                         case 48000:  cai[2] = 8;  break;
7728                         case 76:     cai[2] = 15; break;  /* 75/1200     */
7729                         case 1201:   cai[2] = 14; break;  /* 1200/75     */
7730                         case 56001:  cai[2] = 9;  break;  /* V.110 56000 */
7731
7732                         default:
7733                                 return _B1_PARM_NOT_SUPPORTED;
7734                         }
7735                         cai[3] = 0;
7736                         if (cai[1] == 13)                                        /* v.110 async */
7737                         {
7738                                 if (bp_parms[3].length >= 8)
7739                                 {
7740                                         switch (GET_WORD(&bp_parms[3].info[3]))
7741                                         {       /* char length */
7742                                         case 5:
7743                                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7744                                                 break;
7745                                         case 6:
7746                                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7747                                                 break;
7748                                         case 7:
7749                                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7750                                                 break;
7751                                         }
7752                                         switch (GET_WORD(&bp_parms[3].info[5]))
7753                                         {       /* Parity     */
7754                                         case 1: /* odd parity */
7755                                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7756                                                 break;
7757                                         case 2: /* even parity */
7758                                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7759                                                 break;
7760                                         }
7761                                         switch (GET_WORD(&bp_parms[3].info[7]))
7762                                         {       /* stop bits   */
7763                                         case 1: /* 2 stop bits */
7764                                                 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7765                                                 break;
7766                                         }
7767                                 }
7768                         }
7769                 }
7770                 else if (cai[1] == 8 || GET_WORD(bp_parms[0].info) == 3) {
7771                         dbug(1, dprintf("V.110 default 56k sync"));
7772                         cai[1] = 8;
7773                         cai[2] = 0;
7774                         cai[3] = 0;
7775                 }
7776                 else {
7777                         dbug(1, dprintf("V.110 default 9600 async"));
7778                         cai[2] = 5;
7779                 }
7780         }
7781         PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7782         dbug(1, dprintf("CAI[%d]=%x,%x,%x,%x,%x,%x", cai[0], cai[1], cai[2], cai[3], cai[4], cai[5], cai[6]));
7783 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7784
7785         add_p(plci, CAI, cai);
7786         return 0;
7787 }
7788
7789 /*------------------------------------------------------------------*/
7790 /* put parameter for b2 and B3  protocol in the parameter buffer    */
7791 /*------------------------------------------------------------------*/
7792
7793 static word add_b23(PLCI *plci, API_PARSE *bp)
7794 {
7795         word i, fax_control_bits;
7796         byte pos, len;
7797         byte SAPI = 0x40;  /* default SAPI 16 for x.31 */
7798         API_PARSE bp_parms[8];
7799         API_PARSE *b1_config;
7800         API_PARSE *b2_config;
7801         API_PARSE b2_config_parms[8];
7802         API_PARSE *b3_config;
7803         API_PARSE b3_config_parms[6];
7804         API_PARSE global_config[2];
7805
7806         static byte llc[3] = {2,0,0};
7807         static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7808         static byte nlc[256];
7809         static byte lli[12] = {1,1};
7810
7811         const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7812         const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7813
7814         const byte llc3[] = {4,3,2,2,6,6,0};
7815         const byte header[] = {0,2,3,3,0,0,0};
7816
7817         for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7818         for (i = 0; i < 6; i++) b2_config_parms[i].length = 0;
7819         for (i = 0; i < 5; i++) b3_config_parms[i].length = 0;
7820
7821         lli[0] = 1;
7822         lli[1] = 1;
7823         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7824                 lli[1] |= 2;
7825         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7826                 lli[1] |= 4;
7827
7828         if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7829                 lli[1] |= 0x10;
7830                 if (plci->rx_dma_descriptor <= 0) {
7831                         plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
7832                         if (plci->rx_dma_descriptor >= 0)
7833                                 plci->rx_dma_descriptor++;
7834                 }
7835                 if (plci->rx_dma_descriptor > 0) {
7836                         lli[0] = 6;
7837                         lli[1] |= 0x40;
7838                         lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7839                         lli[3] = (byte)plci->rx_dma_magic;
7840                         lli[4] = (byte)(plci->rx_dma_magic >>  8);
7841                         lli[5] = (byte)(plci->rx_dma_magic >> 16);
7842                         lli[6] = (byte)(plci->rx_dma_magic >> 24);
7843                 }
7844         }
7845
7846         if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7847                 lli[1] |= 0x20;
7848         }
7849
7850         dbug(1, dprintf("add_b23"));
7851         api_save_msg(bp, "s", &plci->B_protocol);
7852
7853         if (!bp->length && plci->tel)
7854         {
7855                 plci->adv_nl = true;
7856                 dbug(1, dprintf("Default adv.Nl"));
7857                 add_p(plci, LLI, lli);
7858                 plci->B2_prot = 1 /*XPARENT*/;
7859                 plci->B3_prot = 0 /*XPARENT*/;
7860                 llc[1] = 2;
7861                 llc[2] = 4;
7862                 add_p(plci, LLC, llc);
7863                 dlc[0] = 2;
7864                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7865                 add_p(plci, DLC, dlc);
7866                 return 0;
7867         }
7868
7869         if (!bp->length) /*default*/
7870         {
7871                 dbug(1, dprintf("ret default"));
7872                 add_p(plci, LLI, lli);
7873                 plci->B2_prot = 0 /*X.75   */;
7874                 plci->B3_prot = 0 /*XPARENT*/;
7875                 llc[1] = 1;
7876                 llc[2] = 4;
7877                 add_p(plci, LLC, llc);
7878                 dlc[0] = 2;
7879                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7880                 add_p(plci, DLC, dlc);
7881                 return 0;
7882         }
7883         dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7884         if ((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT;
7885
7886         if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7887         {
7888                 bp_parms[6].length = 0;
7889                 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7890                 {
7891                         dbug(1, dprintf("b-form.!"));
7892                         return _WRONG_MESSAGE_FORMAT;
7893                 }
7894         }
7895         else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7896         {
7897                 dbug(1, dprintf("b-form.!"));
7898                 return _WRONG_MESSAGE_FORMAT;
7899         }
7900
7901         if (plci->tel == ADV_VOICE) /* transparent B on advanced voice */
7902         {
7903                 if (GET_WORD(bp_parms[1].info) != 1
7904                     || GET_WORD(bp_parms[2].info) != 0) return _B2_NOT_SUPPORTED;
7905                 plci->adv_nl = true;
7906         }
7907         else if (plci->tel) return _B2_NOT_SUPPORTED;
7908
7909
7910         if ((GET_WORD(bp_parms[1].info) == B2_RTP)
7911             && (GET_WORD(bp_parms[2].info) == B3_RTP)
7912             && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7913         {
7914                 add_p(plci, LLI, lli);
7915                 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
7916                 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
7917                 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
7918                 llc[2] = 4;
7919                 add_p(plci, LLC, llc);
7920                 dlc[0] = 2;
7921                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7922                 dlc[3] = 3; /* Addr A */
7923                 dlc[4] = 1; /* Addr B */
7924                 dlc[5] = 7; /* modulo mode */
7925                 dlc[6] = 7; /* window size */
7926                 dlc[7] = 0; /* XID len Lo  */
7927                 dlc[8] = 0; /* XID len Hi  */
7928                 for (i = 0; i < bp_parms[4].length; i++)
7929                         dlc[9 + i] = bp_parms[4].info[1 + i];
7930                 dlc[0] = (byte)(8 + bp_parms[4].length);
7931                 add_p(plci, DLC, dlc);
7932                 for (i = 0; i < bp_parms[5].length; i++)
7933                         nlc[1 + i] = bp_parms[5].info[1 + i];
7934                 nlc[0] = (byte)(bp_parms[5].length);
7935                 add_p(plci, NLC, nlc);
7936                 return 0;
7937         }
7938
7939
7940
7941         if ((GET_WORD(bp_parms[1].info) >= 32)
7942             || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
7943                 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
7944                     || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
7945
7946         {
7947                 return _B2_NOT_SUPPORTED;
7948         }
7949         if ((GET_WORD(bp_parms[2].info) >= 32)
7950             || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
7951         {
7952                 return _B3_NOT_SUPPORTED;
7953         }
7954         if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
7955             && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7956                 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7957                 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
7958         {
7959                 return (add_modem_b23(plci, bp_parms));
7960         }
7961
7962         add_p(plci, LLI, lli);
7963
7964         plci->B2_prot = (byte)GET_WORD(bp_parms[1].info);
7965         plci->B3_prot = (byte)GET_WORD(bp_parms[2].info);
7966         if (plci->B2_prot == 12) SAPI = 0; /* default SAPI D-channel */
7967
7968         if (bp_parms[6].length)
7969         {
7970                 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7971                 {
7972                         return _WRONG_MESSAGE_FORMAT;
7973                 }
7974                 switch (GET_WORD(global_config[0].info))
7975                 {
7976                 case 1:
7977                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7978                         break;
7979                 case 2:
7980                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7981                         break;
7982                 }
7983         }
7984         dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7985
7986
7987         if (plci->B2_prot == B2_PIAFS)
7988                 llc[1] = PIAFS_CRC;
7989         else
7990 /* IMPLEMENT_PIAFS */
7991         {
7992                 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
7993                         llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
7994         }
7995         llc[2] = llc3[GET_WORD(bp_parms[2].info)];
7996
7997         add_p(plci, LLC, llc);
7998
7999         dlc[0] = 2;
8000         PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8001                  header[GET_WORD(bp_parms[2].info)]);
8002
8003         b1_config = &bp_parms[3];
8004         nlc[0] = 0;
8005         if (plci->B3_prot == 4
8006             || plci->B3_prot == 5)
8007         {
8008                 for (i = 0; i < sizeof(T30_INFO); i++) nlc[i] = 0;
8009                 nlc[0] = sizeof(T30_INFO);
8010                 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8011                         ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8012                 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8013                 if (b1_config->length >= 2)
8014                 {
8015                         ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1]) / 2400);
8016                 }
8017         }
8018         b2_config = &bp_parms[4];
8019
8020
8021         if (llc[1] == PIAFS_CRC)
8022         {
8023                 if (plci->B3_prot != B3_TRANSPARENT)
8024                 {
8025                         return _B_STACK_NOT_SUPPORTED;
8026                 }
8027                 if (b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8028                         return _WRONG_MESSAGE_FORMAT;
8029                 }
8030                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8031                 dlc[3] = 0; /* Addr A */
8032                 dlc[4] = 0; /* Addr B */
8033                 dlc[5] = 0; /* modulo mode */
8034                 dlc[6] = 0; /* window size */
8035                 if (b2_config->length >= 7) {
8036                         dlc[7] = 7;
8037                         dlc[8] = 0;
8038                         dlc[9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8039                         dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8040                         dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8041                         dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8042                         dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8043                         dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8044                         dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8045                         dlc[0] = 15;
8046                         if (b2_config->length >= 8) { /* PIAFS control abilities */
8047                                 dlc[7] = 10;
8048                                 dlc[16] = 2; /* Length of PIAFS extension */
8049                                 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8050                                 dlc[18] = b2_config_parms[4].info[0]; /* value */
8051                                 dlc[0] = 18;
8052                         }
8053                 }
8054                 else /* default values, 64K, variable, no compression */
8055                 {
8056                         dlc[7] = 7;
8057                         dlc[8] = 0;
8058                         dlc[9] = 0x03; /* PIAFS protocol Speed configuration */
8059                         dlc[10] = 0x03; /* V.42bis P0 */
8060                         dlc[11] = 0;    /* V.42bis P0 */
8061                         dlc[12] = 0;    /* V.42bis P1 */
8062                         dlc[13] = 0;    /* V.42bis P1 */
8063                         dlc[14] = 0;    /* V.42bis P2 */
8064                         dlc[15] = 0;    /* V.42bis P2 */
8065                         dlc[0] = 15;
8066                 }
8067                 add_p(plci, DLC, dlc);
8068         }
8069         else
8070
8071                 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8072                 {
8073                         if (plci->B3_prot != B3_TRANSPARENT)
8074                                 return _B_STACK_NOT_SUPPORTED;
8075
8076                         dlc[0] = 6;
8077                         PUT_WORD(&dlc[1], GET_WORD(&dlc[1]) + 2);
8078                         dlc[3] = 0x08;
8079                         dlc[4] = 0x01;
8080                         dlc[5] = 127;
8081                         dlc[6] = 7;
8082                         if (b2_config->length != 0)
8083                         {
8084                                 if ((llc[1] == V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8085                                         return _WRONG_MESSAGE_FORMAT;
8086                                 }
8087                                 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8088                                 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8089                                 if (b2_config->info[3] != 128)
8090                                 {
8091                                         dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8092                                         return _B2_PARM_NOT_SUPPORTED;
8093                                 }
8094                                 dlc[5] = (byte)(b2_config->info[3] - 1);
8095                                 dlc[6] = b2_config->info[4];
8096                                 if (llc[1] == V120_V42BIS) {
8097                                         if (b2_config->length >= 10) {
8098                                                 dlc[7] = 6;
8099                                                 dlc[8] = 0;
8100                                                 dlc[9] = b2_config_parms[4].info[0];
8101                                                 dlc[10] = b2_config_parms[4].info[1];
8102                                                 dlc[11] = b2_config_parms[5].info[0];
8103                                                 dlc[12] = b2_config_parms[5].info[1];
8104                                                 dlc[13] = b2_config_parms[6].info[0];
8105                                                 dlc[14] = b2_config_parms[6].info[1];
8106                                                 dlc[0] = 14;
8107                                                 dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8108                                                 dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8109                                                 dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8110                                         }
8111                                         else {
8112                                                 dlc[6] = 14;
8113                                         }
8114                                 }
8115                         }
8116                 }
8117                 else
8118                 {
8119                         if (b2_config->length)
8120                         {
8121                                 dbug(1, dprintf("B2-Config"));
8122                                 if (llc[1] == X75_V42BIS) {
8123                                         if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8124                                         {
8125                                                 return _WRONG_MESSAGE_FORMAT;
8126                                         }
8127                                 }
8128                                 else {
8129                                         if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8130                                         {
8131                                                 return _WRONG_MESSAGE_FORMAT;
8132                                         }
8133                                 }
8134                                 /* if B2 Protocol is LAPD, b2_config structure is different */
8135                                 if (llc[1] == 6)
8136                                 {
8137                                         dlc[0] = 4;
8138                                         if (b2_config->length >= 1) dlc[2] = b2_config->info[1];      /* TEI */
8139                                         else dlc[2] = 0x01;
8140                                         if ((b2_config->length >= 2) && (plci->B2_prot == 12))
8141                                         {
8142                                                 SAPI = b2_config->info[2];    /* SAPI */
8143                                         }
8144                                         dlc[1] = SAPI;
8145                                         if ((b2_config->length >= 3) && (b2_config->info[3] == 128))
8146                                         {
8147                                                 dlc[3] = 127;      /* Mode */
8148                                         }
8149                                         else
8150                                         {
8151                                                 dlc[3] = 7;        /* Mode */
8152                                         }
8153
8154                                         if (b2_config->length >= 4) dlc[4] = b2_config->info[4];      /* Window */
8155                                         else dlc[4] = 1;
8156                                         dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8157                                         if (b2_config->length > 5) return _B2_PARM_NOT_SUPPORTED;
8158                                 }
8159                                 else
8160                                 {
8161                                         dlc[0] = (byte)(b2_config_parms[4].length + 6);
8162                                         dlc[3] = b2_config->info[1];
8163                                         dlc[4] = b2_config->info[2];
8164                                         if (b2_config->info[3] != 8 && b2_config->info[3] != 128) {
8165                                                 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8166                                                 return _B2_PARM_NOT_SUPPORTED;
8167                                         }
8168
8169                                         dlc[5] = (byte)(b2_config->info[3] - 1);
8170                                         dlc[6] = b2_config->info[4];
8171                                         if (dlc[6] > dlc[5]) {
8172                                                 dbug(1, dprintf("2D-dlc= %x %x %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4], dlc[5], dlc[6]));
8173                                                 return _B2_PARM_NOT_SUPPORTED;
8174                                         }
8175
8176                                         if (llc[1] == X75_V42BIS) {
8177                                                 if (b2_config->length >= 10) {
8178                                                         dlc[7] = 6;
8179                                                         dlc[8] = 0;
8180                                                         dlc[9] = b2_config_parms[4].info[0];
8181                                                         dlc[10] = b2_config_parms[4].info[1];
8182                                                         dlc[11] = b2_config_parms[5].info[0];
8183                                                         dlc[12] = b2_config_parms[5].info[1];
8184                                                         dlc[13] = b2_config_parms[6].info[0];
8185                                                         dlc[14] = b2_config_parms[6].info[1];
8186                                                         dlc[0] = 14;
8187                                                         dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8188                                                         dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8189                                                         dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8190                                                 }
8191                                                 else {
8192                                                         dlc[6] = 14;
8193                                                 }
8194
8195                                         }
8196                                         else {
8197                                                 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8198                                                 for (i = 0; i < b2_config_parms[4].length; i++)
8199                                                         dlc[11 + i] = b2_config_parms[4].info[1 + i];
8200                                         }
8201                                 }
8202                         }
8203                 }
8204         add_p(plci, DLC, dlc);
8205
8206         b3_config = &bp_parms[5];
8207         if (b3_config->length)
8208         {
8209                 if (plci->B3_prot == 4
8210                     || plci->B3_prot == 5)
8211                 {
8212                         if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8213                         {
8214                                 return _WRONG_MESSAGE_FORMAT;
8215                         }
8216                         i = GET_WORD((byte *)(b3_config_parms[0].info));
8217                         ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8218                                                                     ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8219                         ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8220                         fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8221                         if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8222                                 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8223                         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8224                         {
8225
8226                                 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8227                                     & (1L << PRIVATE_FAX_PAPER_FORMATS))
8228                                 {
8229                                         ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8230                                                 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8231                                                 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8232                                 }
8233
8234                                 ((T30_INFO *)&nlc[1])->recording_properties =
8235                                         T30_RECORDING_WIDTH_ISO_A3 |
8236                                         (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8237                                         (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8238                         }
8239                         if (plci->B3_prot == 5)
8240                         {
8241                                 if (i & 0x0002) /* Accept incoming fax-polling requests */
8242                                         fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8243                                 if (i & 0x2000) /* Do not use MR compression */
8244                                         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8245                                 if (i & 0x4000) /* Do not use MMR compression */
8246                                         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8247                                 if (i & 0x8000) /* Do not use ECM */
8248                                         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8249                                 if (plci->fax_connect_info_length != 0)
8250                                 {
8251                                         ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8252                                         ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8253                                         ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8254                                         fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8255                                                 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8256                                 }
8257                         }
8258                         /* copy station id to NLC */
8259                         for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
8260                         {
8261                                 if (i < b3_config_parms[2].length)
8262                                 {
8263                                         ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1 + i];
8264                                 }
8265                                 else
8266                                 {
8267                                         ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8268                                 }
8269                         }
8270                         ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8271                         /* copy head line to NLC */
8272                         if (b3_config_parms[3].length)
8273                         {
8274
8275                                 pos = (byte)(fax_head_line_time(&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8276                                 if (pos != 0)
8277                                 {
8278                                         if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8279                                                 pos = 0;
8280                                         else
8281                                         {
8282                                                 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8283                                                 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8284                                                 len = (byte)b3_config_parms[2].length;
8285                                                 if (len > 20)
8286                                                         len = 20;
8287                                                 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8288                                                 {
8289                                                         for (i = 0; i < len; i++)
8290                                                                 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1 + i];
8291                                                         nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8292                                                         nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8293                                                 }
8294                                         }
8295                                 }
8296
8297                                 len = (byte)b3_config_parms[3].length;
8298                                 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8299                                         len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8300                                 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8301                                 nlc[0] += (byte)(pos + len);
8302                                 for (i = 0; i < len; i++)
8303                                         nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] =  ((byte *)b3_config_parms[3].info)[1 + i];
8304                         } else
8305                                 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8306
8307                         plci->nsf_control_bits = 0;
8308                         if (plci->B3_prot == 5)
8309                         {
8310                                 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8311                                     && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8312                                 {
8313                                         plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8314                                 }
8315                                 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8316                                     && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8317                                 {
8318                                         plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8319                                 }
8320                                 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8321                                     & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8322                                 {
8323                                         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8324                                             & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8325                                         {
8326                                                 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8327                                                 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8328                                                         fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8329                                         }
8330                                         len = nlc[0];
8331                                         pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8332                                         if (pos < plci->fax_connect_info_length)
8333                                         {
8334                                                 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8335                                                         nlc[++len] = plci->fax_connect_info_buffer[pos++];
8336                                         }
8337                                         else
8338                                                 nlc[++len] = 0;
8339                                         if (pos < plci->fax_connect_info_length)
8340                                         {
8341                                                 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8342                                                         nlc[++len] = plci->fax_connect_info_buffer[pos++];
8343                                         }
8344                                         else
8345                                                 nlc[++len] = 0;
8346                                         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8347                                             & (1L << PRIVATE_FAX_NONSTANDARD))
8348                                         {
8349                                                 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8350                                                 {
8351                                                         if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos + 1] >= 2))
8352                                                                 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos + 2]);
8353                                                         for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8354                                                                 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8355                                                 }
8356                                                 else
8357                                                 {
8358                                                         if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8359                                                         {
8360                                                                 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8361                                                                 nlc[++len] = 0;
8362                                                         }
8363                                                         else
8364                                                         {
8365                                                                 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8366                                                                         plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8367                                                                 nlc[++len] = (byte)(b3_config_parms[4].length);
8368                                                                 for (i = 0; i < b3_config_parms[4].length; i++)
8369                                                                         nlc[++len] = b3_config_parms[4].info[1 + i];
8370                                                         }
8371                                                 }
8372                                         }
8373                                         nlc[0] = len;
8374                                         if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8375                                             && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8376                                         {
8377                                                 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8378                                         }
8379                                 }
8380                         }
8381
8382                         PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8383                         len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8384                         for (i = 0; i < len; i++)
8385                                 plci->fax_connect_info_buffer[i] = nlc[1 + i];
8386                         ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8387                         i += ((T30_INFO *)&nlc[1])->head_line_len;
8388                         while (i < nlc[0])
8389                                 plci->fax_connect_info_buffer[len++] = nlc[++i];
8390                         plci->fax_connect_info_length = len;
8391                 }
8392                 else
8393                 {
8394                         nlc[0] = 14;
8395                         if (b3_config->length != 16)
8396                                 return _B3_PARM_NOT_SUPPORTED;
8397                         for (i = 0; i < 12; i++) nlc[1 + i] = b3_config->info[1 + i];
8398                         if (GET_WORD(&b3_config->info[13]) != 8 && GET_WORD(&b3_config->info[13]) != 128)
8399                                 return _B3_PARM_NOT_SUPPORTED;
8400                         nlc[13] = b3_config->info[13];
8401                         if (GET_WORD(&b3_config->info[15]) >= nlc[13])
8402                                 return _B3_PARM_NOT_SUPPORTED;
8403                         nlc[14] = b3_config->info[15];
8404                 }
8405         }
8406         else
8407         {
8408                 if (plci->B3_prot == 4
8409                     || plci->B3_prot == 5 /*T.30 - FAX*/) return _B3_PARM_NOT_SUPPORTED;
8410         }
8411         add_p(plci, NLC, nlc);
8412         return 0;
8413 }
8414
8415 /*----------------------------------------------------------------*/
8416 /*      make the same as add_b23, but only for the modem related  */
8417 /*      L2 and L3 B-Chan protocol.                                */
8418 /*                                                                */
8419 /*      Enabled L2 and L3 Configurations:                         */
8420 /*        If L1 == Modem all negotiation                          */
8421 /*          only L2 == Modem with full negotiation is allowed     */
8422 /*        If L1 == Modem async or sync                            */
8423 /*          only L2 == Transparent is allowed                     */
8424 /*        L3 == Modem or L3 == Transparent are allowed            */
8425 /*      B2 Configuration for modem:                               */
8426 /*          word : enable/disable compression, bitoptions         */
8427 /*      B3 Configuration for modem:                               */
8428 /*          empty                                                 */
8429 /*----------------------------------------------------------------*/
8430 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms)
8431 {
8432         static byte lli[12] = {1,1};
8433         static byte llc[3] = {2,0,0};
8434         static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8435         API_PARSE mdm_config[2];
8436         word i;
8437         word b2_config = 0;
8438
8439         for (i = 0; i < 2; i++) mdm_config[i].length = 0;
8440         for (i = 0; i < sizeof(dlc); i++) dlc[i] = 0;
8441
8442         if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8443              && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8444             || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8445                 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8446         {
8447                 return (_B_STACK_NOT_SUPPORTED);
8448         }
8449         if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8450             && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8451         {
8452                 return (_B_STACK_NOT_SUPPORTED);
8453         }
8454
8455         plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8456         plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8457
8458         if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8459         {
8460                 if (api_parse(&bp_parms[4].info[1],
8461                               (word)bp_parms[4].length, "w",
8462                               mdm_config))
8463                 {
8464                         return (_WRONG_MESSAGE_FORMAT);
8465                 }
8466                 b2_config = GET_WORD(mdm_config[0].info);
8467         }
8468
8469         /* OK, L2 is modem */
8470
8471         lli[0] = 1;
8472         lli[1] = 1;
8473         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8474                 lli[1] |= 2;
8475         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8476                 lli[1] |= 4;
8477
8478         if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8479                 lli[1] |= 0x10;
8480                 if (plci->rx_dma_descriptor <= 0) {
8481                         plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
8482                         if (plci->rx_dma_descriptor >= 0)
8483                                 plci->rx_dma_descriptor++;
8484                 }
8485                 if (plci->rx_dma_descriptor > 0) {
8486                         lli[1] |= 0x40;
8487                         lli[0] = 6;
8488                         lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8489                         lli[3] = (byte)plci->rx_dma_magic;
8490                         lli[4] = (byte)(plci->rx_dma_magic >>  8);
8491                         lli[5] = (byte)(plci->rx_dma_magic >> 16);
8492                         lli[6] = (byte)(plci->rx_dma_magic >> 24);
8493                 }
8494         }
8495
8496         if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8497                 lli[1] |= 0x20;
8498         }
8499
8500         llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8501                 /*V42*/ 10 : /*V42_IN*/ 9;
8502         llc[2] = 4;                      /* pass L3 always transparent */
8503         add_p(plci, LLI, lli);
8504         add_p(plci, LLC, llc);
8505         i =  1;
8506         PUT_WORD(&dlc[i], plci->appl->MaxDataLength);
8507         i += 2;
8508         if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8509         {
8510                 if (bp_parms[4].length)
8511                 {
8512                         dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8513                         dlc[i++] = 3; /* Addr A */
8514                         dlc[i++] = 1; /* Addr B */
8515                         dlc[i++] = 7; /* modulo mode */
8516                         dlc[i++] = 7; /* window size */
8517                         dlc[i++] = 0; /* XID len Lo  */
8518                         dlc[i++] = 0; /* XID len Hi  */
8519
8520                         if (b2_config & MDM_B2_DISABLE_V42bis)
8521                         {
8522                                 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8523                         }
8524                         if (b2_config & MDM_B2_DISABLE_MNP)
8525                         {
8526                                 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8527                         }
8528                         if (b2_config & MDM_B2_DISABLE_TRANS)
8529                         {
8530                                 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8531                         }
8532                         if (b2_config & MDM_B2_DISABLE_V42)
8533                         {
8534                                 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8535                         }
8536                         if (b2_config & MDM_B2_DISABLE_COMP)
8537                         {
8538                                 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8539                         }
8540                         i++;
8541                 }
8542         }
8543         else
8544         {
8545                 dlc[i++] = 3; /* Addr A */
8546                 dlc[i++] = 1; /* Addr B */
8547                 dlc[i++] = 7; /* modulo mode */
8548                 dlc[i++] = 7; /* window size */
8549                 dlc[i++] = 0; /* XID len Lo  */
8550                 dlc[i++] = 0; /* XID len Hi  */
8551                 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8552                         DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8553                         DLC_MODEMPROT_DISABLE_V42_DETECT |
8554                         DLC_MODEMPROT_DISABLE_COMPRESSION;
8555         }
8556         dlc[0] = (byte)(i - 1);
8557 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8558         add_p(plci, DLC, dlc);
8559         return (0);
8560 }
8561
8562
8563 /*------------------------------------------------------------------*/
8564 /* send a request for the signaling entity                          */
8565 /*------------------------------------------------------------------*/
8566
8567 static void sig_req(PLCI *plci, byte req, byte Id)
8568 {
8569         if (!plci) return;
8570         if (plci->adapter->adapter_disabled) return;
8571         dbug(1, dprintf("sig_req(%x)", req));
8572         if (req == REMOVE)
8573                 plci->sig_remove_id = plci->Sig.Id;
8574         if (plci->req_in == plci->req_in_start) {
8575                 plci->req_in += 2;
8576                 plci->RBuffer[plci->req_in++] = 0;
8577         }
8578         PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8579         plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
8580         plci->RBuffer[plci->req_in++] = req;  /* request */
8581         plci->RBuffer[plci->req_in++] = 0;    /* channel */
8582         plci->req_in_start = plci->req_in;
8583 }
8584
8585 /*------------------------------------------------------------------*/
8586 /* send a request for the network layer entity                      */
8587 /*------------------------------------------------------------------*/
8588
8589 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8590 {
8591         if (!plci) return;
8592         if (plci->adapter->adapter_disabled) return;
8593         dbug(1, dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8594         if (req == REMOVE)
8595         {
8596                 plci->nl_remove_id = plci->NL.Id;
8597                 ncci_remove(plci, 0, (byte)(ncci != 0));
8598                 ncci = 0;
8599         }
8600         if (plci->req_in == plci->req_in_start) {
8601                 plci->req_in += 2;
8602                 plci->RBuffer[plci->req_in++] = 0;
8603         }
8604         PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8605         plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */
8606         plci->RBuffer[plci->req_in++] = req;  /* request */
8607         plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
8608         plci->req_in_start = plci->req_in;
8609 }
8610
8611 static void send_req(PLCI *plci)
8612 {
8613         ENTITY *e;
8614         word l;
8615 /*  word i; */
8616
8617         if (!plci) return;
8618         if (plci->adapter->adapter_disabled) return;
8619         channel_xmit_xon(plci);
8620
8621         /* if nothing to do, return */
8622         if (plci->req_in == plci->req_out) return;
8623         dbug(1, dprintf("send_req(in=%d,out=%d)", plci->req_in, plci->req_out));
8624
8625         if (plci->nl_req || plci->sig_req) return;
8626
8627         l = GET_WORD(&plci->RBuffer[plci->req_out]);
8628         plci->req_out += 2;
8629         plci->XData[0].P = &plci->RBuffer[plci->req_out];
8630         plci->req_out += l;
8631         if (plci->RBuffer[plci->req_out] == 1)
8632         {
8633                 e = &plci->NL;
8634                 plci->req_out++;
8635                 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8636                 e->ReqCh = plci->RBuffer[plci->req_out++];
8637                 if (!(e->Id & 0x1f))
8638                 {
8639                         e->Id = NL_ID;
8640                         plci->RBuffer[plci->req_out - 4] = CAI;
8641                         plci->RBuffer[plci->req_out - 3] = 1;
8642                         plci->RBuffer[plci->req_out - 2] = (plci->Sig.Id == 0xff) ? 0 : plci->Sig.Id;
8643                         plci->RBuffer[plci->req_out - 1] = 0;
8644                         l += 3;
8645                         plci->nl_global_req = plci->nl_req;
8646                 }
8647                 dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8648         }
8649         else
8650         {
8651                 e = &plci->Sig;
8652                 if (plci->RBuffer[plci->req_out])
8653                         e->Id = plci->RBuffer[plci->req_out];
8654                 plci->req_out++;
8655                 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8656                 e->ReqCh = plci->RBuffer[plci->req_out++];
8657                 if (!(e->Id & 0x1f))
8658                         plci->sig_global_req = plci->sig_req;
8659                 dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8660         }
8661         plci->XData[0].PLength = l;
8662         e->X = plci->XData;
8663         plci->adapter->request(e);
8664         dbug(1, dprintf("send_ok"));
8665 }
8666
8667 static void send_data(PLCI *plci)
8668 {
8669         DIVA_CAPI_ADAPTER *a;
8670         DATA_B3_DESC *data;
8671         NCCI   *ncci_ptr;
8672         word ncci;
8673
8674         if (!plci->nl_req && plci->ncci_ring_list)
8675         {
8676                 a = plci->adapter;
8677                 ncci = plci->ncci_ring_list;
8678                 do
8679                 {
8680                         ncci = a->ncci_next[ncci];
8681                         ncci_ptr = &(a->ncci[ncci]);
8682                         if (!(a->ncci_ch[ncci]
8683                               && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8684                         {
8685                                 if (ncci_ptr->data_pending)
8686                                 {
8687                                         if ((a->ncci_state[ncci] == CONNECTED)
8688                                             || (a->ncci_state[ncci] == INC_ACT_PENDING)
8689                                             || (plci->send_disc == ncci))
8690                                         {
8691                                                 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8692                                                 if ((plci->B2_prot == B2_V120_ASYNC)
8693                                                     || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8694                                                     || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8695                                                 {
8696                                                         plci->NData[1].P = TransmitBufferGet(plci->appl, data->P);
8697                                                         plci->NData[1].PLength = data->Length;
8698                                                         if (data->Flags & 0x10)
8699                                                                 plci->NData[0].P = v120_break_header;
8700                                                         else
8701                                                                 plci->NData[0].P = v120_default_header;
8702                                                         plci->NData[0].PLength = 1;
8703                                                         plci->NL.XNum = 2;
8704                                                         plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8705                                                 }
8706                                                 else
8707                                                 {
8708                                                         plci->NData[0].P = TransmitBufferGet(plci->appl, data->P);
8709                                                         plci->NData[0].PLength = data->Length;
8710                                                         if (data->Flags & 0x10)
8711                                                                 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8712
8713                                                         else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8714                                                                 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8715
8716                                                         else
8717                                                                 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8718                                                 }
8719                                                 plci->NL.X = plci->NData;
8720                                                 plci->NL.ReqCh = a->ncci_ch[ncci];
8721                                                 dbug(1, dprintf("%x:DREQ(%x:%x)", a->Id, plci->NL.Id, plci->NL.Req));
8722                                                 plci->data_sent = true;
8723                                                 plci->data_sent_ptr = data->P;
8724                                                 a->request(&plci->NL);
8725                                         }
8726                                         else {
8727                                                 cleanup_ncci_data(plci, ncci);
8728                                         }
8729                                 }
8730                                 else if (plci->send_disc == ncci)
8731                                 {
8732                                         /* dprintf("N_DISC"); */
8733                                         plci->NData[0].PLength = 0;
8734                                         plci->NL.ReqCh = a->ncci_ch[ncci];
8735                                         plci->NL.Req = plci->nl_req = N_DISC;
8736                                         a->request(&plci->NL);
8737                                         plci->command = _DISCONNECT_B3_R;
8738                                         plci->send_disc = 0;
8739                                 }
8740                         }
8741                 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8742                 plci->ncci_ring_list = ncci;
8743         }
8744 }
8745
8746 static void listen_check(DIVA_CAPI_ADAPTER *a)
8747 {
8748         word i, j;
8749         PLCI *plci;
8750         byte activnotifiedcalls = 0;
8751
8752         dbug(1, dprintf("listen_check(%d,%d)", a->listen_active, a->max_listen));
8753         if (!remove_started && !a->adapter_disabled)
8754         {
8755                 for (i = 0; i < a->max_plci; i++)
8756                 {
8757                         plci = &(a->plci[i]);
8758                         if (plci->notifiedcall) activnotifiedcalls++;
8759                 }
8760                 dbug(1, dprintf("listen_check(%d)", activnotifiedcalls));
8761
8762                 for (i = a->listen_active; i < ((word)(a->max_listen + activnotifiedcalls)); i++) {
8763                         if ((j = get_plci(a))) {
8764                                 a->listen_active++;
8765                                 plci = &a->plci[j - 1];
8766                                 plci->State = LISTENING;
8767
8768                                 add_p(plci, OAD, "\x01\xfd");
8769
8770                                 add_p(plci, KEY, "\x04\x43\x41\x32\x30");
8771
8772                                 add_p(plci, CAI, "\x01\xc0");
8773                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
8774                                 add_p(plci, LLI, "\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */
8775                                 add_p(plci, SHIFT | 6, NULL);
8776                                 add_p(plci, SIN, "\x02\x00\x00");
8777                                 plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
8778                                 sig_req(plci, ASSIGN, DSIG_ID);
8779                                 send_req(plci);
8780                         }
8781                 }
8782         }
8783 }
8784
8785 /*------------------------------------------------------------------*/
8786 /* functions for all parameters sent in INDs                        */
8787 /*------------------------------------------------------------------*/
8788
8789 static void IndParse(PLCI *plci, const word *parms_id, byte **parms, byte multiIEsize)
8790 {
8791         word ploc;            /* points to current location within packet */
8792         byte w;
8793         byte wlen;
8794         byte codeset, lock;
8795         byte *in;
8796         word i;
8797         word code;
8798         word mIEindex = 0;
8799         ploc = 0;
8800         codeset = 0;
8801         lock = 0;
8802
8803         in = plci->Sig.RBuffer->P;
8804         for (i = 0; i < parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
8805         {                            /* element but parms array is larger      */
8806                 parms[i] = (byte *)"";
8807         }
8808         for (i = 0; i < multiIEsize; i++)
8809         {
8810                 parms[i] = (byte *)"";
8811         }
8812
8813         while (ploc < plci->Sig.RBuffer->length - 1) {
8814
8815                 /* read information element id and length                   */
8816                 w = in[ploc];
8817
8818                 if (w & 0x80) {
8819 /*    w &=0xf0; removed, cannot detect congestion levels */
8820 /*    upper 4 bit masked with w==SHIFT now               */
8821                         wlen = 0;
8822                 }
8823                 else {
8824                         wlen = (byte)(in[ploc + 1] + 1);
8825                 }
8826                 /* check if length valid (not exceeding end of packet)      */
8827                 if ((ploc + wlen) > 270) return;
8828                 if (lock & 0x80) lock &= 0x7f;
8829                 else codeset = lock;
8830
8831                 if ((w & 0xf0) == SHIFT) {
8832                         codeset = in[ploc];
8833                         if (!(codeset & 0x08)) lock = (byte)(codeset & 7);
8834                         codeset &= 7;
8835                         lock |= 0x80;
8836                 }
8837                 else {
8838                         if (w == ESC && wlen >= 3) code = in[ploc + 2] | 0x800;
8839                         else code = w;
8840                         code |= (codeset << 8);
8841
8842                         for (i = 1; i < parms_id[0] + 1 && parms_id[i] != code; i++);
8843
8844                         if (i < parms_id[0] + 1) {
8845                                 if (!multiIEsize) { /* with multiIEs use next field index,          */
8846                                         mIEindex = i - 1;    /* with normal IEs use same index like parms_id */
8847                                 }
8848
8849                                 parms[mIEindex] = &in[ploc + 1];
8850                                 dbug(1, dprintf("mIE[%d]=0x%x", *parms[mIEindex], in[ploc]));
8851                                 if (parms_id[i] == OAD
8852                                     || parms_id[i] == CONN_NR
8853                                     || parms_id[i] == CAD) {
8854                                         if (in[ploc + 2] & 0x80) {
8855                                                 in[ploc + 0] = (byte)(in[ploc + 1] + 1);
8856                                                 in[ploc + 1] = (byte)(in[ploc + 2] & 0x7f);
8857                                                 in[ploc + 2] = 0x80;
8858                                                 parms[mIEindex] = &in[ploc];
8859                                         }
8860                                 }
8861                                 mIEindex++;       /* effects multiIEs only */
8862                         }
8863                 }
8864
8865                 ploc += (wlen + 1);
8866         }
8867         return;
8868 }
8869
8870 /*------------------------------------------------------------------*/
8871 /* try to match a cip from received BC and HLC                      */
8872 /*------------------------------------------------------------------*/
8873
8874 static byte ie_compare(byte *ie1, byte *ie2)
8875 {
8876         word i;
8877         if (!ie1 || !ie2) return false;
8878         if (!ie1[0]) return false;
8879         for (i = 0; i < (word)(ie1[0] + 1); i++) if (ie1[i] != ie2[i]) return false;
8880         return true;
8881 }
8882
8883 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
8884 {
8885         word i;
8886         word j;
8887
8888         for (i = 9; i && !ie_compare(bc, cip_bc[i][a->u_law]); i--);
8889
8890         for (j = 16; j < 29 &&
8891                      (!ie_compare(bc, cip_bc[j][a->u_law]) || !ie_compare(hlc, cip_hlc[j])); j++);
8892         if (j == 29) return i;
8893         return j;
8894 }
8895
8896
8897 static byte AddInfo(byte **add_i,
8898                     byte **fty_i,
8899                     byte *esc_chi,
8900                     byte *facility)
8901 {
8902         byte i;
8903         byte j;
8904         byte k;
8905         byte flen;
8906         byte len = 0;
8907         /* facility is a nested structure */
8908         /* FTY can be more than once      */
8909
8910         if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
8911         {
8912                 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
8913         }
8914
8915         else
8916         {
8917                 add_i[0] = (byte *)"";
8918         }
8919         if (!fty_i[0][0])
8920         {
8921                 add_i[3] = (byte *)"";
8922         }
8923         else
8924         {    /* facility array found  */
8925                 for (i = 0, j = 1; i < MAX_MULTI_IE && fty_i[i][0]; i++)
8926                 {
8927                         dbug(1, dprintf("AddIFac[%d]", fty_i[i][0]));
8928                         len += fty_i[i][0];
8929                         len += 2;
8930                         flen = fty_i[i][0];
8931                         facility[j++] = 0x1c; /* copy fac IE */
8932                         for (k = 0; k <= flen; k++, j++)
8933                         {
8934                                 facility[j] = fty_i[i][k];
8935 /*      dbug(1, dprintf("%x ",facility[j])); */
8936                         }
8937                 }
8938                 facility[0] = len;
8939                 add_i[3] = facility;
8940         }
8941 /*  dbug(1, dprintf("FacArrLen=%d ",len)); */
8942         len = add_i[0][0] + add_i[1][0] + add_i[2][0] + add_i[3][0];
8943         len += 4;                          /* calculate length of all */
8944         return (len);
8945 }
8946
8947 /*------------------------------------------------------------------*/
8948 /* voice and codec features                                         */
8949 /*------------------------------------------------------------------*/
8950
8951 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
8952 {
8953         byte voice_chi[] = "\x02\x18\x01";
8954         byte channel;
8955
8956         channel = chi[chi[0]] & 0x3;
8957         dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel));
8958         voice_chi[2] = (channel) ? channel : 1;
8959         add_p(plci, FTY, "\x02\x01\x07");             /* B On, default on 1 */
8960         add_p(plci, ESC, voice_chi);                  /* Channel */
8961         sig_req(plci, TEL_CTRL, 0);
8962         send_req(plci);
8963         if (a->AdvSignalPLCI)
8964         {
8965                 adv_voice_write_coefs(a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
8966         }
8967 }
8968
8969 static void VoiceChannelOff(PLCI *plci)
8970 {
8971         dbug(1, dprintf("ExtDevOFF"));
8972         add_p(plci, FTY, "\x02\x01\x08");             /* B Off */
8973         sig_req(plci, TEL_CTRL, 0);
8974         send_req(plci);
8975         if (plci->adapter->AdvSignalPLCI)
8976         {
8977                 adv_voice_clear_config(plci->adapter->AdvSignalPLCI);
8978         }
8979 }
8980
8981
8982 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
8983                             byte hook_listen)
8984 {
8985         word j;
8986         PLCI *splci;
8987
8988         /* check if hardware supports handset with hook states (adv.codec) */
8989         /* or if just a on board codec is supported                        */
8990         /* the advanced codec plci is just for internal use                */
8991
8992         /* diva Pro with on-board codec:                                   */
8993         if (a->profile.Global_Options & HANDSET)
8994         {
8995                 /* new call, but hook states are already signalled */
8996                 if (a->AdvCodecFLAG)
8997                 {
8998                         if (a->AdvSignalAppl != appl || a->AdvSignalPLCI)
8999                         {
9000                                 dbug(1, dprintf("AdvSigPlci=0x%x", a->AdvSignalPLCI));
9001                                 return 0x2001; /* codec in use by another application */
9002                         }
9003                         if (plci != NULL)
9004                         {
9005                                 a->AdvSignalPLCI = plci;
9006                                 plci->tel = ADV_VOICE;
9007                         }
9008                         return 0;                      /* adv codec still used */
9009                 }
9010                 if ((j = get_plci(a)))
9011                 {
9012                         splci = &a->plci[j - 1];
9013                         splci->tel = CODEC_PERMANENT;
9014                         /* hook_listen indicates if a facility_req with handset/hook support */
9015                         /* was sent. Otherwise if just a call on an external device was made */
9016                         /* the codec will be used but the hook info will be discarded (just  */
9017                         /* the external controller is in use                                 */
9018                         if (hook_listen) splci->State = ADVANCED_VOICE_SIG;
9019                         else
9020                         {
9021                                 splci->State = ADVANCED_VOICE_NOSIG;
9022                                 if (plci)
9023                                 {
9024                                         plci->spoofed_msg = SPOOFING_REQUIRED;
9025                                 }
9026                                 /* indicate D-ch connect if  */
9027                         }                                        /* codec is connected OK     */
9028                         if (plci != NULL)
9029                         {
9030                                 a->AdvSignalPLCI = plci;
9031                                 plci->tel = ADV_VOICE;
9032                         }
9033                         a->AdvSignalAppl = appl;
9034                         a->AdvCodecFLAG = true;
9035                         a->AdvCodecPLCI = splci;
9036                         add_p(splci, CAI, "\x01\x15");
9037                         add_p(splci, LLI, "\x01\x00");
9038                         add_p(splci, ESC, "\x02\x18\x00");
9039                         add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9040                         splci->internal_command = PERM_COD_ASSIGN;
9041                         dbug(1, dprintf("Codec Assign"));
9042                         sig_req(splci, ASSIGN, DSIG_ID);
9043                         send_req(splci);
9044                 }
9045                 else
9046                 {
9047                         return 0x2001; /* wrong state, no more plcis */
9048                 }
9049         }
9050         else if (a->profile.Global_Options & ON_BOARD_CODEC)
9051         {
9052                 if (hook_listen) return 0x300B;               /* Facility not supported */
9053                 /* no hook with SCOM      */
9054                 if (plci != NULL) plci->tel = CODEC;
9055                 dbug(1, dprintf("S/SCOM codec"));
9056                 /* first time we use the scom-s codec we must shut down the internal   */
9057                 /* handset application of the card. This can be done by an assign with */
9058                 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9059                 if (!a->scom_appl_disable) {
9060                         if ((j = get_plci(a))) {
9061                                 splci = &a->plci[j - 1];
9062                                 add_p(splci, CAI, "\x01\x80");
9063                                 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9064                                 sig_req(splci, ASSIGN, 0xC0);  /* 0xc0 is the TEL_ID */
9065                                 send_req(splci);
9066                                 a->scom_appl_disable = true;
9067                         }
9068                         else{
9069                                 return 0x2001; /* wrong state, no more plcis */
9070                         }
9071                 }
9072         }
9073         else return 0x300B;               /* Facility not supported */
9074
9075         return 0;
9076 }
9077
9078
9079 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9080 {
9081
9082         dbug(1, dprintf("CodecIdCheck"));
9083
9084         if (a->AdvSignalPLCI == plci)
9085         {
9086                 dbug(1, dprintf("PLCI owns codec"));
9087                 VoiceChannelOff(a->AdvCodecPLCI);
9088                 if (a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9089                 {
9090                         dbug(1, dprintf("remove temp codec PLCI"));
9091                         plci_remove(a->AdvCodecPLCI);
9092                         a->AdvCodecFLAG  = 0;
9093                         a->AdvCodecPLCI  = NULL;
9094                         a->AdvSignalAppl = NULL;
9095                 }
9096                 a->AdvSignalPLCI = NULL;
9097         }
9098 }
9099
9100 /* -------------------------------------------------------------------
9101    Ask for physical address of card on PCI bus
9102    ------------------------------------------------------------------- */
9103 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *a,
9104                                        IDI_SYNC_REQ *preq) {
9105         a->sdram_bar = 0;
9106         if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9107                 ENTITY *e = (ENTITY *)preq;
9108
9109                 e->user[0] = a->Id - 1;
9110                 preq->xdi_sdram_bar.info.bar    = 0;
9111                 preq->xdi_sdram_bar.Req         = 0;
9112                 preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9113
9114                 (*(a->request))(e);
9115
9116                 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9117                 dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9118         }
9119 }
9120
9121 /* -------------------------------------------------------------------
9122    Ask XDI about extended features
9123    ------------------------------------------------------------------- */
9124 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a) {
9125         IDI_SYNC_REQ *preq;
9126         char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
9127
9128         char features[4];
9129         preq = (IDI_SYNC_REQ *)&buffer[0];
9130
9131         if (!diva_xdi_extended_features) {
9132                 ENTITY *e = (ENTITY *)preq;
9133                 diva_xdi_extended_features |= 0x80000000;
9134
9135                 e->user[0] = a->Id - 1;
9136                 preq->xdi_extended_features.Req = 0;
9137                 preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9138                 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9139                 preq->xdi_extended_features.info.features = &features[0];
9140
9141                 (*(a->request))(e);
9142
9143                 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9144                         /*
9145                           Check features located in the byte '0'
9146                         */
9147                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9148                                 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9149                         }
9150                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9151                                 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9152                                 dbug(1, dprintf("XDI provides RxDMA"));
9153                         }
9154                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9155                                 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9156                         }
9157                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9158                                 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9159                                 dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9160                         }
9161
9162                 }
9163         }
9164
9165         diva_ask_for_xdi_sdram_bar(a, preq);
9166 }
9167
9168 /*------------------------------------------------------------------*/
9169 /* automatic law                                                    */
9170 /*------------------------------------------------------------------*/
9171 /* called from OS specific part after init time to get the Law              */
9172 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9173 void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9174 {
9175         word j;
9176         PLCI *splci;
9177
9178         if (a->automatic_law) {
9179                 return;
9180         }
9181         if ((j = get_plci(a))) {
9182                 diva_get_extended_adapter_features(a);
9183                 splci = &a->plci[j - 1];
9184                 a->automatic_lawPLCI = splci;
9185                 a->automatic_law = 1;
9186                 add_p(splci, CAI, "\x01\x80");
9187                 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9188                 splci->internal_command = USELAW_REQ;
9189                 splci->command = 0;
9190                 splci->number = 0;
9191                 sig_req(splci, ASSIGN, DSIG_ID);
9192                 send_req(splci);
9193         }
9194 }
9195
9196 /* called from OS specific part if an application sends an Capi20Release */
9197 word CapiRelease(word Id)
9198 {
9199         word i, j, appls_found;
9200         PLCI *plci;
9201         APPL   *this;
9202         DIVA_CAPI_ADAPTER *a;
9203
9204         if (!Id)
9205         {
9206                 dbug(0, dprintf("A: CapiRelease(Id==0)"));
9207                 return (_WRONG_APPL_ID);
9208         }
9209
9210         this = &application[Id - 1];               /* get application pointer */
9211
9212         for (i = 0, appls_found = 0; i < max_appl; i++)
9213         {
9214                 if (application[i].Id)       /* an application has been found        */
9215                 {
9216                         appls_found++;
9217                 }
9218         }
9219
9220         for (i = 0; i < max_adapter; i++)             /* scan all adapters...    */
9221         {
9222                 a = &adapter[i];
9223                 if (a->request)
9224                 {
9225                         a->Info_Mask[Id - 1] = 0;
9226                         a->CIP_Mask[Id - 1] = 0;
9227                         a->Notification_Mask[Id - 1] = 0;
9228                         a->codec_listen[Id - 1] = NULL;
9229                         a->requested_options_table[Id - 1] = 0;
9230                         for (j = 0; j < a->max_plci; j++)           /* and all PLCIs connected */
9231                         {                                      /* with this application   */
9232                                 plci = &a->plci[j];
9233                                 if (plci->Id)                         /* if plci owns no application */
9234                                 {                                    /* it may be not jet connected */
9235                                         if (plci->State == INC_CON_PENDING
9236                                             || plci->State == INC_CON_ALERT)
9237                                         {
9238                                                 if (test_bit(Id - 1, plci->c_ind_mask_table))
9239                                                 {
9240                                                         __clear_bit(Id - 1, plci->c_ind_mask_table);
9241                                                         if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9242                                                         {
9243                                                                 sig_req(plci, HANGUP, 0);
9244                                                                 send_req(plci);
9245                                                                 plci->State = OUTG_DIS_PENDING;
9246                                                         }
9247                                                 }
9248                                         }
9249                                         if (test_bit(Id - 1, plci->c_ind_mask_table))
9250                                         {
9251                                                 __clear_bit(Id - 1, plci->c_ind_mask_table);
9252                                                 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9253                                                 {
9254                                                         if (!plci->appl)
9255                                                         {
9256                                                                 plci_remove(plci);
9257                                                                 plci->State = IDLE;
9258                                                         }
9259                                                 }
9260                                         }
9261                                         if (plci->appl == this)
9262                                         {
9263                                                 plci->appl = NULL;
9264                                                 plci_remove(plci);
9265                                                 plci->State = IDLE;
9266                                         }
9267                                 }
9268                         }
9269                         listen_check(a);
9270
9271                         if (a->flag_dynamic_l1_down)
9272                         {
9273                                 if (appls_found == 1)            /* last application does a capi release */
9274                                 {
9275                                         if ((j = get_plci(a)))
9276                                         {
9277                                                 plci = &a->plci[j - 1];
9278                                                 plci->command = 0;
9279                                                 add_p(plci, OAD, "\x01\xfd");
9280                                                 add_p(plci, CAI, "\x01\x80");
9281                                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9282                                                 add_p(plci, SHIFT | 6, NULL);
9283                                                 add_p(plci, SIN, "\x02\x00\x00");
9284                                                 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9285                                                 sig_req(plci, ASSIGN, DSIG_ID);
9286                                                 add_p(plci, FTY, "\x02\xff\x06"); /* l1 down */
9287                                                 sig_req(plci, SIG_CTRL, 0);
9288                                                 send_req(plci);
9289                                         }
9290                                 }
9291                         }
9292                         if (a->AdvSignalAppl == this)
9293                         {
9294                                 this->NullCREnable = false;
9295                                 if (a->AdvCodecPLCI)
9296                                 {
9297                                         plci_remove(a->AdvCodecPLCI);
9298                                         a->AdvCodecPLCI->tel = 0;
9299                                         a->AdvCodecPLCI->adv_nl = 0;
9300                                 }
9301                                 a->AdvSignalAppl = NULL;
9302                                 a->AdvSignalPLCI = NULL;
9303                                 a->AdvCodecFLAG = 0;
9304                                 a->AdvCodecPLCI = NULL;
9305                         }
9306                 }
9307         }
9308
9309         this->Id = 0;
9310
9311         return GOOD;
9312 }
9313
9314 static word plci_remove_check(PLCI *plci)
9315 {
9316         if (!plci) return true;
9317         if (!plci->NL.Id && bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9318         {
9319                 if (plci->Sig.Id == 0xff)
9320                         plci->Sig.Id = 0;
9321                 if (!plci->Sig.Id)
9322                 {
9323                         dbug(1, dprintf("plci_remove_complete(%x)", plci->Id));
9324                         dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci->tel, plci->Sig.Id));
9325                         if (plci->Id)
9326                         {
9327                                 CodecIdCheck(plci->adapter, plci);
9328                                 clear_b1_config(plci);
9329                                 ncci_remove(plci, 0, false);
9330                                 plci_free_msg_in_queue(plci);
9331                                 channel_flow_control_remove(plci);
9332                                 plci->Id = 0;
9333                                 plci->State = IDLE;
9334                                 plci->channels = 0;
9335                                 plci->appl = NULL;
9336                                 plci->notifiedcall = 0;
9337                         }
9338                         listen_check(plci->adapter);
9339                         return true;
9340                 }
9341         }
9342         return false;
9343 }
9344
9345
9346 /*------------------------------------------------------------------*/
9347
9348 static byte plci_nl_busy(PLCI *plci)
9349 {
9350         /* only applicable for non-multiplexed protocols */
9351         return (plci->nl_req
9352                 || (plci->ncci_ring_list
9353                     && plci->adapter->ncci_ch[plci->ncci_ring_list]
9354                     && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9355 }
9356
9357
9358 /*------------------------------------------------------------------*/
9359 /* DTMF facilities                                                  */
9360 /*------------------------------------------------------------------*/
9361
9362
9363 static struct
9364 {
9365         byte send_mask;
9366         byte listen_mask;
9367         byte character;
9368         byte code;
9369 } dtmf_digit_map[] =
9370 {
9371         { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9372         { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9373         { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9374         { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9375         { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9376         { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9377         { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9378         { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9379         { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9380         { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9381         { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9382         { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9383         { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9384         { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9385         { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9386         { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9387         { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9388         { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9389         { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9390         { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9391
9392         { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9393         { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9394         { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9395         { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9396         { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9397         { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9398         { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9399         { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9400         { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9401         { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9402         { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9403         { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9404         { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9405         { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9406         { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9407         { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9408         { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9409         { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9410         { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9411         { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9412         { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9413         { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9414         { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9415         { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9416         { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9417         { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9418         { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9419         { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9420         { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9421         { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9422         { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9423         { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9424         { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9425         { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9426         { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9427         { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9428         { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9429         { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9430         { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9431         { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9432         { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9433         { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9434         { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9435         { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9436         { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9437         { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9438         { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9439         { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9440         { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9441         { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9442         { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9443         { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9444
9445 };
9446
9447 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9448
9449
9450 static void dtmf_enable_receiver(PLCI *plci, byte enable_mask)
9451 {
9452         word min_digit_duration, min_gap_duration;
9453
9454         dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9455                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9456                         (char *)(FILE_), __LINE__, enable_mask));
9457
9458         if (enable_mask != 0)
9459         {
9460                 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9461                 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9462                 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9463                 PUT_WORD(&plci->internal_req_buffer[1], min_digit_duration);
9464                 PUT_WORD(&plci->internal_req_buffer[3], min_gap_duration);
9465                 plci->NData[0].PLength = 5;
9466
9467                 PUT_WORD(&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9468                 plci->NData[0].PLength += 2;
9469                 capidtmf_recv_enable(&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9470
9471         }
9472         else
9473         {
9474                 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9475                 plci->NData[0].PLength = 1;
9476
9477                 capidtmf_recv_disable(&(plci->capidtmf_state));
9478
9479         }
9480         plci->NData[0].P = plci->internal_req_buffer;
9481         plci->NL.X = plci->NData;
9482         plci->NL.ReqCh = 0;
9483         plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9484         plci->adapter->request(&plci->NL);
9485 }
9486
9487
9488 static void dtmf_send_digits(PLCI *plci, byte *digit_buffer, word digit_count)
9489 {
9490         word w, i;
9491
9492         dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9493                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9494                         (char *)(FILE_), __LINE__, digit_count));
9495
9496         plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9497         w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9498         PUT_WORD(&plci->internal_req_buffer[1], w);
9499         w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9500         PUT_WORD(&plci->internal_req_buffer[3], w);
9501         for (i = 0; i < digit_count; i++)
9502         {
9503                 w = 0;
9504                 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9505                        && (digit_buffer[i] != dtmf_digit_map[w].character))
9506                 {
9507                         w++;
9508                 }
9509                 plci->internal_req_buffer[5 + i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9510                         dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9511         }
9512         plci->NData[0].PLength = 5 + digit_count;
9513         plci->NData[0].P = plci->internal_req_buffer;
9514         plci->NL.X = plci->NData;
9515         plci->NL.ReqCh = 0;
9516         plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9517         plci->adapter->request(&plci->NL);
9518 }
9519
9520
9521 static void dtmf_rec_clear_config(PLCI *plci)
9522 {
9523
9524         dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9525                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9526                         (char *)(FILE_), __LINE__));
9527
9528         plci->dtmf_rec_active = 0;
9529         plci->dtmf_rec_pulse_ms = 0;
9530         plci->dtmf_rec_pause_ms = 0;
9531
9532         capidtmf_init(&(plci->capidtmf_state), plci->adapter->u_law);
9533
9534 }
9535
9536
9537 static void dtmf_send_clear_config(PLCI *plci)
9538 {
9539
9540         dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9541                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9542                         (char *)(FILE_), __LINE__));
9543
9544         plci->dtmf_send_requests = 0;
9545         plci->dtmf_send_pulse_ms = 0;
9546         plci->dtmf_send_pause_ms = 0;
9547 }
9548
9549
9550 static void dtmf_prepare_switch(dword Id, PLCI *plci)
9551 {
9552
9553         dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9554                         UnMapId(Id), (char *)(FILE_), __LINE__));
9555
9556         while (plci->dtmf_send_requests != 0)
9557                 dtmf_confirmation(Id, plci);
9558 }
9559
9560
9561 static word dtmf_save_config(dword Id, PLCI *plci, byte Rc)
9562 {
9563
9564         dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9565                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9566
9567         return (GOOD);
9568 }
9569
9570
9571 static word dtmf_restore_config(dword Id, PLCI *plci, byte Rc)
9572 {
9573         word Info;
9574
9575         dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9576                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9577
9578         Info = GOOD;
9579         if (plci->B1_facilities & B1_FACILITY_DTMFR)
9580         {
9581                 switch (plci->adjust_b_state)
9582                 {
9583                 case ADJUST_B_RESTORE_DTMF_1:
9584                         plci->internal_command = plci->adjust_b_command;
9585                         if (plci_nl_busy(plci))
9586                         {
9587                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9588                                 break;
9589                         }
9590                         dtmf_enable_receiver(plci, plci->dtmf_rec_active);
9591                         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9592                         break;
9593                 case ADJUST_B_RESTORE_DTMF_2:
9594                         if ((Rc != OK) && (Rc != OK_FC))
9595                         {
9596                                 dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9597                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9598                                 Info = _WRONG_STATE;
9599                                 break;
9600                         }
9601                         break;
9602                 }
9603         }
9604         return (Info);
9605 }
9606
9607
9608 static void dtmf_command(dword Id, PLCI *plci, byte Rc)
9609 {
9610         word internal_command, Info;
9611         byte mask;
9612         byte result[4];
9613
9614         dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9615                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9616                         plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9617                         plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9618
9619         Info = GOOD;
9620         result[0] = 2;
9621         PUT_WORD(&result[1], DTMF_SUCCESS);
9622         internal_command = plci->internal_command;
9623         plci->internal_command = 0;
9624         mask = 0x01;
9625         switch (plci->dtmf_cmd)
9626         {
9627
9628         case DTMF_LISTEN_TONE_START:
9629                 mask <<= 1;
9630         case DTMF_LISTEN_MF_START:
9631                 mask <<= 1;
9632
9633         case DTMF_LISTEN_START:
9634                 switch (internal_command)
9635                 {
9636                 default:
9637                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9638                                                                   B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9639                 case DTMF_COMMAND_1:
9640                         if (adjust_b_process(Id, plci, Rc) != GOOD)
9641                         {
9642                                 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9643                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9644                                 Info = _FACILITY_NOT_SUPPORTED;
9645                                 break;
9646                         }
9647                         if (plci->internal_command)
9648                                 return;
9649                 case DTMF_COMMAND_2:
9650                         if (plci_nl_busy(plci))
9651                         {
9652                                 plci->internal_command = DTMF_COMMAND_2;
9653                                 return;
9654                         }
9655                         plci->internal_command = DTMF_COMMAND_3;
9656                         dtmf_enable_receiver(plci, (byte)(plci->dtmf_rec_active | mask));
9657                         return;
9658                 case DTMF_COMMAND_3:
9659                         if ((Rc != OK) && (Rc != OK_FC))
9660                         {
9661                                 dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9662                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9663                                 Info = _FACILITY_NOT_SUPPORTED;
9664                                 break;
9665                         }
9666
9667                         plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9668
9669                         plci->dtmf_rec_active |= mask;
9670                         break;
9671                 }
9672                 break;
9673
9674
9675         case DTMF_LISTEN_TONE_STOP:
9676                 mask <<= 1;
9677         case DTMF_LISTEN_MF_STOP:
9678                 mask <<= 1;
9679
9680         case DTMF_LISTEN_STOP:
9681                 switch (internal_command)
9682                 {
9683                 default:
9684                         plci->dtmf_rec_active &= ~mask;
9685                         if (plci->dtmf_rec_active)
9686                                 break;
9687 /*
9688   case DTMF_COMMAND_1:
9689   if (plci->dtmf_rec_active)
9690   {
9691   if (plci_nl_busy (plci))
9692   {
9693   plci->internal_command = DTMF_COMMAND_1;
9694   return;
9695   }
9696   plci->dtmf_rec_active &= ~mask;
9697   plci->internal_command = DTMF_COMMAND_2;
9698   dtmf_enable_receiver (plci, false);
9699   return;
9700   }
9701   Rc = OK;
9702   case DTMF_COMMAND_2:
9703   if ((Rc != OK) && (Rc != OK_FC))
9704   {
9705   dbug (1, dprintf("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9706   UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9707   Info = _FACILITY_NOT_SUPPORTED;
9708   break;
9709   }
9710 */
9711                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
9712                                                                   ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9713                 case DTMF_COMMAND_3:
9714                         if (adjust_b_process(Id, plci, Rc) != GOOD)
9715                         {
9716                                 dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9717                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9718                                 Info = _FACILITY_NOT_SUPPORTED;
9719                                 break;
9720                         }
9721                         if (plci->internal_command)
9722                                 return;
9723                         break;
9724                 }
9725                 break;
9726
9727
9728         case DTMF_SEND_TONE:
9729                 mask <<= 1;
9730         case DTMF_SEND_MF:
9731                 mask <<= 1;
9732
9733         case DTMF_DIGITS_SEND:
9734                 switch (internal_command)
9735                 {
9736                 default:
9737                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9738                                                                   ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9739                                            DTMF_COMMAND_1);
9740                 case DTMF_COMMAND_1:
9741                         if (adjust_b_process(Id, plci, Rc) != GOOD)
9742                         {
9743                                 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9744                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9745                                 Info = _FACILITY_NOT_SUPPORTED;
9746                                 break;
9747                         }
9748                         if (plci->internal_command)
9749                                 return;
9750                 case DTMF_COMMAND_2:
9751                         if (plci_nl_busy(plci))
9752                         {
9753                                 plci->internal_command = DTMF_COMMAND_2;
9754                                 return;
9755                         }
9756                         plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9757                         plci->internal_command = DTMF_COMMAND_3;
9758                         dtmf_send_digits(plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9759                         return;
9760                 case DTMF_COMMAND_3:
9761                         if ((Rc != OK) && (Rc != OK_FC))
9762                         {
9763                                 dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9764                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9765                                 if (plci->dtmf_send_requests != 0)
9766                                         (plci->dtmf_send_requests)--;
9767                                 Info = _FACILITY_NOT_SUPPORTED;
9768                                 break;
9769                         }
9770                         return;
9771                 }
9772                 break;
9773         }
9774         sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9775               "wws", Info, SELECTOR_DTMF, result);
9776 }
9777
9778
9779 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
9780 {
9781         word Info;
9782         word i, j;
9783         byte mask;
9784         API_PARSE dtmf_parms[5];
9785         byte result[40];
9786
9787         dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9788                         UnMapId(Id), (char *)(FILE_), __LINE__));
9789
9790         Info = GOOD;
9791         result[0] = 2;
9792         PUT_WORD(&result[1], DTMF_SUCCESS);
9793         if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9794         {
9795                 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9796                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9797                 Info = _FACILITY_NOT_SUPPORTED;
9798         }
9799         else if (api_parse(&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9800         {
9801                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9802                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9803                 Info = _WRONG_MESSAGE_FORMAT;
9804         }
9805
9806         else if ((GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9807                  || (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9808         {
9809                 if (!((a->requested_options_table[appl->Id - 1])
9810                       & (1L << PRIVATE_DTMF_TONE)))
9811                 {
9812                         dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9813                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9814                         PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9815                 }
9816                 else
9817                 {
9818                         for (i = 0; i < 32; i++)
9819                                 result[4 + i] = 0;
9820                         if (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9821                         {
9822                                 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9823                                 {
9824                                         if (dtmf_digit_map[i].listen_mask != 0)
9825                                                 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9826                                 }
9827                         }
9828                         else
9829                         {
9830                                 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9831                                 {
9832                                         if (dtmf_digit_map[i].send_mask != 0)
9833                                                 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9834                                 }
9835                         }
9836                         result[0] = 3 + 32;
9837                         result[3] = 32;
9838                 }
9839         }
9840
9841         else if (plci == NULL)
9842         {
9843                 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9844                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9845                 Info = _WRONG_IDENTIFIER;
9846         }
9847         else
9848         {
9849                 if (!plci->State
9850                     || !plci->NL.Id || plci->nl_remove_id)
9851                 {
9852                         dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9853                                         UnMapId(Id), (char *)(FILE_), __LINE__));
9854                         Info = _WRONG_STATE;
9855                 }
9856                 else
9857                 {
9858                         plci->command = 0;
9859                         plci->dtmf_cmd = GET_WORD(dtmf_parms[0].info);
9860                         mask = 0x01;
9861                         switch (plci->dtmf_cmd)
9862                         {
9863
9864                         case DTMF_LISTEN_TONE_START:
9865                         case DTMF_LISTEN_TONE_STOP:
9866                                 mask <<= 1;
9867                         case DTMF_LISTEN_MF_START:
9868                         case DTMF_LISTEN_MF_STOP:
9869                                 mask <<= 1;
9870                                 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
9871                                       & (1L << PRIVATE_DTMF_TONE)))
9872                                 {
9873                                         dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9874                                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9875                                         PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9876                                         break;
9877                                 }
9878
9879                         case DTMF_LISTEN_START:
9880                         case DTMF_LISTEN_STOP:
9881                                 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
9882                                     && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
9883                                 {
9884                                         dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9885                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
9886                                         Info = _FACILITY_NOT_SUPPORTED;
9887                                         break;
9888                                 }
9889                                 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
9890                                 {
9891                                         if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
9892                                         {
9893                                                 plci->dtmf_rec_pulse_ms = 0;
9894                                                 plci->dtmf_rec_pause_ms = 0;
9895                                         }
9896                                         else
9897                                         {
9898                                                 plci->dtmf_rec_pulse_ms = GET_WORD(dtmf_parms[1].info);
9899                                                 plci->dtmf_rec_pause_ms = GET_WORD(dtmf_parms[2].info);
9900                                         }
9901                                 }
9902                                 start_internal_command(Id, plci, dtmf_command);
9903                                 return (false);
9904
9905
9906                         case DTMF_SEND_TONE:
9907                                 mask <<= 1;
9908                         case DTMF_SEND_MF:
9909                                 mask <<= 1;
9910                                 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
9911                                       & (1L << PRIVATE_DTMF_TONE)))
9912                                 {
9913                                         dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9914                                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9915                                         PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9916                                         break;
9917                                 }
9918
9919                         case DTMF_DIGITS_SEND:
9920                                 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
9921                                 {
9922                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9923                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
9924                                         Info = _WRONG_MESSAGE_FORMAT;
9925                                         break;
9926                                 }
9927                                 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
9928                                 {
9929                                         plci->dtmf_send_pulse_ms = GET_WORD(dtmf_parms[1].info);
9930                                         plci->dtmf_send_pause_ms = GET_WORD(dtmf_parms[2].info);
9931                                 }
9932                                 i = 0;
9933                                 j = 0;
9934                                 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
9935                                 {
9936                                         j = 0;
9937                                         while ((j < DTMF_DIGIT_MAP_ENTRIES)
9938                                                && ((dtmf_parms[3].info[i + 1] != dtmf_digit_map[j].character)
9939                                                    || ((dtmf_digit_map[j].send_mask & mask) == 0)))
9940                                         {
9941                                                 j++;
9942                                         }
9943                                         i++;
9944                                 }
9945                                 if (j == DTMF_DIGIT_MAP_ENTRIES)
9946                                 {
9947                                         dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
9948                                                         UnMapId(Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
9949                                         PUT_WORD(&result[1], DTMF_INCORRECT_DIGIT);
9950                                         break;
9951                                 }
9952                                 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
9953                                 {
9954                                         dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
9955                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
9956                                         Info = _WRONG_STATE;
9957                                         break;
9958                                 }
9959                                 api_save_msg(dtmf_parms, "wwws", &plci->saved_msg);
9960                                 start_internal_command(Id, plci, dtmf_command);
9961                                 return (false);
9962
9963                         default:
9964                                 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9965                                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
9966                                 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9967                         }
9968                 }
9969         }
9970         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
9971               "wws", Info, SELECTOR_DTMF, result);
9972         return (false);
9973 }
9974
9975
9976 static void dtmf_confirmation(dword Id, PLCI *plci)
9977 {
9978         word i;
9979         byte result[4];
9980
9981         dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
9982                         UnMapId(Id), (char *)(FILE_), __LINE__));
9983
9984         result[0] = 2;
9985         PUT_WORD(&result[1], DTMF_SUCCESS);
9986         if (plci->dtmf_send_requests != 0)
9987         {
9988                 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
9989                       "wws", GOOD, SELECTOR_DTMF, result);
9990                 (plci->dtmf_send_requests)--;
9991                 for (i = 0; i < plci->dtmf_send_requests; i++)
9992                         plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i + 1];
9993         }
9994 }
9995
9996
9997 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length)
9998 {
9999         word i, j, n;
10000
10001         dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10002                         UnMapId(Id), (char *)(FILE_), __LINE__));
10003
10004         n = 0;
10005         for (i = 1; i < length; i++)
10006         {
10007                 j = 0;
10008                 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10009                        && ((msg[i] != dtmf_digit_map[j].code)
10010                            || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10011                 {
10012                         j++;
10013                 }
10014                 if (j < DTMF_DIGIT_MAP_ENTRIES)
10015                 {
10016
10017                         if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10018                             && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10019                             && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10020                         {
10021                                 if (n + 1 == i)
10022                                 {
10023                                         for (i = length; i > n + 1; i--)
10024                                                 msg[i] = msg[i - 1];
10025                                         length++;
10026                                         i++;
10027                                 }
10028                                 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10029                         }
10030                         plci->tone_last_indication_code = dtmf_digit_map[j].character;
10031
10032                         msg[++n] = dtmf_digit_map[j].character;
10033                 }
10034         }
10035         if (n != 0)
10036         {
10037                 msg[0] = (byte) n;
10038                 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10039         }
10040 }
10041
10042
10043 /*------------------------------------------------------------------*/
10044 /* DTMF parameters                                                  */
10045 /*------------------------------------------------------------------*/
10046
10047 static void dtmf_parameter_write(PLCI *plci)
10048 {
10049         word i;
10050         byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10051
10052         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10053                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10054                         (char *)(FILE_), __LINE__));
10055
10056         parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10057         parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10058         for (i = 0; i < plci->dtmf_parameter_length; i++)
10059                 parameter_buffer[2 + i] = plci->dtmf_parameter_buffer[i];
10060         add_p(plci, FTY, parameter_buffer);
10061         sig_req(plci, TEL_CTRL, 0);
10062         send_req(plci);
10063 }
10064
10065
10066 static void dtmf_parameter_clear_config(PLCI *plci)
10067 {
10068
10069         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10070                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10071                         (char *)(FILE_), __LINE__));
10072
10073         plci->dtmf_parameter_length = 0;
10074 }
10075
10076
10077 static void dtmf_parameter_prepare_switch(dword Id, PLCI *plci)
10078 {
10079
10080         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10081                         UnMapId(Id), (char *)(FILE_), __LINE__));
10082
10083 }
10084
10085
10086 static word dtmf_parameter_save_config(dword Id, PLCI *plci, byte Rc)
10087 {
10088
10089         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10090                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10091
10092         return (GOOD);
10093 }
10094
10095
10096 static word dtmf_parameter_restore_config(dword Id, PLCI *plci, byte Rc)
10097 {
10098         word Info;
10099
10100         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10101                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10102
10103         Info = GOOD;
10104         if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10105             && (plci->dtmf_parameter_length != 0))
10106         {
10107                 switch (plci->adjust_b_state)
10108                 {
10109                 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10110                         plci->internal_command = plci->adjust_b_command;
10111                         if (plci->sig_req)
10112                         {
10113                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10114                                 break;
10115                         }
10116                         dtmf_parameter_write(plci);
10117                         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10118                         break;
10119                 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10120                         if ((Rc != OK) && (Rc != OK_FC))
10121                         {
10122                                 dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10123                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10124                                 Info = _WRONG_STATE;
10125                                 break;
10126                         }
10127                         break;
10128                 }
10129         }
10130         return (Info);
10131 }
10132
10133
10134 /*------------------------------------------------------------------*/
10135 /* Line interconnect facilities                                     */
10136 /*------------------------------------------------------------------*/
10137
10138
10139 LI_CONFIG   *li_config_table;
10140 word li_total_channels;
10141
10142
10143 /*------------------------------------------------------------------*/
10144 /* translate a CHI information element to a channel number          */
10145 /* returns 0xff - any channel                                       */
10146 /*         0xfe - chi wrong coding                                  */
10147 /*         0xfd - D-channel                                         */
10148 /*         0x00 - no channel                                        */
10149 /*         else channel number / PRI: timeslot                      */
10150 /* if channels is provided we accept more than one channel.         */
10151 /*------------------------------------------------------------------*/
10152
10153 static byte chi_to_channel(byte *chi, dword *pchannelmap)
10154 {
10155         int p;
10156         int i;
10157         dword map;
10158         byte excl;
10159         byte ofs;
10160         byte ch;
10161
10162         if (pchannelmap) *pchannelmap = 0;
10163         if (!chi[0]) return 0xff;
10164         excl = 0;
10165
10166         if (chi[1] & 0x20) {
10167                 if (chi[0] == 1 && chi[1] == 0xac) return 0xfd; /* exclusive d-channel */
10168                 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10169                 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10170                 if ((chi[1] | 0xc8) != 0xe9) return 0xfe;
10171                 if (chi[1] & 0x08) excl = 0x40;
10172
10173                 /* int. id present */
10174                 if (chi[1] & 0x40) {
10175                         p = i + 1;
10176                         for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10177                         if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10178                 }
10179
10180                 /* coding standard, Number/Map, Channel Type */
10181                 p = i + 1;
10182                 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10183                 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10184                 if ((chi[p] | 0xd0) != 0xd3) return 0xfe;
10185
10186                 /* Number/Map */
10187                 if (chi[p] & 0x10) {
10188
10189                         /* map */
10190                         if ((chi[0] - p) == 4) ofs = 0;
10191                         else if ((chi[0] - p) == 3) ofs = 1;
10192                         else return 0xfe;
10193                         ch = 0;
10194                         map = 0;
10195                         for (i = 0; i < 4 && p < chi[0]; i++) {
10196                                 p++;
10197                                 ch += 8;
10198                                 map <<= 8;
10199                                 if (chi[p]) {
10200                                         for (ch = 0; !(chi[p] & (1 << ch)); ch++);
10201                                         map |= chi[p];
10202                                 }
10203                         }
10204                         ch += ofs;
10205                         map <<= ofs;
10206                 }
10207                 else {
10208
10209                         /* number */
10210                         p = i + 1;
10211                         ch = chi[p] & 0x3f;
10212                         if (pchannelmap) {
10213                                 if ((byte)(chi[0] - p) > 30) return 0xfe;
10214                                 map = 0;
10215                                 for (i = p; i <= chi[0]; i++) {
10216                                         if ((chi[i] & 0x7f) > 31) return 0xfe;
10217                                         map |= (1L << (chi[i] & 0x7f));
10218                                 }
10219                         }
10220                         else {
10221                                 if (p != chi[0]) return 0xfe;
10222                                 if (ch > 31) return 0xfe;
10223                                 map = (1L << ch);
10224                         }
10225                         if (chi[p] & 0x40) return 0xfe;
10226                 }
10227                 if (pchannelmap) *pchannelmap = map;
10228                 else if (map != ((dword)(1L << ch))) return 0xfe;
10229                 return (byte)(excl | ch);
10230         }
10231         else {  /* not PRI */
10232                 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10233                 if (i != chi[0] || !(chi[i] & 0x80)) return 0xfe;
10234                 if (chi[1] & 0x08) excl = 0x40;
10235
10236                 switch (chi[1] | 0x98) {
10237                 case 0x98: return 0;
10238                 case 0x99:
10239                         if (pchannelmap) *pchannelmap = 2;
10240                         return excl | 1;
10241                 case 0x9a:
10242                         if (pchannelmap) *pchannelmap = 4;
10243                         return excl | 2;
10244                 case 0x9b: return 0xff;
10245                 case 0x9c: return 0xfd; /* d-ch */
10246                 default: return 0xfe;
10247                 }
10248         }
10249 }
10250
10251
10252 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id)
10253 {
10254         DIVA_CAPI_ADAPTER *a;
10255         PLCI *splci;
10256         byte old_id;
10257
10258         a = plci->adapter;
10259         old_id = plci->li_bchannel_id;
10260         if (a->li_pri)
10261         {
10262                 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10263                         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10264                 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10265                 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10266                         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10267         }
10268         else
10269         {
10270                 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10271                 {
10272                         if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10273                                 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10274                         plci->li_bchannel_id = bchannel_id & 0x03;
10275                         if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10276                         {
10277                                 splci = a->AdvSignalPLCI;
10278                                 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10279                                 {
10280                                         if ((splci->li_bchannel_id != 0)
10281                                             && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10282                                         {
10283                                                 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10284                                         }
10285                                         splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10286                                         li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10287                                         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10288                                                         (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10289                                                         (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10290                                 }
10291                         }
10292                         if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10293                                 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10294                 }
10295         }
10296         if ((old_id == 0) && (plci->li_bchannel_id != 0)
10297             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10298         {
10299                 mixer_clear_config(plci);
10300         }
10301         dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10302                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10303                         (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10304 }
10305
10306
10307 static void mixer_set_bchannel_id(PLCI *plci, byte *chi)
10308 {
10309         DIVA_CAPI_ADAPTER *a;
10310         PLCI *splci;
10311         byte ch, old_id;
10312
10313         a = plci->adapter;
10314         old_id = plci->li_bchannel_id;
10315         ch = chi_to_channel(chi, NULL);
10316         if (!(ch & 0x80))
10317         {
10318                 if (a->li_pri)
10319                 {
10320                         if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10321                                 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10322                         plci->li_bchannel_id = (ch & 0x1f) + 1;
10323                         if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10324                                 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10325                 }
10326                 else
10327                 {
10328                         if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10329                         {
10330                                 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10331                                         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10332                                 plci->li_bchannel_id = ch & 0x1f;
10333                                 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10334                                 {
10335                                         splci = a->AdvSignalPLCI;
10336                                         if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10337                                         {
10338                                                 if ((splci->li_bchannel_id != 0)
10339                                                     && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10340                                                 {
10341                                                         li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10342                                                 }
10343                                                 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10344                                                 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10345                                                 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10346                                                                 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10347                                                                 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10348                                         }
10349                                 }
10350                                 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10351                                         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10352                         }
10353                 }
10354         }
10355         if ((old_id == 0) && (plci->li_bchannel_id != 0)
10356             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10357         {
10358                 mixer_clear_config(plci);
10359         }
10360         dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10361                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10362                         (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10363 }
10364
10365
10366 #define MIXER_MAX_DUMP_CHANNELS 34
10367
10368 static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER *a)
10369 {
10370         word n, i, j;
10371         char *p;
10372         char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10373
10374         dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10375                         (dword)(UnMapController(a->Id)), (char *)(FILE_), __LINE__));
10376
10377         for (i = 0; i < li_total_channels; i++)
10378         {
10379                 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10380                 if (li_config_table[i].chflags != 0)
10381                         li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10382                 else
10383                 {
10384                         for (j = 0; j < li_total_channels; j++)
10385                         {
10386                                 if (((li_config_table[i].flag_table[j]) != 0)
10387                                     || ((li_config_table[j].flag_table[i]) != 0))
10388                                 {
10389                                         li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10390                                 }
10391                                 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10392                                     || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10393                                 {
10394                                         li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10395                                 }
10396                         }
10397                 }
10398         }
10399         for (i = 0; i < li_total_channels; i++)
10400         {
10401                 for (j = 0; j < li_total_channels; j++)
10402                 {
10403                         li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10404                         if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10405                                 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10406                 }
10407         }
10408         for (n = 0; n < li_total_channels; n++)
10409         {
10410                 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10411                 {
10412                         for (i = 0; i < li_total_channels; i++)
10413                         {
10414                                 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10415                                 {
10416                                         for (j = 0; j < li_total_channels; j++)
10417                                         {
10418                                                 li_config_table[i].coef_table[j] |=
10419                                                         li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10420                                         }
10421                                 }
10422                         }
10423                 }
10424         }
10425         for (i = 0; i < li_total_channels; i++)
10426         {
10427                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10428                 {
10429                         li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10430                         for (j = 0; j < li_total_channels; j++)
10431                         {
10432                                 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10433                                         li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10434                         }
10435                         if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10436                                 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10437                 }
10438         }
10439         for (i = 0; i < li_total_channels; i++)
10440         {
10441                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10442                 {
10443                         for (j = 0; j < li_total_channels; j++)
10444                         {
10445                                 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10446                                         li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10447                                 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10448                                         li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10449                                 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10450                                         li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10451                                 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10452                                         li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10453                         }
10454                         if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10455                         {
10456                                 for (j = 0; j < li_total_channels; j++)
10457                                 {
10458                                         if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10459                                         {
10460                                                 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10461                                                 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10462                                                         li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10463                                         }
10464                                 }
10465                         }
10466                         if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10467                         {
10468                                 for (j = 0; j < li_total_channels; j++)
10469                                 {
10470                                         if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10471                                                 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10472                                 }
10473                         }
10474                         if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10475                         {
10476                                 for (j = 0; j < li_total_channels; j++)
10477                                 {
10478                                         if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10479                                         {
10480                                                 for (n = 0; n < li_total_channels; n++)
10481                                                 {
10482                                                         if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10483                                                         {
10484                                                                 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10485                                                                 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10486                                                                 {
10487                                                                         li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10488                                                                         if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10489                                                                                 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10490                                                                 }
10491                                                                 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10492                                                                         li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10493                                                         }
10494                                                 }
10495                                         }
10496                                 }
10497                         }
10498                 }
10499         }
10500         for (i = 0; i < li_total_channels; i++)
10501         {
10502                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10503                 {
10504                         if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10505                                 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10506                         if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10507                                 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10508                         if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10509                                 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10510                         for (j = 0; j < li_total_channels; j++)
10511                         {
10512                                 if ((li_config_table[i].flag_table[j] &
10513                                      (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10514                                     || (li_config_table[j].flag_table[i] &
10515                                         (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10516                                 {
10517                                         li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10518                                 }
10519                                 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10520                                         li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10521                                 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10522                                         li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10523                         }
10524                         if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10525                         {
10526                                 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10527                                 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10528                         }
10529                 }
10530         }
10531         for (i = 0; i < li_total_channels; i++)
10532         {
10533                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10534                 {
10535                         j = 0;
10536                         while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10537                                 j++;
10538                         if (j < li_total_channels)
10539                         {
10540                                 for (j = 0; j < li_total_channels; j++)
10541                                 {
10542                                         li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10543                                         if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10544                                                 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10545                                 }
10546                         }
10547                 }
10548         }
10549         n = li_total_channels;
10550         if (n > MIXER_MAX_DUMP_CHANNELS)
10551                 n = MIXER_MAX_DUMP_CHANNELS;
10552
10553         p = hex_line;
10554         for (j = 0; j < n; j++)
10555         {
10556                 if ((j & 0x7) == 0)
10557                         *(p++) = ' ';
10558                 p = hex_byte_pack(p, li_config_table[j].curchnl);
10559         }
10560         *p = '\0';
10561         dbug(1, dprintf("[%06lx] CURRENT %s",
10562                         (dword)(UnMapController(a->Id)), (char *)hex_line));
10563         p = hex_line;
10564         for (j = 0; j < n; j++)
10565         {
10566                 if ((j & 0x7) == 0)
10567                         *(p++) = ' ';
10568                 p = hex_byte_pack(p, li_config_table[j].channel);
10569         }
10570         *p = '\0';
10571         dbug(1, dprintf("[%06lx] CHANNEL %s",
10572                         (dword)(UnMapController(a->Id)), (char *)hex_line));
10573         p = hex_line;
10574         for (j = 0; j < n; j++)
10575         {
10576                 if ((j & 0x7) == 0)
10577                         *(p++) = ' ';
10578                 p = hex_byte_pack(p, li_config_table[j].chflags);
10579         }
10580         *p = '\0';
10581         dbug(1, dprintf("[%06lx] CHFLAG  %s",
10582                         (dword)(UnMapController(a->Id)), (char *)hex_line));
10583         for (i = 0; i < n; i++)
10584         {
10585                 p = hex_line;
10586                 for (j = 0; j < n; j++)
10587                 {
10588                         if ((j & 0x7) == 0)
10589                                 *(p++) = ' ';
10590                         p = hex_byte_pack(p, li_config_table[i].flag_table[j]);
10591                 }
10592                 *p = '\0';
10593                 dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10594                                 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10595         }
10596         for (i = 0; i < n; i++)
10597         {
10598                 p = hex_line;
10599                 for (j = 0; j < n; j++)
10600                 {
10601                         if ((j & 0x7) == 0)
10602                                 *(p++) = ' ';
10603                         p = hex_byte_pack(p, li_config_table[i].coef_table[j]);
10604                 }
10605                 *p = '\0';
10606                 dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10607                                 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10608         }
10609 }
10610
10611
10612 static struct
10613 {
10614         byte mask;
10615         byte line_flags;
10616 } mixer_write_prog_pri[] =
10617 {
10618         { LI_COEF_CH_CH, 0 },
10619         { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10620         { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10621         { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10622 };
10623
10624 static struct
10625 {
10626         byte from_ch;
10627         byte to_ch;
10628         byte mask;
10629         byte xconnect_override;
10630 } mixer_write_prog_bri[] =
10631 {
10632         { 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10633         { 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10634         { 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10635         { 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10636         { 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10637         { 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10638         { 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10639         { 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10640         { 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10641         { 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10642         { 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10643         { 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10644         { 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10645         { 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10646         { 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10647         { 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10648         { 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10649         { 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10650         { 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10651         { 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10652         { 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10653         { 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10654         { 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10655         { 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10656         { 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10657         { 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10658         { 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10659         { 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10660         { 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10661         { 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10662         { 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10663         { 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10664         { 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10665         { 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10666         { 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10667         { 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10668 };
10669
10670 static byte mixer_swapped_index_bri[] =
10671 {
10672         18,  /* B      to B      */
10673         19,  /* Alt B  to B      */
10674         20,  /* PC     to B      */
10675         21,  /* Alt PC to B      */
10676         22,  /* IC     to B      */
10677         23,  /* Alt IC to B      */
10678         24,  /* B      to PC     */
10679         25,  /* Alt B  to PC     */
10680         26,  /* PC     to PC     */
10681         27,  /* Alt PC to PC     */
10682         28,  /* IC     to PC     */
10683         29,  /* Alt IC to PC     */
10684         30,  /* B      to IC     */
10685         31,  /* Alt B  to IC     */
10686         32,  /* PC     to IC     */
10687         33,  /* Alt PC to IC     */
10688         34,  /* IC     to IC     */
10689         35,  /* Alt IC to IC     */
10690         0,   /* Alt B  to Alt B  */
10691         1,   /* B      to Alt B  */
10692         2,   /* Alt PC to Alt B  */
10693         3,   /* PC     to Alt B  */
10694         4,   /* Alt IC to Alt B  */
10695         5,   /* IC     to Alt B  */
10696         6,   /* Alt B  to Alt PC */
10697         7,   /* B      to Alt PC */
10698         8,   /* Alt PC to Alt PC */
10699         9,   /* PC     to Alt PC */
10700         10,  /* Alt IC to Alt PC */
10701         11,  /* IC     to Alt PC */
10702         12,  /* Alt B  to Alt IC */
10703         13,  /* B      to Alt IC */
10704         14,  /* Alt PC to Alt IC */
10705         15,  /* PC     to Alt IC */
10706         16,  /* Alt IC to Alt IC */
10707         17   /* IC     to Alt IC */
10708 };
10709
10710 static struct
10711 {
10712         byte mask;
10713         byte from_pc;
10714         byte to_pc;
10715 } xconnect_write_prog[] =
10716 {
10717         { LI_COEF_CH_CH, false, false },
10718         { LI_COEF_CH_PC, false, true },
10719         { LI_COEF_PC_CH, true, false },
10720         { LI_COEF_PC_PC, true, true }
10721 };
10722
10723
10724 static void xconnect_query_addresses(PLCI *plci)
10725 {
10726         DIVA_CAPI_ADAPTER *a;
10727         word w, ch;
10728         byte *p;
10729
10730         dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10731                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10732                         (char *)(FILE_), __LINE__));
10733
10734         a = plci->adapter;
10735         if (a->li_pri && ((plci->li_bchannel_id == 0)
10736                           || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10737         {
10738                 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10739                                 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10740                                 (char *)(FILE_), __LINE__));
10741                 return;
10742         }
10743         p = plci->internal_req_buffer;
10744         ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10745         *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10746         w = ch;
10747         *(p++) = (byte) w;
10748         *(p++) = (byte)(w >> 8);
10749         w = ch | XCONNECT_CHANNEL_PORT_PC;
10750         *(p++) = (byte) w;
10751         *(p++) = (byte)(w >> 8);
10752         plci->NData[0].P = plci->internal_req_buffer;
10753         plci->NData[0].PLength = p - plci->internal_req_buffer;
10754         plci->NL.X = plci->NData;
10755         plci->NL.ReqCh = 0;
10756         plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10757         plci->adapter->request(&plci->NL);
10758 }
10759
10760
10761 static void xconnect_write_coefs(PLCI *plci, word internal_command)
10762 {
10763
10764         dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10765                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10766                         (char *)(FILE_), __LINE__, internal_command));
10767
10768         plci->li_write_command = internal_command;
10769         plci->li_write_channel = 0;
10770 }
10771
10772
10773 static byte xconnect_write_coefs_process(dword Id, PLCI *plci, byte Rc)
10774 {
10775         DIVA_CAPI_ADAPTER *a;
10776         word w, n, i, j, r, s, to_ch;
10777         dword d;
10778         byte *p;
10779         struct xconnect_transfer_address_s   *transfer_address;
10780         byte ch_map[MIXER_CHANNELS_BRI];
10781
10782         dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10783                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10784
10785         a = plci->adapter;
10786         if ((plci->li_bchannel_id == 0)
10787             || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10788         {
10789                 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10790                                 UnMapId(Id), (char *)(FILE_), __LINE__));
10791                 return (true);
10792         }
10793         i = a->li_base + (plci->li_bchannel_id - 1);
10794         j = plci->li_write_channel;
10795         p = plci->internal_req_buffer;
10796         if (j != 0)
10797         {
10798                 if ((Rc != OK) && (Rc != OK_FC))
10799                 {
10800                         dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10801                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10802                         return (false);
10803                 }
10804         }
10805         if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10806         {
10807                 r = 0;
10808                 s = 0;
10809                 if (j < li_total_channels)
10810                 {
10811                         if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10812                         {
10813                                 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10814                                      (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10815                                         ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10816                                          (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10817                         }
10818                         r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10819                         while ((j < li_total_channels)
10820                                && ((r == 0)
10821                                    || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10822                                    || (!li_config_table[j].adapter->li_pri
10823                                        && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10824                                    || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10825                                         || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10826                                        && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10827                                            || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10828                                    || ((li_config_table[j].adapter->li_base != a->li_base)
10829                                        && !(r & s &
10830                                             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10831                                              (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10832                                             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10833                                              (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10834                         {
10835                                 j++;
10836                                 if (j < li_total_channels)
10837                                         r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10838                         }
10839                 }
10840                 if (j < li_total_channels)
10841                 {
10842                         plci->internal_command = plci->li_write_command;
10843                         if (plci_nl_busy(plci))
10844                                 return (true);
10845                         to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10846                         *(p++) = UDATA_REQUEST_XCONNECT_TO;
10847                         do
10848                         {
10849                                 if (li_config_table[j].adapter->li_base != a->li_base)
10850                                 {
10851                                         r &= s &
10852                                                 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10853                                                  (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10854                                                 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10855                                                  (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10856                                 }
10857                                 n = 0;
10858                                 do
10859                                 {
10860                                         if (r & xconnect_write_prog[n].mask)
10861                                         {
10862                                                 if (xconnect_write_prog[n].from_pc)
10863                                                         transfer_address = &(li_config_table[j].send_pc);
10864                                                 else
10865                                                         transfer_address = &(li_config_table[j].send_b);
10866                                                 d = transfer_address->card_address.low;
10867                                                 *(p++) = (byte) d;
10868                                                 *(p++) = (byte)(d >> 8);
10869                                                 *(p++) = (byte)(d >> 16);
10870                                                 *(p++) = (byte)(d >> 24);
10871                                                 d = transfer_address->card_address.high;
10872                                                 *(p++) = (byte) d;
10873                                                 *(p++) = (byte)(d >> 8);
10874                                                 *(p++) = (byte)(d >> 16);
10875                                                 *(p++) = (byte)(d >> 24);
10876                                                 d = transfer_address->offset;
10877                                                 *(p++) = (byte) d;
10878                                                 *(p++) = (byte)(d >> 8);
10879                                                 *(p++) = (byte)(d >> 16);
10880                                                 *(p++) = (byte)(d >> 24);
10881                                                 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
10882                                                 *(p++) = (byte) w;
10883                                                 *(p++) = (byte)(w >> 8);
10884                                                 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
10885                                                         (li_config_table[i].adapter->u_law ?
10886                                                          (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
10887                                                          (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
10888                                                 *(p++) = (byte) w;
10889                                                 *(p++) = (byte) 0;
10890                                                 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
10891                                         }
10892                                         n++;
10893                                 } while ((n < ARRAY_SIZE(xconnect_write_prog))
10894                                          && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
10895                                 if (n == ARRAY_SIZE(xconnect_write_prog))
10896                                 {
10897                                         do
10898                                         {
10899                                                 j++;
10900                                                 if (j < li_total_channels)
10901                                                         r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10902                                         } while ((j < li_total_channels)
10903                                                  && ((r == 0)
10904                                                      || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10905                                                      || (!li_config_table[j].adapter->li_pri
10906                                                          && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10907                                                      || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10908                                                           || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10909                                                          && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10910                                                              || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10911                                                      || ((li_config_table[j].adapter->li_base != a->li_base)
10912                                                          && !(r & s &
10913                                                               ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10914                                                                (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10915                                                               ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10916                                                                (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
10917                                 }
10918                         } while ((j < li_total_channels)
10919                                  && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
10920                 }
10921                 else if (j == li_total_channels)
10922                 {
10923                         plci->internal_command = plci->li_write_command;
10924                         if (plci_nl_busy(plci))
10925                                 return (true);
10926                         if (a->li_pri)
10927                         {
10928                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
10929                                 w = 0;
10930                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
10931                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
10932                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
10933                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
10934                                 *(p++) = (byte) w;
10935                                 *(p++) = (byte)(w >> 8);
10936                         }
10937                         else
10938                         {
10939                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
10940                                 w = 0;
10941                                 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
10942                                     && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
10943                                 {
10944                                         w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
10945                                 }
10946                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
10947                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
10948                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
10949                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
10950                                 *(p++) = (byte) w;
10951                                 *(p++) = (byte)(w >> 8);
10952                                 for (j = 0; j < sizeof(ch_map); j += 2)
10953                                 {
10954                                         if (plci->li_bchannel_id == 2)
10955                                         {
10956                                                 ch_map[j] = (byte)(j + 1);
10957                                                 ch_map[j + 1] = (byte) j;
10958                                         }
10959                                         else
10960                                         {
10961                                                 ch_map[j] = (byte) j;
10962                                                 ch_map[j + 1] = (byte)(j + 1);
10963                                         }
10964                                 }
10965                                 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
10966                                 {
10967                                         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
10968                                         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
10969                                         if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
10970                                         {
10971                                                 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
10972                                                         mixer_write_prog_bri[n].xconnect_override :
10973                                                         ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
10974                                                 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
10975                                                 {
10976                                                         w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10977                                                         li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
10978                                                 }
10979                                         }
10980                                         else
10981                                         {
10982                                                 *p = 0x00;
10983                                                 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10984                                                 {
10985                                                         w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
10986                                                         if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
10987                                                                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
10988                                                 }
10989                                         }
10990                                         p++;
10991                                 }
10992                         }
10993                         j = li_total_channels + 1;
10994                 }
10995         }
10996         else
10997         {
10998                 if (j <= li_total_channels)
10999                 {
11000                         plci->internal_command = plci->li_write_command;
11001                         if (plci_nl_busy(plci))
11002                                 return (true);
11003                         if (j < a->li_base)
11004                                 j = a->li_base;
11005                         if (a->li_pri)
11006                         {
11007                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11008                                 w = 0;
11009                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11010                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
11011                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11012                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
11013                                 *(p++) = (byte) w;
11014                                 *(p++) = (byte)(w >> 8);
11015                                 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11016                                 {
11017                                         *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11018                                         for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11019                                         {
11020                                                 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11021                                                 if (w & mixer_write_prog_pri[n].mask)
11022                                                 {
11023                                                         *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11024                                                         li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11025                                                 }
11026                                                 else
11027                                                         *(p++) = 0x00;
11028                                         }
11029                                         *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11030                                         for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11031                                         {
11032                                                 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11033                                                 if (w & mixer_write_prog_pri[n].mask)
11034                                                 {
11035                                                         *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11036                                                         li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11037                                                 }
11038                                                 else
11039                                                         *(p++) = 0x00;
11040                                         }
11041                                 }
11042                         }
11043                         else
11044                         {
11045                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11046                                 w = 0;
11047                                 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11048                                     && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11049                                 {
11050                                         w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11051                                 }
11052                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11053                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
11054                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11055                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
11056                                 *(p++) = (byte) w;
11057                                 *(p++) = (byte)(w >> 8);
11058                                 for (j = 0; j < sizeof(ch_map); j += 2)
11059                                 {
11060                                         if (plci->li_bchannel_id == 2)
11061                                         {
11062                                                 ch_map[j] = (byte)(j + 1);
11063                                                 ch_map[j + 1] = (byte) j;
11064                                         }
11065                                         else
11066                                         {
11067                                                 ch_map[j] = (byte) j;
11068                                                 ch_map[j + 1] = (byte)(j + 1);
11069                                         }
11070                                 }
11071                                 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11072                                 {
11073                                         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11074                                         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11075                                         if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11076                                         {
11077                                                 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11078                                                 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11079                                                 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11080                                         }
11081                                         else
11082                                         {
11083                                                 *p = 0x00;
11084                                                 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11085                                                 {
11086                                                         w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11087                                                         if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11088                                                                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11089                                                 }
11090                                         }
11091                                         p++;
11092                                 }
11093                         }
11094                         j = li_total_channels + 1;
11095                 }
11096         }
11097         plci->li_write_channel = j;
11098         if (p != plci->internal_req_buffer)
11099         {
11100                 plci->NData[0].P = plci->internal_req_buffer;
11101                 plci->NData[0].PLength = p - plci->internal_req_buffer;
11102                 plci->NL.X = plci->NData;
11103                 plci->NL.ReqCh = 0;
11104                 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11105                 plci->adapter->request(&plci->NL);
11106         }
11107         return (true);
11108 }
11109
11110
11111 static void mixer_notify_update(PLCI *plci, byte others)
11112 {
11113         DIVA_CAPI_ADAPTER *a;
11114         word i, w;
11115         PLCI *notify_plci;
11116         byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11117
11118         dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11119                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11120                         (char *)(FILE_), __LINE__, others));
11121
11122         a = plci->adapter;
11123         if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11124         {
11125                 if (others)
11126                         plci->li_notify_update = true;
11127                 i = 0;
11128                 do
11129                 {
11130                         notify_plci = NULL;
11131                         if (others)
11132                         {
11133                                 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11134                                         i++;
11135                                 if (i < li_total_channels)
11136                                         notify_plci = li_config_table[i++].plci;
11137                         }
11138                         else
11139                         {
11140                                 if ((plci->li_bchannel_id != 0)
11141                                     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11142                                 {
11143                                         notify_plci = plci;
11144                                 }
11145                         }
11146                         if ((notify_plci != NULL)
11147                             && !notify_plci->li_notify_update
11148                             && (notify_plci->appl != NULL)
11149                             && (notify_plci->State)
11150                             && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11151                         {
11152                                 notify_plci->li_notify_update = true;
11153                                 ((CAPI_MSG *) msg)->header.length = 18;
11154                                 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11155                                 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11156                                 ((CAPI_MSG *) msg)->header.number = 0;
11157                                 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11158                                 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11159                                 ((CAPI_MSG *) msg)->header.ncci = 0;
11160                                 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11161                                 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11162                                 ((CAPI_MSG *) msg)->info.facility_req.structs[1] = LI_REQ_SILENT_UPDATE & 0xff;
11163                                 ((CAPI_MSG *) msg)->info.facility_req.structs[2] = LI_REQ_SILENT_UPDATE >> 8;
11164                                 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11165                                 w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11166                                 if (w != _QUEUE_FULL)
11167                                 {
11168                                         if (w != 0)
11169                                         {
11170                                                 dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11171                                                                 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11172                                                                 (char *)(FILE_), __LINE__,
11173                                                                 (dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11174                                         }
11175                                         notify_plci->li_notify_update = false;
11176                                 }
11177                         }
11178                 } while (others && (notify_plci != NULL));
11179                 if (others)
11180                         plci->li_notify_update = false;
11181         }
11182 }
11183
11184
11185 static void mixer_clear_config(PLCI *plci)
11186 {
11187         DIVA_CAPI_ADAPTER *a;
11188         word i, j;
11189
11190         dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11191                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11192                         (char *)(FILE_), __LINE__));
11193
11194         plci->li_notify_update = false;
11195         plci->li_plci_b_write_pos = 0;
11196         plci->li_plci_b_read_pos = 0;
11197         plci->li_plci_b_req_pos = 0;
11198         a = plci->adapter;
11199         if ((plci->li_bchannel_id != 0)
11200             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11201         {
11202                 i = a->li_base + (plci->li_bchannel_id - 1);
11203                 li_config_table[i].curchnl = 0;
11204                 li_config_table[i].channel = 0;
11205                 li_config_table[i].chflags = 0;
11206                 for (j = 0; j < li_total_channels; j++)
11207                 {
11208                         li_config_table[j].flag_table[i] = 0;
11209                         li_config_table[i].flag_table[j] = 0;
11210                         li_config_table[i].coef_table[j] = 0;
11211                         li_config_table[j].coef_table[i] = 0;
11212                 }
11213                 if (!a->li_pri)
11214                 {
11215                         li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11216                         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11217                         {
11218                                 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11219                                 li_config_table[i].curchnl = 0;
11220                                 li_config_table[i].channel = 0;
11221                                 li_config_table[i].chflags = 0;
11222                                 for (j = 0; j < li_total_channels; j++)
11223                                 {
11224                                         li_config_table[i].flag_table[j] = 0;
11225                                         li_config_table[j].flag_table[i] = 0;
11226                                         li_config_table[i].coef_table[j] = 0;
11227                                         li_config_table[j].coef_table[i] = 0;
11228                                 }
11229                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11230                                 {
11231                                         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11232                                         li_config_table[i].curchnl = 0;
11233                                         li_config_table[i].channel = 0;
11234                                         li_config_table[i].chflags = 0;
11235                                         for (j = 0; j < li_total_channels; j++)
11236                                         {
11237                                                 li_config_table[i].flag_table[j] = 0;
11238                                                 li_config_table[j].flag_table[i] = 0;
11239                                                 li_config_table[i].coef_table[j] = 0;
11240                                                 li_config_table[j].coef_table[i] = 0;
11241                                         }
11242                                 }
11243                         }
11244                 }
11245         }
11246 }
11247
11248
11249 static void mixer_prepare_switch(dword Id, PLCI *plci)
11250 {
11251
11252         dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11253                         UnMapId(Id), (char *)(FILE_), __LINE__));
11254
11255         do
11256         {
11257                 mixer_indication_coefs_set(Id, plci);
11258         } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11259 }
11260
11261
11262 static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11263 {
11264         DIVA_CAPI_ADAPTER *a;
11265         word i, j;
11266
11267         dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11268                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11269
11270         a = plci->adapter;
11271         if ((plci->li_bchannel_id != 0)
11272             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11273         {
11274                 i = a->li_base + (plci->li_bchannel_id - 1);
11275                 for (j = 0; j < li_total_channels; j++)
11276                 {
11277                         li_config_table[i].coef_table[j] &= 0xf;
11278                         li_config_table[j].coef_table[i] &= 0xf;
11279                 }
11280                 if (!a->li_pri)
11281                         li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11282         }
11283         return (GOOD);
11284 }
11285
11286
11287 static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11288 {
11289         DIVA_CAPI_ADAPTER *a;
11290         word Info;
11291
11292         dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11293                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11294
11295         Info = GOOD;
11296         a = plci->adapter;
11297         if ((plci->B1_facilities & B1_FACILITY_MIXER)
11298             && (plci->li_bchannel_id != 0)
11299             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11300         {
11301                 switch (plci->adjust_b_state)
11302                 {
11303                 case ADJUST_B_RESTORE_MIXER_1:
11304                         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11305                         {
11306                                 plci->internal_command = plci->adjust_b_command;
11307                                 if (plci_nl_busy(plci))
11308                                 {
11309                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11310                                         break;
11311                                 }
11312                                 xconnect_query_addresses(plci);
11313                                 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11314                                 break;
11315                         }
11316                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11317                         Rc = OK;
11318                 case ADJUST_B_RESTORE_MIXER_2:
11319                 case ADJUST_B_RESTORE_MIXER_3:
11320                 case ADJUST_B_RESTORE_MIXER_4:
11321                         if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11322                         {
11323                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11324                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11325                                 Info = _WRONG_STATE;
11326                                 break;
11327                         }
11328                         if (Rc == OK)
11329                         {
11330                                 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11331                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11332                                 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11333                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11334                         }
11335                         else if (Rc == 0)
11336                         {
11337                                 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11338                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11339                                 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11340                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11341                         }
11342                         if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11343                         {
11344                                 plci->internal_command = plci->adjust_b_command;
11345                                 break;
11346                         }
11347                 case ADJUST_B_RESTORE_MIXER_5:
11348                         xconnect_write_coefs(plci, plci->adjust_b_command);
11349                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11350                         Rc = OK;
11351                 case ADJUST_B_RESTORE_MIXER_6:
11352                         if (!xconnect_write_coefs_process(Id, plci, Rc))
11353                         {
11354                                 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11355                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11356                                 Info = _FACILITY_NOT_SUPPORTED;
11357                                 break;
11358                         }
11359                         if (plci->internal_command)
11360                                 break;
11361                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11362                 case ADJUST_B_RESTORE_MIXER_7:
11363                         break;
11364                 }
11365         }
11366         return (Info);
11367 }
11368
11369
11370 static void mixer_command(dword Id, PLCI *plci, byte Rc)
11371 {
11372         DIVA_CAPI_ADAPTER *a;
11373         word i, internal_command;
11374
11375         dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11376                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11377                         plci->li_cmd));
11378
11379         a = plci->adapter;
11380         internal_command = plci->internal_command;
11381         plci->internal_command = 0;
11382         switch (plci->li_cmd)
11383         {
11384         case LI_REQ_CONNECT:
11385         case LI_REQ_DISCONNECT:
11386         case LI_REQ_SILENT_UPDATE:
11387                 switch (internal_command)
11388                 {
11389                 default:
11390                         if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11391                         {
11392                                 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11393                                                                           B1_FACILITY_MIXER), MIXER_COMMAND_1);
11394                         }
11395                 case MIXER_COMMAND_1:
11396                         if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11397                         {
11398                                 if (adjust_b_process(Id, plci, Rc) != GOOD)
11399                                 {
11400                                         dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11401                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
11402                                         break;
11403                                 }
11404                                 if (plci->internal_command)
11405                                         return;
11406                         }
11407                         plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11408                         if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11409                             || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11410                                 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11411                                                                                       ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11412                         {
11413                                 xconnect_write_coefs(plci, MIXER_COMMAND_2);
11414                         }
11415                         else
11416                         {
11417                                 do
11418                                 {
11419                                         mixer_indication_coefs_set(Id, plci);
11420                                 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11421                         }
11422                 case MIXER_COMMAND_2:
11423                         if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11424                             || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11425                                 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11426                                                                                       ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11427                         {
11428                                 if (!xconnect_write_coefs_process(Id, plci, Rc))
11429                                 {
11430                                         dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11431                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
11432                                         if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11433                                         {
11434                                                 do
11435                                                 {
11436                                                         plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11437                                                                 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11438                                                         i = (plci->li_plci_b_write_pos == 0) ?
11439                                                                 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11440                                                 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11441                                                          && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11442                                         }
11443                                         break;
11444                                 }
11445                                 if (plci->internal_command)
11446                                         return;
11447                         }
11448                         if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11449                         {
11450                                 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11451                                                                           ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11452                         }
11453                 case MIXER_COMMAND_3:
11454                         if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11455                         {
11456                                 if (adjust_b_process(Id, plci, Rc) != GOOD)
11457                                 {
11458                                         dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11459                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
11460                                         break;
11461                                 }
11462                                 if (plci->internal_command)
11463                                         return;
11464                         }
11465                         break;
11466                 }
11467                 break;
11468         }
11469         if ((plci->li_bchannel_id == 0)
11470             || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11471         {
11472                 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11473                                 UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11474         }
11475         else
11476         {
11477                 i = a->li_base + (plci->li_bchannel_id - 1);
11478                 li_config_table[i].curchnl = plci->li_channel_bits;
11479                 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11480                 {
11481                         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11482                         li_config_table[i].curchnl = plci->li_channel_bits;
11483                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11484                         {
11485                                 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11486                                 li_config_table[i].curchnl = plci->li_channel_bits;
11487                         }
11488                 }
11489         }
11490 }
11491
11492
11493 static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11494                               dword plci_b_id, byte connect, dword li_flags)
11495 {
11496         word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11497         PLCI *plci_b;
11498         DIVA_CAPI_ADAPTER *a_b;
11499
11500         a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11501         plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11502         ch_a = a->li_base + (plci->li_bchannel_id - 1);
11503         if (!a->li_pri && (plci->tel == ADV_VOICE)
11504             && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11505         {
11506                 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11507                 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11508                         a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11509         }
11510         else
11511         {
11512                 ch_a_v = ch_a;
11513                 ch_a_s = ch_a;
11514         }
11515         ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11516         if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11517             && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11518         {
11519                 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11520                 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11521                         a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11522         }
11523         else
11524         {
11525                 ch_b_v = ch_b;
11526                 ch_b_s = ch_b;
11527         }
11528         if (connect)
11529         {
11530                 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11531                 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11532                 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11533                 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11534         }
11535         li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11536         li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11537         li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11538         li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11539         if (ch_a_v == ch_b_v)
11540         {
11541                 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11542                 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11543         }
11544         else
11545         {
11546                 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11547                 {
11548                         for (i = 0; i < li_total_channels; i++)
11549                         {
11550                                 if (i != ch_a_v)
11551                                         li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11552                         }
11553                 }
11554                 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11555                 {
11556                         for (i = 0; i < li_total_channels; i++)
11557                         {
11558                                 if (i != ch_a_s)
11559                                         li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11560                         }
11561                 }
11562                 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11563                 {
11564                         for (i = 0; i < li_total_channels; i++)
11565                         {
11566                                 if (i != ch_a_v)
11567                                         li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11568                         }
11569                 }
11570                 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11571                 {
11572                         for (i = 0; i < li_total_channels; i++)
11573                         {
11574                                 if (i != ch_a_s)
11575                                         li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11576                         }
11577                 }
11578         }
11579         if (li_flags & LI_FLAG_CONFERENCE_A_B)
11580         {
11581                 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11582                 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11583                 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11584                 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11585         }
11586         if (li_flags & LI_FLAG_CONFERENCE_B_A)
11587         {
11588                 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11589                 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11590                 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11591                 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11592         }
11593         if (li_flags & LI_FLAG_MONITOR_A)
11594         {
11595                 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11596                 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11597         }
11598         if (li_flags & LI_FLAG_MONITOR_B)
11599         {
11600                 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11601                 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11602         }
11603         if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11604         {
11605                 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11606                 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11607         }
11608         if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11609         {
11610                 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11611                 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11612         }
11613         if (li_flags & LI_FLAG_MIX_A)
11614         {
11615                 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11616                 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11617         }
11618         if (li_flags & LI_FLAG_MIX_B)
11619         {
11620                 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11621                 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11622         }
11623         if (ch_a_v != ch_a_s)
11624         {
11625                 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11626                 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11627         }
11628         if (ch_b_v != ch_b_s)
11629         {
11630                 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11631                 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11632         }
11633 }
11634
11635
11636 static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11637                                dword plci_b_id, byte connect, dword li_flags)
11638 {
11639         word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11640         PLCI *plci_b;
11641         DIVA_CAPI_ADAPTER *a_b;
11642
11643         a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11644         plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11645         ch_a = a->li_base + (plci->li_bchannel_id - 1);
11646         if (!a->li_pri && (plci->tel == ADV_VOICE)
11647             && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11648         {
11649                 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11650                 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11651                         a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11652         }
11653         else
11654         {
11655                 ch_a_v = ch_a;
11656                 ch_a_s = ch_a;
11657         }
11658         ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11659         if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11660             && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11661         {
11662                 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11663                 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11664                         a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11665         }
11666         else
11667         {
11668                 ch_b_v = ch_b;
11669                 ch_b_s = ch_b;
11670         }
11671         if (connect)
11672         {
11673                 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11674                 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11675                 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11676                 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11677                 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11678                 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11679         }
11680         li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11681         li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11682         li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11683         li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11684         li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11685         li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11686         li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11687         li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11688         if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11689         {
11690                 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11691                 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11692                 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11693                 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11694         }
11695         if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11696         {
11697                 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11698                 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11699                 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11700                 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11701         }
11702         if (li_flags & LI2_FLAG_MONITOR_B)
11703         {
11704                 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11705                 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11706         }
11707         if (li_flags & LI2_FLAG_MIX_B)
11708         {
11709                 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11710                 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11711         }
11712         if (li_flags & LI2_FLAG_MONITOR_X)
11713                 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11714         if (li_flags & LI2_FLAG_MIX_X)
11715                 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11716         if (li_flags & LI2_FLAG_LOOP_B)
11717         {
11718                 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11719                 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11720                 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11721                 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11722         }
11723         if (li_flags & LI2_FLAG_LOOP_PC)
11724                 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11725         if (li_flags & LI2_FLAG_LOOP_X)
11726                 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11727         if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11728                 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11729         if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11730                 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11731         if (ch_a_v != ch_a_s)
11732         {
11733                 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11734                 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11735         }
11736         if (ch_b_v != ch_b_s)
11737         {
11738                 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11739                 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11740         }
11741 }
11742
11743
11744 static word li_check_main_plci(dword Id, PLCI *plci)
11745 {
11746         if (plci == NULL)
11747         {
11748                 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11749                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11750                 return (_WRONG_IDENTIFIER);
11751         }
11752         if (!plci->State
11753             || !plci->NL.Id || plci->nl_remove_id
11754             || (plci->li_bchannel_id == 0))
11755         {
11756                 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11757                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11758                 return (_WRONG_STATE);
11759         }
11760         li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11761         return (GOOD);
11762 }
11763
11764
11765 static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11766                              dword plci_b_id, word plci_b_write_pos, byte *p_result)
11767 {
11768         byte ctlr_b;
11769         PLCI *plci_b;
11770
11771         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11772              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11773         {
11774                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11775                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11776                 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11777                 return (NULL);
11778         }
11779         ctlr_b = 0;
11780         if ((plci_b_id & 0x7f) != 0)
11781         {
11782                 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11783                 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11784                         ctlr_b = 0;
11785         }
11786         if ((ctlr_b == 0)
11787             || (((plci_b_id >> 8) & 0xff) == 0)
11788             || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11789         {
11790                 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11791                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11792                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11793                 return (NULL);
11794         }
11795         plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11796         if (!plci_b->State
11797             || !plci_b->NL.Id || plci_b->nl_remove_id
11798             || (plci_b->li_bchannel_id == 0))
11799         {
11800                 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11801                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11802                 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11803                 return (NULL);
11804         }
11805         li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11806         if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11807             ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11808             && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11809                 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11810         {
11811                 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11812                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11813                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11814                 return (NULL);
11815         }
11816         if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11817                                                           (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11818         {
11819                 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11820                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11821                 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11822                 return (NULL);
11823         }
11824         return (plci_b);
11825 }
11826
11827
11828 static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11829                               dword plci_b_id, word plci_b_write_pos, byte *p_result)
11830 {
11831         byte ctlr_b;
11832         PLCI *plci_b;
11833
11834         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11835              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11836         {
11837                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11838                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11839                 PUT_WORD(p_result, _WRONG_STATE);
11840                 return (NULL);
11841         }
11842         ctlr_b = 0;
11843         if ((plci_b_id & 0x7f) != 0)
11844         {
11845                 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11846                 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11847                         ctlr_b = 0;
11848         }
11849         if ((ctlr_b == 0)
11850             || (((plci_b_id >> 8) & 0xff) == 0)
11851             || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11852         {
11853                 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11854                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11855                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11856                 return (NULL);
11857         }
11858         plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11859         if (!plci_b->State
11860             || !plci_b->NL.Id || plci_b->nl_remove_id
11861             || (plci_b->li_bchannel_id == 0)
11862             || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11863         {
11864                 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11865                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11866                 PUT_WORD(p_result, _WRONG_STATE);
11867                 return (NULL);
11868         }
11869         if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11870             ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11871             && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11872                 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11873         {
11874                 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11875                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11876                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11877                 return (NULL);
11878         }
11879         if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11880                                                           (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11881         {
11882                 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11883                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11884                 PUT_WORD(p_result, _WRONG_STATE);
11885                 return (NULL);
11886         }
11887         return (plci_b);
11888 }
11889
11890
11891 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
11892 {
11893         word Info;
11894         word i;
11895         dword d, li_flags, plci_b_id;
11896         PLCI *plci_b;
11897         API_PARSE li_parms[3];
11898         API_PARSE li_req_parms[3];
11899         API_PARSE li_participant_struct[2];
11900         API_PARSE li_participant_parms[3];
11901         word participant_parms_pos;
11902         byte result_buffer[32];
11903         byte *result;
11904         word result_pos;
11905         word plci_b_write_pos;
11906
11907         dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
11908                         UnMapId(Id), (char *)(FILE_), __LINE__));
11909
11910         Info = GOOD;
11911         result = result_buffer;
11912         result_buffer[0] = 0;
11913         if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
11914         {
11915                 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
11916                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11917                 Info = _FACILITY_NOT_SUPPORTED;
11918         }
11919         else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
11920         {
11921                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
11922                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11923                 Info = _WRONG_MESSAGE_FORMAT;
11924         }
11925         else
11926         {
11927                 result_buffer[0] = 3;
11928                 PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
11929                 result_buffer[3] = 0;
11930                 switch (GET_WORD(li_parms[0].info))
11931                 {
11932                 case LI_GET_SUPPORTED_SERVICES:
11933                         if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
11934                         {
11935                                 result_buffer[0] = 17;
11936                                 result_buffer[3] = 14;
11937                                 PUT_WORD(&result_buffer[4], GOOD);
11938                                 d = 0;
11939                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
11940                                         d |= LI_CONFERENCING_SUPPORTED;
11941                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
11942                                         d |= LI_MONITORING_SUPPORTED;
11943                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
11944                                         d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
11945                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11946                                         d |= LI_CROSS_CONTROLLER_SUPPORTED;
11947                                 PUT_DWORD(&result_buffer[6], d);
11948                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11949                                 {
11950                                         d = 0;
11951                                         for (i = 0; i < li_total_channels; i++)
11952                                         {
11953                                                 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11954                                                     && (li_config_table[i].adapter->li_pri
11955                                                         || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
11956                                                 {
11957                                                         d++;
11958                                                 }
11959                                         }
11960                                 }
11961                                 else
11962                                 {
11963                                         d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
11964                                 }
11965                                 PUT_DWORD(&result_buffer[10], d / 2);
11966                                 PUT_DWORD(&result_buffer[14], d);
11967                         }
11968                         else
11969                         {
11970                                 result_buffer[0] = 25;
11971                                 result_buffer[3] = 22;
11972                                 PUT_WORD(&result_buffer[4], GOOD);
11973                                 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
11974                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
11975                                         d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
11976                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
11977                                         d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
11978                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
11979                                         d |= LI2_PC_LOOPING_SUPPORTED;
11980                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11981                                         d |= LI2_CROSS_CONTROLLER_SUPPORTED;
11982                                 PUT_DWORD(&result_buffer[6], d);
11983                                 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
11984                                 PUT_DWORD(&result_buffer[10], d / 2);
11985                                 PUT_DWORD(&result_buffer[14], d - 1);
11986                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11987                                 {
11988                                         d = 0;
11989                                         for (i = 0; i < li_total_channels; i++)
11990                                         {
11991                                                 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11992                                                     && (li_config_table[i].adapter->li_pri
11993                                                         || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
11994                                                 {
11995                                                         d++;
11996                                                 }
11997                                         }
11998                                 }
11999                                 PUT_DWORD(&result_buffer[18], d / 2);
12000                                 PUT_DWORD(&result_buffer[22], d - 1);
12001                         }
12002                         break;
12003
12004                 case LI_REQ_CONNECT:
12005                         if (li_parms[1].length == 8)
12006                         {
12007                                 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12008                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12009                                 {
12010                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12011                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12012                                         Info = _WRONG_MESSAGE_FORMAT;
12013                                         break;
12014                                 }
12015                                 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12016                                 li_flags = GET_DWORD(li_req_parms[1].info);
12017                                 Info = li_check_main_plci(Id, plci);
12018                                 result_buffer[0] = 9;
12019                                 result_buffer[3] = 6;
12020                                 PUT_DWORD(&result_buffer[4], plci_b_id);
12021                                 PUT_WORD(&result_buffer[8], GOOD);
12022                                 if (Info != GOOD)
12023                                         break;
12024                                 result = plci->saved_msg.info;
12025                                 for (i = 0; i <= result_buffer[0]; i++)
12026                                         result[i] = result_buffer[i];
12027                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12028                                 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12029                                 if (plci_b == NULL)
12030                                         break;
12031                                 li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12032                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12033                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12034                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12035                         }
12036                         else
12037                         {
12038                                 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12039                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12040                                 {
12041                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12042                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12043                                         Info = _WRONG_MESSAGE_FORMAT;
12044                                         break;
12045                                 }
12046                                 li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12047                                 Info = li_check_main_plci(Id, plci);
12048                                 result_buffer[0] = 7;
12049                                 result_buffer[3] = 4;
12050                                 PUT_WORD(&result_buffer[4], Info);
12051                                 result_buffer[6] = 0;
12052                                 if (Info != GOOD)
12053                                         break;
12054                                 result = plci->saved_msg.info;
12055                                 for (i = 0; i <= result_buffer[0]; i++)
12056                                         result[i] = result_buffer[i];
12057                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12058                                 participant_parms_pos = 0;
12059                                 result_pos = 7;
12060                                 li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12061                                 while (participant_parms_pos < li_req_parms[1].length)
12062                                 {
12063                                         result[result_pos] = 6;
12064                                         result_pos += 7;
12065                                         PUT_DWORD(&result[result_pos - 6], 0);
12066                                         PUT_WORD(&result[result_pos - 2], GOOD);
12067                                         if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12068                                                       (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12069                                         {
12070                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12071                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12072                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12073                                                 break;
12074                                         }
12075                                         if (api_parse(&li_participant_struct[0].info[1],
12076                                                       li_participant_struct[0].length, "dd", li_participant_parms))
12077                                         {
12078                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12079                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12080                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12081                                                 break;
12082                                         }
12083                                         plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12084                                         li_flags = GET_DWORD(li_participant_parms[1].info);
12085                                         PUT_DWORD(&result[result_pos - 6], plci_b_id);
12086                                         if (sizeof(result) - result_pos < 7)
12087                                         {
12088                                                 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12089                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12090                                                 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12091                                                 break;
12092                                         }
12093                                         plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12094                                         if (plci_b != NULL)
12095                                         {
12096                                                 li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12097                                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12098                                                         ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12099                                                                       LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12100                                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12101                                         }
12102                                         participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12103                                                                        (&li_req_parms[1].info[1]));
12104                                 }
12105                                 result[0] = (byte)(result_pos - 1);
12106                                 result[3] = (byte)(result_pos - 4);
12107                                 result[6] = (byte)(result_pos - 7);
12108                                 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12109                                 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12110                                     || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12111                                 {
12112                                         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12113                                         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12114                                 }
12115                                 else
12116                                         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12117                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12118                         }
12119                         mixer_calculate_coefs(a);
12120                         plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12121                         mixer_notify_update(plci, true);
12122                         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12123                               "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12124                         plci->command = 0;
12125                         plci->li_cmd = GET_WORD(li_parms[0].info);
12126                         start_internal_command(Id, plci, mixer_command);
12127                         return (false);
12128
12129                 case LI_REQ_DISCONNECT:
12130                         if (li_parms[1].length == 4)
12131                         {
12132                                 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12133                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12134                                 {
12135                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12136                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12137                                         Info = _WRONG_MESSAGE_FORMAT;
12138                                         break;
12139                                 }
12140                                 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12141                                 Info = li_check_main_plci(Id, plci);
12142                                 result_buffer[0] = 9;
12143                                 result_buffer[3] = 6;
12144                                 PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12145                                 PUT_WORD(&result_buffer[8], GOOD);
12146                                 if (Info != GOOD)
12147                                         break;
12148                                 result = plci->saved_msg.info;
12149                                 for (i = 0; i <= result_buffer[0]; i++)
12150                                         result[i] = result_buffer[i];
12151                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12152                                 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12153                                 if (plci_b == NULL)
12154                                         break;
12155                                 li_update_connect(Id, a, plci, plci_b_id, false, 0);
12156                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12157                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12158                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12159                         }
12160                         else
12161                         {
12162                                 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12163                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12164                                 {
12165                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12166                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12167                                         Info = _WRONG_MESSAGE_FORMAT;
12168                                         break;
12169                                 }
12170                                 Info = li_check_main_plci(Id, plci);
12171                                 result_buffer[0] = 7;
12172                                 result_buffer[3] = 4;
12173                                 PUT_WORD(&result_buffer[4], Info);
12174                                 result_buffer[6] = 0;
12175                                 if (Info != GOOD)
12176                                         break;
12177                                 result = plci->saved_msg.info;
12178                                 for (i = 0; i <= result_buffer[0]; i++)
12179                                         result[i] = result_buffer[i];
12180                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12181                                 participant_parms_pos = 0;
12182                                 result_pos = 7;
12183                                 while (participant_parms_pos < li_req_parms[0].length)
12184                                 {
12185                                         result[result_pos] = 6;
12186                                         result_pos += 7;
12187                                         PUT_DWORD(&result[result_pos - 6], 0);
12188                                         PUT_WORD(&result[result_pos - 2], GOOD);
12189                                         if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12190                                                       (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12191                                         {
12192                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12193                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12194                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12195                                                 break;
12196                                         }
12197                                         if (api_parse(&li_participant_struct[0].info[1],
12198                                                       li_participant_struct[0].length, "d", li_participant_parms))
12199                                         {
12200                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12201                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12202                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12203                                                 break;
12204                                         }
12205                                         plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12206                                         PUT_DWORD(&result[result_pos - 6], plci_b_id);
12207                                         if (sizeof(result) - result_pos < 7)
12208                                         {
12209                                                 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12210                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12211                                                 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12212                                                 break;
12213                                         }
12214                                         plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12215                                         if (plci_b != NULL)
12216                                         {
12217                                                 li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12218                                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12219                                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12220                                         }
12221                                         participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12222                                                                        (&li_req_parms[0].info[1]));
12223                                 }
12224                                 result[0] = (byte)(result_pos - 1);
12225                                 result[3] = (byte)(result_pos - 4);
12226                                 result[6] = (byte)(result_pos - 7);
12227                                 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12228                                 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12229                                     || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12230                                 {
12231                                         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12232                                         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12233                                 }
12234                                 else
12235                                         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12236                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12237                         }
12238                         mixer_calculate_coefs(a);
12239                         plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12240                         mixer_notify_update(plci, true);
12241                         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12242                               "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12243                         plci->command = 0;
12244                         plci->li_cmd = GET_WORD(li_parms[0].info);
12245                         start_internal_command(Id, plci, mixer_command);
12246                         return (false);
12247
12248                 case LI_REQ_SILENT_UPDATE:
12249                         if (!plci || !plci->State
12250                             || !plci->NL.Id || plci->nl_remove_id
12251                             || (plci->li_bchannel_id == 0)
12252                             || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12253                         {
12254                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12255                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12256                                 return (false);
12257                         }
12258                         plci_b_write_pos = plci->li_plci_b_write_pos;
12259                         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12260                              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12261                         {
12262                                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12263                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12264                                 return (false);
12265                         }
12266                         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12267                         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12268                             || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12269                         {
12270                                 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12271                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12272                         }
12273                         else
12274                                 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12275                         plci->li_plci_b_write_pos = plci_b_write_pos;
12276                         plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12277                         plci->command = 0;
12278                         plci->li_cmd = GET_WORD(li_parms[0].info);
12279                         start_internal_command(Id, plci, mixer_command);
12280                         return (false);
12281
12282                 default:
12283                         dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12284                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12285                         Info = _FACILITY_NOT_SUPPORTED;
12286                 }
12287         }
12288         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12289               "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12290         return (false);
12291 }
12292
12293
12294 static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12295 {
12296         dword d;
12297         byte result[12];
12298
12299         dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12300                         UnMapId(Id), (char *)(FILE_), __LINE__));
12301
12302         if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12303         {
12304                 do
12305                 {
12306                         d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12307                         if (!(d & LI_PLCI_B_SKIP_FLAG))
12308                         {
12309                                 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12310                                 {
12311                                         if (d & LI_PLCI_B_DISC_FLAG)
12312                                         {
12313                                                 result[0] = 5;
12314                                                 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12315                                                 result[3] = 2;
12316                                                 PUT_WORD(&result[4], _LI_USER_INITIATED);
12317                                         }
12318                                         else
12319                                         {
12320                                                 result[0] = 7;
12321                                                 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12322                                                 result[3] = 4;
12323                                                 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12324                                         }
12325                                 }
12326                                 else
12327                                 {
12328                                         if (d & LI_PLCI_B_DISC_FLAG)
12329                                         {
12330                                                 result[0] = 9;
12331                                                 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12332                                                 result[3] = 6;
12333                                                 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12334                                                 PUT_WORD(&result[8], _LI_USER_INITIATED);
12335                                         }
12336                                         else
12337                                         {
12338                                                 result[0] = 7;
12339                                                 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12340                                                 result[3] = 4;
12341                                                 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12342                                         }
12343                                 }
12344                                 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12345                                       "ws", SELECTOR_LINE_INTERCONNECT, result);
12346                         }
12347                         plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12348                                 0 : plci->li_plci_b_read_pos + 1;
12349                 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12350         }
12351 }
12352
12353
12354 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12355 {
12356         word i, j, ch;
12357         struct xconnect_transfer_address_s s,   *p;
12358         DIVA_CAPI_ADAPTER *a;
12359
12360         dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12361                         UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12362
12363         a = plci->adapter;
12364         i = 1;
12365         for (i = 1; i < length; i += 16)
12366         {
12367                 s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12368                 s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12369                 s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12370                 ch = msg[i + 12] | (msg[i + 13] << 8);
12371                 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12372                 if (!a->li_pri && (plci->li_bchannel_id == 2))
12373                         j = 1 - j;
12374                 j += a->li_base;
12375                 if (ch & XCONNECT_CHANNEL_PORT_PC)
12376                         p = &(li_config_table[j].send_pc);
12377                 else
12378                         p = &(li_config_table[j].send_b);
12379                 p->card_address.low = s.card_address.low;
12380                 p->card_address.high = s.card_address.high;
12381                 p->offset = s.offset;
12382                 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12383         }
12384         if (plci->internal_command_queue[0]
12385             && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12386                 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12387                 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12388         {
12389                 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12390                 if (!plci->internal_command)
12391                         next_internal_command(Id, plci);
12392         }
12393         mixer_notify_update(plci, true);
12394 }
12395
12396
12397 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12398 {
12399
12400         dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12401                         UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12402
12403 }
12404
12405
12406 static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12407 {
12408         word plci_b_write_pos;
12409
12410         plci_b_write_pos = plci->li_plci_b_write_pos;
12411         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12412              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12413         {
12414                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12415                                 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12416                                 (char *)(FILE_), __LINE__));
12417                 return (false);
12418         }
12419         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12420         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12421         plci->li_plci_b_write_pos = plci_b_write_pos;
12422         return (true);
12423 }
12424
12425
12426 static void mixer_remove(PLCI *plci)
12427 {
12428         DIVA_CAPI_ADAPTER *a;
12429         PLCI *notify_plci;
12430         dword plci_b_id;
12431         word i, j;
12432
12433         dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12434                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12435                         (char *)(FILE_), __LINE__));
12436
12437         a = plci->adapter;
12438         plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12439         if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12440         {
12441                 if ((plci->li_bchannel_id != 0)
12442                     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12443                 {
12444                         i = a->li_base + (plci->li_bchannel_id - 1);
12445                         if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12446                         {
12447                                 for (j = 0; j < li_total_channels; j++)
12448                                 {
12449                                         if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12450                                             || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12451                                         {
12452                                                 notify_plci = li_config_table[j].plci;
12453                                                 if ((notify_plci != NULL)
12454                                                     && (notify_plci != plci)
12455                                                     && (notify_plci->appl != NULL)
12456                                                     && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12457                                                     && (notify_plci->State)
12458                                                     && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12459                                                 {
12460                                                         mixer_notify_source_removed(notify_plci, plci_b_id);
12461                                                 }
12462                                         }
12463                                 }
12464                                 mixer_clear_config(plci);
12465                                 mixer_calculate_coefs(a);
12466                                 mixer_notify_update(plci, true);
12467                         }
12468                         li_config_table[i].plci = NULL;
12469                         plci->li_bchannel_id = 0;
12470                 }
12471         }
12472 }
12473
12474
12475 /*------------------------------------------------------------------*/
12476 /* Echo canceller facilities                                        */
12477 /*------------------------------------------------------------------*/
12478
12479
12480 static void ec_write_parameters(PLCI *plci)
12481 {
12482         word w;
12483         byte parameter_buffer[6];
12484
12485         dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12486                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12487                         (char *)(FILE_), __LINE__));
12488
12489         parameter_buffer[0] = 5;
12490         parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12491         PUT_WORD(&parameter_buffer[2], plci->ec_idi_options);
12492         plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12493         w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12494         PUT_WORD(&parameter_buffer[4], w);
12495         add_p(plci, FTY, parameter_buffer);
12496         sig_req(plci, TEL_CTRL, 0);
12497         send_req(plci);
12498 }
12499
12500
12501 static void ec_clear_config(PLCI *plci)
12502 {
12503
12504         dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12505                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12506                         (char *)(FILE_), __LINE__));
12507
12508         plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12509                 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12510         plci->ec_tail_length = 0;
12511 }
12512
12513
12514 static void ec_prepare_switch(dword Id, PLCI *plci)
12515 {
12516
12517         dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12518                         UnMapId(Id), (char *)(FILE_), __LINE__));
12519
12520 }
12521
12522
12523 static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12524 {
12525
12526         dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12527                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12528
12529         return (GOOD);
12530 }
12531
12532
12533 static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12534 {
12535         word Info;
12536
12537         dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12538                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12539
12540         Info = GOOD;
12541         if (plci->B1_facilities & B1_FACILITY_EC)
12542         {
12543                 switch (plci->adjust_b_state)
12544                 {
12545                 case ADJUST_B_RESTORE_EC_1:
12546                         plci->internal_command = plci->adjust_b_command;
12547                         if (plci->sig_req)
12548                         {
12549                                 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12550                                 break;
12551                         }
12552                         ec_write_parameters(plci);
12553                         plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12554                         break;
12555                 case ADJUST_B_RESTORE_EC_2:
12556                         if ((Rc != OK) && (Rc != OK_FC))
12557                         {
12558                                 dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12559                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12560                                 Info = _WRONG_STATE;
12561                                 break;
12562                         }
12563                         break;
12564                 }
12565         }
12566         return (Info);
12567 }
12568
12569
12570 static void ec_command(dword Id, PLCI *plci, byte Rc)
12571 {
12572         word internal_command, Info;
12573         byte result[8];
12574
12575         dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12576                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12577                         plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12578
12579         Info = GOOD;
12580         if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12581         {
12582                 result[0] = 2;
12583                 PUT_WORD(&result[1], EC_SUCCESS);
12584         }
12585         else
12586         {
12587                 result[0] = 5;
12588                 PUT_WORD(&result[1], plci->ec_cmd);
12589                 result[3] = 2;
12590                 PUT_WORD(&result[4], GOOD);
12591         }
12592         internal_command = plci->internal_command;
12593         plci->internal_command = 0;
12594         switch (plci->ec_cmd)
12595         {
12596         case EC_ENABLE_OPERATION:
12597         case EC_FREEZE_COEFFICIENTS:
12598         case EC_RESUME_COEFFICIENT_UPDATE:
12599         case EC_RESET_COEFFICIENTS:
12600                 switch (internal_command)
12601                 {
12602                 default:
12603                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12604                                                                   B1_FACILITY_EC), EC_COMMAND_1);
12605                 case EC_COMMAND_1:
12606                         if (adjust_b_process(Id, plci, Rc) != GOOD)
12607                         {
12608                                 dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12609                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12610                                 Info = _FACILITY_NOT_SUPPORTED;
12611                                 break;
12612                         }
12613                         if (plci->internal_command)
12614                                 return;
12615                 case EC_COMMAND_2:
12616                         if (plci->sig_req)
12617                         {
12618                                 plci->internal_command = EC_COMMAND_2;
12619                                 return;
12620                         }
12621                         plci->internal_command = EC_COMMAND_3;
12622                         ec_write_parameters(plci);
12623                         return;
12624                 case EC_COMMAND_3:
12625                         if ((Rc != OK) && (Rc != OK_FC))
12626                         {
12627                                 dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12628                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12629                                 Info = _FACILITY_NOT_SUPPORTED;
12630                                 break;
12631                         }
12632                         break;
12633                 }
12634                 break;
12635
12636         case EC_DISABLE_OPERATION:
12637                 switch (internal_command)
12638                 {
12639                 default:
12640                 case EC_COMMAND_1:
12641                         if (plci->B1_facilities & B1_FACILITY_EC)
12642                         {
12643                                 if (plci->sig_req)
12644                                 {
12645                                         plci->internal_command = EC_COMMAND_1;
12646                                         return;
12647                                 }
12648                                 plci->internal_command = EC_COMMAND_2;
12649                                 ec_write_parameters(plci);
12650                                 return;
12651                         }
12652                         Rc = OK;
12653                 case EC_COMMAND_2:
12654                         if ((Rc != OK) && (Rc != OK_FC))
12655                         {
12656                                 dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12657                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12658                                 Info = _FACILITY_NOT_SUPPORTED;
12659                                 break;
12660                         }
12661                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12662                                                                   ~B1_FACILITY_EC), EC_COMMAND_3);
12663                 case EC_COMMAND_3:
12664                         if (adjust_b_process(Id, plci, Rc) != GOOD)
12665                         {
12666                                 dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12667                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12668                                 Info = _FACILITY_NOT_SUPPORTED;
12669                                 break;
12670                         }
12671                         if (plci->internal_command)
12672                                 return;
12673                         break;
12674                 }
12675                 break;
12676         }
12677         sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12678               "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12679               PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12680 }
12681
12682
12683 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
12684 {
12685         word Info;
12686         word opt;
12687         API_PARSE ec_parms[3];
12688         byte result[16];
12689
12690         dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12691                         UnMapId(Id), (char *)(FILE_), __LINE__));
12692
12693         Info = GOOD;
12694         result[0] = 0;
12695         if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12696         {
12697                 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12698                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12699                 Info = _FACILITY_NOT_SUPPORTED;
12700         }
12701         else
12702         {
12703                 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12704                 {
12705                         if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12706                         {
12707                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12708                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12709                                 Info = _WRONG_MESSAGE_FORMAT;
12710                         }
12711                         else
12712                         {
12713                                 if (plci == NULL)
12714                                 {
12715                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12716                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12717                                         Info = _WRONG_IDENTIFIER;
12718                                 }
12719                                 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12720                                 {
12721                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12722                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12723                                         Info = _WRONG_STATE;
12724                                 }
12725                                 else
12726                                 {
12727                                         plci->command = 0;
12728                                         plci->ec_cmd = GET_WORD(ec_parms[0].info);
12729                                         plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12730                                         result[0] = 2;
12731                                         PUT_WORD(&result[1], EC_SUCCESS);
12732                                         if (msg[1].length >= 4)
12733                                         {
12734                                                 opt = GET_WORD(&ec_parms[0].info[2]);
12735                                                 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12736                                                                           LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12737                                                 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12738                                                         plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12739                                                 if (opt & EC_DETECT_DISABLE_TONE)
12740                                                         plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12741                                                 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12742                                                         plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12743                                                 if (msg[1].length >= 6)
12744                                                 {
12745                                                         plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12746                                                 }
12747                                         }
12748                                         switch (plci->ec_cmd)
12749                                         {
12750                                         case EC_ENABLE_OPERATION:
12751                                                 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12752                                                 start_internal_command(Id, plci, ec_command);
12753                                                 return (false);
12754
12755                                         case EC_DISABLE_OPERATION:
12756                                                 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12757                                                         LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12758                                                         LEC_RESET_COEFFICIENTS;
12759                                                 start_internal_command(Id, plci, ec_command);
12760                                                 return (false);
12761
12762                                         case EC_FREEZE_COEFFICIENTS:
12763                                                 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12764                                                 start_internal_command(Id, plci, ec_command);
12765                                                 return (false);
12766
12767                                         case EC_RESUME_COEFFICIENT_UPDATE:
12768                                                 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12769                                                 start_internal_command(Id, plci, ec_command);
12770                                                 return (false);
12771
12772                                         case EC_RESET_COEFFICIENTS:
12773                                                 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12774                                                 start_internal_command(Id, plci, ec_command);
12775                                                 return (false);
12776
12777                                         default:
12778                                                 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12779                                                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12780                                                 PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12781                                         }
12782                                 }
12783                         }
12784                 }
12785                 else
12786                 {
12787                         if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12788                         {
12789                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12790                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12791                                 Info = _WRONG_MESSAGE_FORMAT;
12792                         }
12793                         else
12794                         {
12795                                 if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12796                                 {
12797                                         result[0] = 11;
12798                                         PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12799                                         result[3] = 8;
12800                                         PUT_WORD(&result[4], GOOD);
12801                                         PUT_WORD(&result[6], 0x0007);
12802                                         PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12803                                         PUT_WORD(&result[10], 0);
12804                                 }
12805                                 else if (plci == NULL)
12806                                 {
12807                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12808                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12809                                         Info = _WRONG_IDENTIFIER;
12810                                 }
12811                                 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12812                                 {
12813                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12814                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12815                                         Info = _WRONG_STATE;
12816                                 }
12817                                 else
12818                                 {
12819                                         plci->command = 0;
12820                                         plci->ec_cmd = GET_WORD(ec_parms[0].info);
12821                                         plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12822                                         result[0] = 5;
12823                                         PUT_WORD(&result[1], plci->ec_cmd);
12824                                         result[3] = 2;
12825                                         PUT_WORD(&result[4], GOOD);
12826                                         plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12827                                                                   LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12828                                         plci->ec_tail_length = 0;
12829                                         if (ec_parms[1].length >= 2)
12830                                         {
12831                                                 opt = GET_WORD(&ec_parms[1].info[1]);
12832                                                 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12833                                                         plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12834                                                 if (opt & EC_DETECT_DISABLE_TONE)
12835                                                         plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12836                                                 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12837                                                         plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12838                                                 if (ec_parms[1].length >= 4)
12839                                                 {
12840                                                         plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12841                                                 }
12842                                         }
12843                                         switch (plci->ec_cmd)
12844                                         {
12845                                         case EC_ENABLE_OPERATION:
12846                                                 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12847                                                 start_internal_command(Id, plci, ec_command);
12848                                                 return (false);
12849
12850                                         case EC_DISABLE_OPERATION:
12851                                                 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12852                                                         LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12853                                                         LEC_RESET_COEFFICIENTS;
12854                                                 start_internal_command(Id, plci, ec_command);
12855                                                 return (false);
12856
12857                                         default:
12858                                                 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12859                                                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12860                                                 PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12861                                         }
12862                                 }
12863                         }
12864                 }
12865         }
12866         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12867               "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12868               PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12869         return (false);
12870 }
12871
12872
12873 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
12874 {
12875         byte result[8];
12876
12877         dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
12878                         UnMapId(Id), (char *)(FILE_), __LINE__));
12879
12880         if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
12881         {
12882                 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12883                 {
12884                         result[0] = 2;
12885                         PUT_WORD(&result[1], 0);
12886                         switch (msg[1])
12887                         {
12888                         case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
12889                                 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
12890                                 break;
12891                         case LEC_DISABLE_TYPE_REVERSED_2100HZ:
12892                                 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
12893                                 break;
12894                         case LEC_DISABLE_RELEASED:
12895                                 PUT_WORD(&result[1], EC_BYPASS_RELEASED);
12896                                 break;
12897                         }
12898                 }
12899                 else
12900                 {
12901                         result[0] = 5;
12902                         PUT_WORD(&result[1], EC_BYPASS_INDICATION);
12903                         result[3] = 2;
12904                         PUT_WORD(&result[4], 0);
12905                         switch (msg[1])
12906                         {
12907                         case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
12908                                 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
12909                                 break;
12910                         case LEC_DISABLE_TYPE_REVERSED_2100HZ:
12911                                 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
12912                                 break;
12913                         case LEC_DISABLE_RELEASED:
12914                                 PUT_WORD(&result[4], EC_BYPASS_RELEASED);
12915                                 break;
12916                         }
12917                 }
12918                 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12919                       PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12920         }
12921 }
12922
12923
12924
12925 /*------------------------------------------------------------------*/
12926 /* Advanced voice                                                   */
12927 /*------------------------------------------------------------------*/
12928
12929 static void adv_voice_write_coefs(PLCI *plci, word write_command)
12930 {
12931         DIVA_CAPI_ADAPTER *a;
12932         word i;
12933         byte *p;
12934
12935         word w, n, j, k;
12936         byte ch_map[MIXER_CHANNELS_BRI];
12937
12938         byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
12939
12940         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
12941                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12942                         (char *)(FILE_), __LINE__, write_command));
12943
12944         a = plci->adapter;
12945         p = coef_buffer + 1;
12946         *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
12947         i = 0;
12948         while (i + sizeof(word) <= a->adv_voice_coef_length)
12949         {
12950                 PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
12951                 p += 2;
12952                 i += 2;
12953         }
12954         while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
12955         {
12956                 PUT_WORD(p, 0x8000);
12957                 p += 2;
12958                 i += 2;
12959         }
12960
12961         if (!a->li_pri && (plci->li_bchannel_id == 0))
12962         {
12963                 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
12964                 {
12965                         plci->li_bchannel_id = 1;
12966                         li_config_table[a->li_base].plci = plci;
12967                         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
12968                                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12969                                         (char *)(FILE_), __LINE__, plci->li_bchannel_id));
12970                 }
12971                 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
12972                 {
12973                         plci->li_bchannel_id = 2;
12974                         li_config_table[a->li_base + 1].plci = plci;
12975                         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
12976                                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12977                                         (char *)(FILE_), __LINE__, plci->li_bchannel_id));
12978                 }
12979         }
12980         if (!a->li_pri && (plci->li_bchannel_id != 0)
12981             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12982         {
12983                 i = a->li_base + (plci->li_bchannel_id - 1);
12984                 switch (write_command)
12985                 {
12986                 case ADV_VOICE_WRITE_ACTIVATION:
12987                         j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
12988                         k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
12989                         if (!(plci->B1_facilities & B1_FACILITY_MIXER))
12990                         {
12991                                 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
12992                                 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
12993                         }
12994                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
12995                         {
12996                                 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
12997                                 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
12998                                 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
12999                                 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13000                         }
13001                         mixer_calculate_coefs(a);
13002                         li_config_table[i].curchnl = li_config_table[i].channel;
13003                         li_config_table[j].curchnl = li_config_table[j].channel;
13004                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13005                                 li_config_table[k].curchnl = li_config_table[k].channel;
13006                         break;
13007
13008                 case ADV_VOICE_WRITE_DEACTIVATION:
13009                         for (j = 0; j < li_total_channels; j++)
13010                         {
13011                                 li_config_table[i].flag_table[j] = 0;
13012                                 li_config_table[j].flag_table[i] = 0;
13013                         }
13014                         k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13015                         for (j = 0; j < li_total_channels; j++)
13016                         {
13017                                 li_config_table[k].flag_table[j] = 0;
13018                                 li_config_table[j].flag_table[k] = 0;
13019                         }
13020                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13021                         {
13022                                 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13023                                 for (j = 0; j < li_total_channels; j++)
13024                                 {
13025                                         li_config_table[k].flag_table[j] = 0;
13026                                         li_config_table[j].flag_table[k] = 0;
13027                                 }
13028                         }
13029                         mixer_calculate_coefs(a);
13030                         break;
13031                 }
13032                 if (plci->B1_facilities & B1_FACILITY_MIXER)
13033                 {
13034                         w = 0;
13035                         if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13036                                 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13037                         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13038                                 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13039                         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13040                                 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13041                         *(p++) = (byte) w;
13042                         *(p++) = (byte)(w >> 8);
13043                         for (j = 0; j < sizeof(ch_map); j += 2)
13044                         {
13045                                 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13046                                 ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13047                         }
13048                         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13049                         {
13050                                 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13051                                 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13052                                 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13053                                 {
13054                                         *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13055                                         w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13056                                         li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13057                                 }
13058                                 else
13059                                 {
13060                                         *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13061                                                 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13062                                 }
13063                         }
13064                 }
13065                 else
13066                 {
13067                         for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13068                                 *(p++) = a->adv_voice_coef_buffer[i];
13069                 }
13070         }
13071         else
13072
13073         {
13074                 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13075                         *(p++) = a->adv_voice_coef_buffer[i];
13076         }
13077         coef_buffer[0] = (p - coef_buffer) - 1;
13078         add_p(plci, FTY, coef_buffer);
13079         sig_req(plci, TEL_CTRL, 0);
13080         send_req(plci);
13081 }
13082
13083
13084 static void adv_voice_clear_config(PLCI *plci)
13085 {
13086         DIVA_CAPI_ADAPTER *a;
13087
13088         word i, j;
13089
13090
13091         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13092                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13093                         (char *)(FILE_), __LINE__));
13094
13095         a = plci->adapter;
13096         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13097         {
13098                 a->adv_voice_coef_length = 0;
13099
13100                 if (!a->li_pri && (plci->li_bchannel_id != 0)
13101                     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13102                 {
13103                         i = a->li_base + (plci->li_bchannel_id - 1);
13104                         li_config_table[i].curchnl = 0;
13105                         li_config_table[i].channel = 0;
13106                         li_config_table[i].chflags = 0;
13107                         for (j = 0; j < li_total_channels; j++)
13108                         {
13109                                 li_config_table[i].flag_table[j] = 0;
13110                                 li_config_table[j].flag_table[i] = 0;
13111                                 li_config_table[i].coef_table[j] = 0;
13112                                 li_config_table[j].coef_table[i] = 0;
13113                         }
13114                         li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13115                         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13116                         li_config_table[i].curchnl = 0;
13117                         li_config_table[i].channel = 0;
13118                         li_config_table[i].chflags = 0;
13119                         for (j = 0; j < li_total_channels; j++)
13120                         {
13121                                 li_config_table[i].flag_table[j] = 0;
13122                                 li_config_table[j].flag_table[i] = 0;
13123                                 li_config_table[i].coef_table[j] = 0;
13124                                 li_config_table[j].coef_table[i] = 0;
13125                         }
13126                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13127                         {
13128                                 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13129                                 li_config_table[i].curchnl = 0;
13130                                 li_config_table[i].channel = 0;
13131                                 li_config_table[i].chflags = 0;
13132                                 for (j = 0; j < li_total_channels; j++)
13133                                 {
13134                                         li_config_table[i].flag_table[j] = 0;
13135                                         li_config_table[j].flag_table[i] = 0;
13136                                         li_config_table[i].coef_table[j] = 0;
13137                                         li_config_table[j].coef_table[i] = 0;
13138                                 }
13139                         }
13140                 }
13141
13142         }
13143 }
13144
13145
13146 static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13147 {
13148
13149         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13150                         UnMapId(Id), (char *)(FILE_), __LINE__));
13151
13152 }
13153
13154
13155 static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13156 {
13157
13158         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13159                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13160
13161         return (GOOD);
13162 }
13163
13164
13165 static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13166 {
13167         DIVA_CAPI_ADAPTER *a;
13168         word Info;
13169
13170         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13171                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13172
13173         Info = GOOD;
13174         a = plci->adapter;
13175         if ((plci->B1_facilities & B1_FACILITY_VOICE)
13176             && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13177         {
13178                 switch (plci->adjust_b_state)
13179                 {
13180                 case ADJUST_B_RESTORE_VOICE_1:
13181                         plci->internal_command = plci->adjust_b_command;
13182                         if (plci->sig_req)
13183                         {
13184                                 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13185                                 break;
13186                         }
13187                         adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13188                         plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13189                         break;
13190                 case ADJUST_B_RESTORE_VOICE_2:
13191                         if ((Rc != OK) && (Rc != OK_FC))
13192                         {
13193                                 dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13194                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13195                                 Info = _WRONG_STATE;
13196                                 break;
13197                         }
13198                         break;
13199                 }
13200         }
13201         return (Info);
13202 }
13203
13204
13205
13206
13207 /*------------------------------------------------------------------*/
13208 /* B1 resource switching                                            */
13209 /*------------------------------------------------------------------*/
13210
13211 static byte b1_facilities_table[] =
13212 {
13213         0x00,  /* 0  No bchannel resources      */
13214         0x00,  /* 1  Codec (automatic law)      */
13215         0x00,  /* 2  Codec (A-law)              */
13216         0x00,  /* 3  Codec (y-law)              */
13217         0x00,  /* 4  HDLC for X.21              */
13218         0x00,  /* 5  HDLC                       */
13219         0x00,  /* 6  External Device 0          */
13220         0x00,  /* 7  External Device 1          */
13221         0x00,  /* 8  HDLC 56k                   */
13222         0x00,  /* 9  Transparent                */
13223         0x00,  /* 10 Loopback to network        */
13224         0x00,  /* 11 Test pattern to net        */
13225         0x00,  /* 12 Rate adaptation sync       */
13226         0x00,  /* 13 Rate adaptation async      */
13227         0x00,  /* 14 R-Interface                */
13228         0x00,  /* 15 HDLC 128k leased line      */
13229         0x00,  /* 16 FAX                        */
13230         0x00,  /* 17 Modem async                */
13231         0x00,  /* 18 Modem sync HDLC            */
13232         0x00,  /* 19 V.110 async HDLC           */
13233         0x12,  /* 20 Adv voice (Trans,mixer)    */
13234         0x00,  /* 21 Codec connected to IC      */
13235         0x0c,  /* 22 Trans,DTMF                 */
13236         0x1e,  /* 23 Trans,DTMF+mixer           */
13237         0x1f,  /* 24 Trans,DTMF+mixer+local     */
13238         0x13,  /* 25 Trans,mixer+local          */
13239         0x12,  /* 26 HDLC,mixer                 */
13240         0x12,  /* 27 HDLC 56k,mixer             */
13241         0x2c,  /* 28 Trans,LEC+DTMF             */
13242         0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13243         0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13244         0x2c,  /* 31 RTP,LEC+DTMF               */
13245         0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13246         0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13247         0x00,  /* 34 Signaling task             */
13248         0x00,  /* 35 PIAFS                      */
13249         0x0c,  /* 36 Trans,DTMF+TONE            */
13250         0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13251         0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13252 };
13253
13254
13255 static word get_b1_facilities(PLCI *plci, byte b1_resource)
13256 {
13257         word b1_facilities;
13258
13259         b1_facilities = b1_facilities_table[b1_resource];
13260         if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13261         {
13262
13263                 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13264                       || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13265
13266                 {
13267                         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13268                                 b1_facilities |= B1_FACILITY_DTMFX;
13269                         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13270                                 b1_facilities |= B1_FACILITY_DTMFR;
13271                 }
13272         }
13273         if ((b1_resource == 17) || (b1_resource == 18))
13274         {
13275                 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13276                         b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13277         }
13278 /*
13279   dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13280   (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13281   (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13282 */
13283         return (b1_facilities);
13284 }
13285
13286
13287 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13288 {
13289         byte b;
13290
13291         switch (b1_resource)
13292         {
13293         case 5:
13294         case 26:
13295                 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13296                         b = 26;
13297                 else
13298                         b = 5;
13299                 break;
13300
13301         case 8:
13302         case 27:
13303                 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13304                         b = 27;
13305                 else
13306                         b = 8;
13307                 break;
13308
13309         case 9:
13310         case 20:
13311         case 22:
13312         case 23:
13313         case 24:
13314         case 25:
13315         case 28:
13316         case 29:
13317         case 30:
13318         case 36:
13319         case 37:
13320         case 38:
13321                 if (b1_facilities & B1_FACILITY_EC)
13322                 {
13323                         if (b1_facilities & B1_FACILITY_LOCAL)
13324                                 b = 30;
13325                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13326                                 b = 29;
13327                         else
13328                                 b = 28;
13329                 }
13330
13331                 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13332                          && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13333                              || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13334                 {
13335                         if (b1_facilities & B1_FACILITY_LOCAL)
13336                                 b = 38;
13337                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13338                                 b = 37;
13339                         else
13340                                 b = 36;
13341                 }
13342
13343                 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13344                           && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13345                          || ((b1_facilities & B1_FACILITY_DTMFR)
13346                              && ((b1_facilities & B1_FACILITY_MIXER)
13347                                  || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13348                          || ((b1_facilities & B1_FACILITY_DTMFX)
13349                              && ((b1_facilities & B1_FACILITY_MIXER)
13350                                  || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13351                 {
13352                         if (b1_facilities & B1_FACILITY_LOCAL)
13353                                 b = 24;
13354                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13355                                 b = 23;
13356                         else
13357                                 b = 22;
13358                 }
13359                 else
13360                 {
13361                         if (b1_facilities & B1_FACILITY_LOCAL)
13362                                 b = 25;
13363                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13364                                 b = 20;
13365                         else
13366                                 b = 9;
13367                 }
13368                 break;
13369
13370         case 31:
13371         case 32:
13372         case 33:
13373                 if (b1_facilities & B1_FACILITY_LOCAL)
13374                         b = 33;
13375                 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13376                         b = 32;
13377                 else
13378                         b = 31;
13379                 break;
13380
13381         default:
13382                 b = b1_resource;
13383         }
13384         dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13385                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13386                         (char *)(FILE_), __LINE__,
13387                         b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13388         return (b);
13389 }
13390
13391
13392 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13393 {
13394         word removed_facilities;
13395
13396         dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13397                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13398                         (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13399                         new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13400
13401         new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13402         removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13403
13404         if (removed_facilities & B1_FACILITY_EC)
13405                 ec_clear_config(plci);
13406
13407
13408         if (removed_facilities & B1_FACILITY_DTMFR)
13409         {
13410                 dtmf_rec_clear_config(plci);
13411                 dtmf_parameter_clear_config(plci);
13412         }
13413         if (removed_facilities & B1_FACILITY_DTMFX)
13414                 dtmf_send_clear_config(plci);
13415
13416
13417         if (removed_facilities & B1_FACILITY_MIXER)
13418                 mixer_clear_config(plci);
13419
13420         if (removed_facilities & B1_FACILITY_VOICE)
13421                 adv_voice_clear_config(plci);
13422         plci->B1_facilities = new_b1_facilities;
13423 }
13424
13425
13426 static void adjust_b_clear(PLCI *plci)
13427 {
13428
13429         dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13430                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13431                         (char *)(FILE_), __LINE__));
13432
13433         plci->adjust_b_restore = false;
13434 }
13435
13436
13437 static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13438 {
13439         word Info;
13440         byte b1_resource;
13441         NCCI *ncci_ptr;
13442         API_PARSE bp[2];
13443
13444         dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13445                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13446
13447         Info = GOOD;
13448         switch (plci->adjust_b_state)
13449         {
13450         case ADJUST_B_START:
13451                 if ((plci->adjust_b_parms_msg == NULL)
13452                     && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13453                     && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13454                                                  ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13455                 {
13456                         b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13457                                 0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13458                         if (b1_resource == plci->B1_resource)
13459                         {
13460                                 adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13461                                 break;
13462                         }
13463                         if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13464                         {
13465                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13466                                                 UnMapId(Id), (char *)(FILE_), __LINE__,
13467                                                 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13468                                 Info = _WRONG_STATE;
13469                                 break;
13470                         }
13471                 }
13472                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13473                 {
13474
13475                         mixer_prepare_switch(Id, plci);
13476
13477
13478                         dtmf_prepare_switch(Id, plci);
13479                         dtmf_parameter_prepare_switch(Id, plci);
13480
13481
13482                         ec_prepare_switch(Id, plci);
13483
13484                         adv_voice_prepare_switch(Id, plci);
13485                 }
13486                 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13487                 Rc = OK;
13488         case ADJUST_B_SAVE_MIXER_1:
13489                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13490                 {
13491
13492                         Info = mixer_save_config(Id, plci, Rc);
13493                         if ((Info != GOOD) || plci->internal_command)
13494                                 break;
13495
13496                 }
13497                 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13498                 Rc = OK;
13499         case ADJUST_B_SAVE_DTMF_1:
13500                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13501                 {
13502
13503                         Info = dtmf_save_config(Id, plci, Rc);
13504                         if ((Info != GOOD) || plci->internal_command)
13505                                 break;
13506
13507                 }
13508                 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13509         case ADJUST_B_REMOVE_L23_1:
13510                 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13511                     && plci->NL.Id && !plci->nl_remove_id)
13512                 {
13513                         plci->internal_command = plci->adjust_b_command;
13514                         if (plci->adjust_b_ncci != 0)
13515                         {
13516                                 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13517                                 while (ncci_ptr->data_pending)
13518                                 {
13519                                         plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13520                                         data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13521                                 }
13522                                 while (ncci_ptr->data_ack_pending)
13523                                         data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13524                         }
13525                         nl_req_ncci(plci, REMOVE,
13526                                     (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13527                         send_req(plci);
13528                         plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13529                         break;
13530                 }
13531                 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13532                 Rc = OK;
13533         case ADJUST_B_REMOVE_L23_2:
13534                 if ((Rc != OK) && (Rc != OK_FC))
13535                 {
13536                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13537                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13538                         Info = _WRONG_STATE;
13539                         break;
13540                 }
13541                 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13542                 {
13543                         if (plci_nl_busy(plci))
13544                         {
13545                                 plci->internal_command = plci->adjust_b_command;
13546                                 break;
13547                         }
13548                 }
13549                 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13550                 Rc = OK;
13551         case ADJUST_B_SAVE_EC_1:
13552                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13553                 {
13554
13555                         Info = ec_save_config(Id, plci, Rc);
13556                         if ((Info != GOOD) || plci->internal_command)
13557                                 break;
13558
13559                 }
13560                 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13561                 Rc = OK;
13562         case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13563                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13564                 {
13565
13566                         Info = dtmf_parameter_save_config(Id, plci, Rc);
13567                         if ((Info != GOOD) || plci->internal_command)
13568                                 break;
13569
13570                 }
13571                 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13572                 Rc = OK;
13573         case ADJUST_B_SAVE_VOICE_1:
13574                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13575                 {
13576                         Info = adv_voice_save_config(Id, plci, Rc);
13577                         if ((Info != GOOD) || plci->internal_command)
13578                                 break;
13579                 }
13580                 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13581         case ADJUST_B_SWITCH_L1_1:
13582                 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13583                 {
13584                         if (plci->sig_req)
13585                         {
13586                                 plci->internal_command = plci->adjust_b_command;
13587                                 break;
13588                         }
13589                         if (plci->adjust_b_parms_msg != NULL)
13590                                 api_load_msg(plci->adjust_b_parms_msg, bp);
13591                         else
13592                                 api_load_msg(&plci->B_protocol, bp);
13593                         Info = add_b1(plci, bp,
13594                                       (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13595                                       plci->adjust_b_facilities);
13596                         if (Info != GOOD)
13597                         {
13598                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13599                                                 UnMapId(Id), (char *)(FILE_), __LINE__,
13600                                                 plci->B1_resource, plci->adjust_b_facilities));
13601                                 break;
13602                         }
13603                         plci->internal_command = plci->adjust_b_command;
13604                         sig_req(plci, RESOURCES, 0);
13605                         send_req(plci);
13606                         plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13607                         break;
13608                 }
13609                 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13610                 Rc = OK;
13611         case ADJUST_B_SWITCH_L1_2:
13612                 if ((Rc != OK) && (Rc != OK_FC))
13613                 {
13614                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13615                                         UnMapId(Id), (char *)(FILE_), __LINE__,
13616                                         Rc, plci->B1_resource, plci->adjust_b_facilities));
13617                         Info = _WRONG_STATE;
13618                         break;
13619                 }
13620                 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13621                 Rc = OK;
13622         case ADJUST_B_RESTORE_VOICE_1:
13623         case ADJUST_B_RESTORE_VOICE_2:
13624                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13625                 {
13626                         Info = adv_voice_restore_config(Id, plci, Rc);
13627                         if ((Info != GOOD) || plci->internal_command)
13628                                 break;
13629                 }
13630                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13631                 Rc = OK;
13632         case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13633         case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13634                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13635                 {
13636
13637                         Info = dtmf_parameter_restore_config(Id, plci, Rc);
13638                         if ((Info != GOOD) || plci->internal_command)
13639                                 break;
13640
13641                 }
13642                 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13643                 Rc = OK;
13644         case ADJUST_B_RESTORE_EC_1:
13645         case ADJUST_B_RESTORE_EC_2:
13646                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13647                 {
13648
13649                         Info = ec_restore_config(Id, plci, Rc);
13650                         if ((Info != GOOD) || plci->internal_command)
13651                                 break;
13652
13653                 }
13654                 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13655         case ADJUST_B_ASSIGN_L23_1:
13656                 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13657                 {
13658                         if (plci_nl_busy(plci))
13659                         {
13660                                 plci->internal_command = plci->adjust_b_command;
13661                                 break;
13662                         }
13663                         if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13664                                 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13665                         if (plci->adjust_b_parms_msg != NULL)
13666                                 api_load_msg(plci->adjust_b_parms_msg, bp);
13667                         else
13668                                 api_load_msg(&plci->B_protocol, bp);
13669                         Info = add_b23(plci, bp);
13670                         if (Info != GOOD)
13671                         {
13672                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13673                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13674                                 break;
13675                         }
13676                         plci->internal_command = plci->adjust_b_command;
13677                         nl_req_ncci(plci, ASSIGN, 0);
13678                         send_req(plci);
13679                         plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13680                         break;
13681                 }
13682                 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13683                 Rc = ASSIGN_OK;
13684         case ADJUST_B_ASSIGN_L23_2:
13685                 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13686                 {
13687                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13688                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13689                         Info = _WRONG_STATE;
13690                         break;
13691                 }
13692                 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13693                 {
13694                         if (Rc != ASSIGN_OK)
13695                         {
13696                                 plci->internal_command = plci->adjust_b_command;
13697                                 break;
13698                         }
13699                 }
13700                 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13701                 {
13702                         plci->adjust_b_restore = true;
13703                         break;
13704                 }
13705                 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13706         case ADJUST_B_CONNECT_1:
13707                 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13708                 {
13709                         plci->internal_command = plci->adjust_b_command;
13710                         if (plci_nl_busy(plci))
13711                                 break;
13712                         nl_req_ncci(plci, N_CONNECT, 0);
13713                         send_req(plci);
13714                         plci->adjust_b_state = ADJUST_B_CONNECT_2;
13715                         break;
13716                 }
13717                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13718                 Rc = OK;
13719         case ADJUST_B_CONNECT_2:
13720         case ADJUST_B_CONNECT_3:
13721         case ADJUST_B_CONNECT_4:
13722                 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13723                 {
13724                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13725                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13726                         Info = _WRONG_STATE;
13727                         break;
13728                 }
13729                 if (Rc == OK)
13730                 {
13731                         if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13732                         {
13733                                 get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13734                                 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13735                         }
13736                         if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13737                                 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13738                         else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13739                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13740                 }
13741                 else if (Rc == 0)
13742                 {
13743                         if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13744                                 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13745                         else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13746                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13747                 }
13748                 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13749                 {
13750                         plci->internal_command = plci->adjust_b_command;
13751                         break;
13752                 }
13753                 Rc = OK;
13754         case ADJUST_B_RESTORE_DTMF_1:
13755         case ADJUST_B_RESTORE_DTMF_2:
13756                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13757                 {
13758
13759                         Info = dtmf_restore_config(Id, plci, Rc);
13760                         if ((Info != GOOD) || plci->internal_command)
13761                                 break;
13762
13763                 }
13764                 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13765                 Rc = OK;
13766         case ADJUST_B_RESTORE_MIXER_1:
13767         case ADJUST_B_RESTORE_MIXER_2:
13768         case ADJUST_B_RESTORE_MIXER_3:
13769         case ADJUST_B_RESTORE_MIXER_4:
13770         case ADJUST_B_RESTORE_MIXER_5:
13771         case ADJUST_B_RESTORE_MIXER_6:
13772         case ADJUST_B_RESTORE_MIXER_7:
13773                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13774                 {
13775
13776                         Info = mixer_restore_config(Id, plci, Rc);
13777                         if ((Info != GOOD) || plci->internal_command)
13778                                 break;
13779
13780                 }
13781                 plci->adjust_b_state = ADJUST_B_END;
13782         case ADJUST_B_END:
13783                 break;
13784         }
13785         return (Info);
13786 }
13787
13788
13789 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13790 {
13791
13792         dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13793                         UnMapId(Id), (char *)(FILE_), __LINE__,
13794                         plci->B1_resource, b1_facilities));
13795
13796         plci->adjust_b_parms_msg = bp_msg;
13797         plci->adjust_b_facilities = b1_facilities;
13798         plci->adjust_b_command = internal_command;
13799         plci->adjust_b_ncci = (word)(Id >> 16);
13800         if ((bp_msg == NULL) && (plci->B1_resource == 0))
13801                 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13802         else
13803                 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13804         plci->adjust_b_state = ADJUST_B_START;
13805         dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13806                         UnMapId(Id), (char *)(FILE_), __LINE__,
13807                         plci->B1_resource, b1_facilities));
13808 }
13809
13810
13811 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13812 {
13813         word internal_command;
13814
13815         dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13816                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13817
13818         internal_command = plci->internal_command;
13819         plci->internal_command = 0;
13820         switch (internal_command)
13821         {
13822         default:
13823                 plci->command = 0;
13824                 if (plci->req_in != 0)
13825                 {
13826                         plci->internal_command = ADJUST_B_RESTORE_1;
13827                         break;
13828                 }
13829                 Rc = OK;
13830         case ADJUST_B_RESTORE_1:
13831                 if ((Rc != OK) && (Rc != OK_FC))
13832                 {
13833                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13834                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13835                 }
13836                 plci->adjust_b_parms_msg = NULL;
13837                 plci->adjust_b_facilities = plci->B1_facilities;
13838                 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13839                 plci->adjust_b_ncci = (word)(Id >> 16);
13840                 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13841                 plci->adjust_b_state = ADJUST_B_START;
13842                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13843                                 UnMapId(Id), (char *)(FILE_), __LINE__));
13844         case ADJUST_B_RESTORE_2:
13845                 if (adjust_b_process(Id, plci, Rc) != GOOD)
13846                 {
13847                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13848                                         UnMapId(Id), (char *)(FILE_), __LINE__));
13849                 }
13850                 if (plci->internal_command)
13851                         break;
13852                 break;
13853         }
13854 }
13855
13856
13857 static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
13858 {
13859         word Info;
13860         word internal_command;
13861
13862         dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
13863                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13864
13865         Info = GOOD;
13866         internal_command = plci->internal_command;
13867         plci->internal_command = 0;
13868         switch (internal_command)
13869         {
13870         default:
13871                 plci->command = 0;
13872                 plci->adjust_b_parms_msg = NULL;
13873                 plci->adjust_b_facilities = plci->B1_facilities;
13874                 plci->adjust_b_command = RESET_B3_COMMAND_1;
13875                 plci->adjust_b_ncci = (word)(Id >> 16);
13876                 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
13877                 plci->adjust_b_state = ADJUST_B_START;
13878                 dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
13879                                 UnMapId(Id), (char *)(FILE_), __LINE__));
13880         case RESET_B3_COMMAND_1:
13881                 Info = adjust_b_process(Id, plci, Rc);
13882                 if (Info != GOOD)
13883                 {
13884                         dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
13885                                         UnMapId(Id), (char *)(FILE_), __LINE__));
13886                         break;
13887                 }
13888                 if (plci->internal_command)
13889                         return;
13890                 break;
13891         }
13892 /*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
13893         sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
13894 }
13895
13896
13897 static void select_b_command(dword Id, PLCI *plci, byte Rc)
13898 {
13899         word Info;
13900         word internal_command;
13901         byte esc_chi[3];
13902
13903         dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
13904                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13905
13906         Info = GOOD;
13907         internal_command = plci->internal_command;
13908         plci->internal_command = 0;
13909         switch (internal_command)
13910         {
13911         default:
13912                 plci->command = 0;
13913                 plci->adjust_b_parms_msg = &plci->saved_msg;
13914                 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
13915                         plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
13916                 else
13917                         plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
13918                 plci->adjust_b_command = SELECT_B_COMMAND_1;
13919                 plci->adjust_b_ncci = (word)(Id >> 16);
13920                 if (plci->saved_msg.parms[0].length == 0)
13921                 {
13922                         plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
13923                                 ADJUST_B_MODE_NO_RESOURCE;
13924                 }
13925                 else
13926                 {
13927                         plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
13928                                 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
13929                 }
13930                 plci->adjust_b_state = ADJUST_B_START;
13931                 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
13932                                 UnMapId(Id), (char *)(FILE_), __LINE__));
13933         case SELECT_B_COMMAND_1:
13934                 Info = adjust_b_process(Id, plci, Rc);
13935                 if (Info != GOOD)
13936                 {
13937                         dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
13938                                         UnMapId(Id), (char *)(FILE_), __LINE__));
13939                         break;
13940                 }
13941                 if (plci->internal_command)
13942                         return;
13943                 if (plci->tel == ADV_VOICE)
13944                 {
13945                         esc_chi[0] = 0x02;
13946                         esc_chi[1] = 0x18;
13947                         esc_chi[2] = plci->b_channel;
13948                         SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
13949                 }
13950                 break;
13951         }
13952         sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
13953 }
13954
13955
13956 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
13957 {
13958         word internal_command;
13959
13960         dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
13961                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13962
13963         internal_command = plci->internal_command;
13964         plci->internal_command = 0;
13965         switch (internal_command)
13966         {
13967         default:
13968                 plci->command = 0;
13969         case FAX_CONNECT_ACK_COMMAND_1:
13970                 if (plci_nl_busy(plci))
13971                 {
13972                         plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
13973                         return;
13974                 }
13975                 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
13976                 plci->NData[0].P = plci->fax_connect_info_buffer;
13977                 plci->NData[0].PLength = plci->fax_connect_info_length;
13978                 plci->NL.X = plci->NData;
13979                 plci->NL.ReqCh = 0;
13980                 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
13981                 plci->adapter->request(&plci->NL);
13982                 return;
13983         case FAX_CONNECT_ACK_COMMAND_2:
13984                 if ((Rc != OK) && (Rc != OK_FC))
13985                 {
13986                         dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
13987                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13988                         break;
13989                 }
13990         }
13991         if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
13992             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
13993         {
13994                 if (plci->B3_prot == 4)
13995                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
13996                 else
13997                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
13998                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
13999         }
14000 }
14001
14002
14003 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14004 {
14005         word internal_command;
14006
14007         dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14008                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14009
14010         internal_command = plci->internal_command;
14011         plci->internal_command = 0;
14012         switch (internal_command)
14013         {
14014         default:
14015                 plci->command = 0;
14016         case FAX_EDATA_ACK_COMMAND_1:
14017                 if (plci_nl_busy(plci))
14018                 {
14019                         plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14020                         return;
14021                 }
14022                 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14023                 plci->NData[0].P = plci->fax_connect_info_buffer;
14024                 plci->NData[0].PLength = plci->fax_edata_ack_length;
14025                 plci->NL.X = plci->NData;
14026                 plci->NL.ReqCh = 0;
14027                 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14028                 plci->adapter->request(&plci->NL);
14029                 return;
14030         case FAX_EDATA_ACK_COMMAND_2:
14031                 if ((Rc != OK) && (Rc != OK_FC))
14032                 {
14033                         dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14034                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14035                         break;
14036                 }
14037         }
14038 }
14039
14040
14041 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14042 {
14043         word Info;
14044         word internal_command;
14045
14046         dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14047                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14048
14049         Info = GOOD;
14050         internal_command = plci->internal_command;
14051         plci->internal_command = 0;
14052         switch (internal_command)
14053         {
14054         default:
14055                 plci->command = 0;
14056         case FAX_CONNECT_INFO_COMMAND_1:
14057                 if (plci_nl_busy(plci))
14058                 {
14059                         plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14060                         return;
14061                 }
14062                 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14063                 plci->NData[0].P = plci->fax_connect_info_buffer;
14064                 plci->NData[0].PLength = plci->fax_connect_info_length;
14065                 plci->NL.X = plci->NData;
14066                 plci->NL.ReqCh = 0;
14067                 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14068                 plci->adapter->request(&plci->NL);
14069                 return;
14070         case FAX_CONNECT_INFO_COMMAND_2:
14071                 if ((Rc != OK) && (Rc != OK_FC))
14072                 {
14073                         dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14074                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14075                         Info = _WRONG_STATE;
14076                         break;
14077                 }
14078                 if (plci_nl_busy(plci))
14079                 {
14080                         plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14081                         return;
14082                 }
14083                 plci->command = _CONNECT_B3_R;
14084                 nl_req_ncci(plci, N_CONNECT, 0);
14085                 send_req(plci);
14086                 return;
14087         }
14088         sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14089 }
14090
14091
14092 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14093 {
14094         word Info;
14095         word internal_command;
14096
14097         dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14098                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14099
14100         Info = GOOD;
14101         internal_command = plci->internal_command;
14102         plci->internal_command = 0;
14103         switch (internal_command)
14104         {
14105         default:
14106                 plci->command = 0;
14107                 plci->adjust_b_parms_msg = NULL;
14108                 plci->adjust_b_facilities = plci->B1_facilities;
14109                 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14110                 plci->adjust_b_ncci = (word)(Id >> 16);
14111                 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14112                 plci->adjust_b_state = ADJUST_B_START;
14113                 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14114                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14115         case FAX_ADJUST_B23_COMMAND_1:
14116                 Info = adjust_b_process(Id, plci, Rc);
14117                 if (Info != GOOD)
14118                 {
14119                         dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14120                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14121                         break;
14122                 }
14123                 if (plci->internal_command)
14124                         return;
14125         case FAX_ADJUST_B23_COMMAND_2:
14126                 if (plci_nl_busy(plci))
14127                 {
14128                         plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14129                         return;
14130                 }
14131                 plci->command = _CONNECT_B3_R;
14132                 nl_req_ncci(plci, N_CONNECT, 0);
14133                 send_req(plci);
14134                 return;
14135         }
14136         sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14137 }
14138
14139
14140 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14141 {
14142         word internal_command;
14143
14144         dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14145                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14146
14147         internal_command = plci->internal_command;
14148         plci->internal_command = 0;
14149         switch (internal_command)
14150         {
14151         default:
14152                 plci->command = 0;
14153                 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14154                 return;
14155         case FAX_DISCONNECT_COMMAND_1:
14156         case FAX_DISCONNECT_COMMAND_2:
14157         case FAX_DISCONNECT_COMMAND_3:
14158                 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14159                 {
14160                         dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14161                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14162                         break;
14163                 }
14164                 if (Rc == OK)
14165                 {
14166                         if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14167                             || (internal_command == FAX_DISCONNECT_COMMAND_2))
14168                         {
14169                                 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14170                         }
14171                 }
14172                 else if (Rc == 0)
14173                 {
14174                         if (internal_command == FAX_DISCONNECT_COMMAND_1)
14175                                 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14176                 }
14177                 return;
14178         }
14179 }
14180
14181
14182
14183 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14184 {
14185         word Info;
14186         word internal_command;
14187
14188         dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14189                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14190
14191         Info = GOOD;
14192         internal_command = plci->internal_command;
14193         plci->internal_command = 0;
14194         switch (internal_command)
14195         {
14196         default:
14197                 plci->command = 0;
14198         case RTP_CONNECT_B3_REQ_COMMAND_1:
14199                 if (plci_nl_busy(plci))
14200                 {
14201                         plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14202                         return;
14203                 }
14204                 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14205                 nl_req_ncci(plci, N_CONNECT, 0);
14206                 send_req(plci);
14207                 return;
14208         case RTP_CONNECT_B3_REQ_COMMAND_2:
14209                 if ((Rc != OK) && (Rc != OK_FC))
14210                 {
14211                         dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14212                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14213                         Info = _WRONG_STATE;
14214                         break;
14215                 }
14216                 if (plci_nl_busy(plci))
14217                 {
14218                         plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14219                         return;
14220                 }
14221                 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14222                 plci->NData[0].PLength = plci->internal_req_buffer[0];
14223                 plci->NData[0].P = plci->internal_req_buffer + 1;
14224                 plci->NL.X = plci->NData;
14225                 plci->NL.ReqCh = 0;
14226                 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14227                 plci->adapter->request(&plci->NL);
14228                 break;
14229         case RTP_CONNECT_B3_REQ_COMMAND_3:
14230                 return;
14231         }
14232         sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14233 }
14234
14235
14236 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14237 {
14238         word internal_command;
14239
14240         dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14241                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14242
14243         internal_command = plci->internal_command;
14244         plci->internal_command = 0;
14245         switch (internal_command)
14246         {
14247         default:
14248                 plci->command = 0;
14249         case RTP_CONNECT_B3_RES_COMMAND_1:
14250                 if (plci_nl_busy(plci))
14251                 {
14252                         plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14253                         return;
14254                 }
14255                 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14256                 nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14257                 send_req(plci);
14258                 return;
14259         case RTP_CONNECT_B3_RES_COMMAND_2:
14260                 if ((Rc != OK) && (Rc != OK_FC))
14261                 {
14262                         dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14263                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14264                         break;
14265                 }
14266                 if (plci_nl_busy(plci))
14267                 {
14268                         plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14269                         return;
14270                 }
14271                 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14272                 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14273                 plci->NData[0].PLength = plci->internal_req_buffer[0];
14274                 plci->NData[0].P = plci->internal_req_buffer + 1;
14275                 plci->NL.X = plci->NData;
14276                 plci->NL.ReqCh = 0;
14277                 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14278                 plci->adapter->request(&plci->NL);
14279                 return;
14280         case RTP_CONNECT_B3_RES_COMMAND_3:
14281                 return;
14282         }
14283 }
14284
14285
14286
14287 static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14288 {
14289         byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14290         word Info;
14291         word internal_command;
14292
14293         dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14294                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14295
14296         Info = GOOD;
14297         internal_command = plci->internal_command;
14298         plci->internal_command = 0;
14299         switch (internal_command)
14300         {
14301         default:
14302                 if (!plci->NL.Id)
14303                         break;
14304                 plci->command = 0;
14305                 plci->adjust_b_parms_msg = NULL;
14306                 plci->adjust_b_facilities = plci->B1_facilities;
14307                 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14308                 plci->adjust_b_ncci = (word)(Id >> 16);
14309                 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14310                 plci->adjust_b_state = ADJUST_B_START;
14311                 dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14312                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14313         case HOLD_SAVE_COMMAND_1:
14314                 Info = adjust_b_process(Id, plci, Rc);
14315                 if (Info != GOOD)
14316                 {
14317                         dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14318                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14319                         break;
14320                 }
14321                 if (plci->internal_command)
14322                         return;
14323         }
14324         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14325 }
14326
14327
14328 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14329 {
14330         byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14331         word Info;
14332         word internal_command;
14333
14334         dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14335                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14336
14337         Info = GOOD;
14338         internal_command = plci->internal_command;
14339         plci->internal_command = 0;
14340         switch (internal_command)
14341         {
14342         default:
14343                 plci->command = 0;
14344                 plci->adjust_b_parms_msg = NULL;
14345                 plci->adjust_b_facilities = plci->B1_facilities;
14346                 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14347                 plci->adjust_b_ncci = (word)(Id >> 16);
14348                 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14349                 plci->adjust_b_state = ADJUST_B_START;
14350                 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14351                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14352         case RETRIEVE_RESTORE_COMMAND_1:
14353                 Info = adjust_b_process(Id, plci, Rc);
14354                 if (Info != GOOD)
14355                 {
14356                         dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14357                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14358                         break;
14359                 }
14360                 if (plci->internal_command)
14361                         return;
14362         }
14363         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14364 }
14365
14366
14367 static void init_b1_config(PLCI *plci)
14368 {
14369
14370         dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14371                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14372                         (char *)(FILE_), __LINE__));
14373
14374         plci->B1_resource = 0;
14375         plci->B1_facilities = 0;
14376
14377         plci->li_bchannel_id = 0;
14378         mixer_clear_config(plci);
14379
14380
14381         ec_clear_config(plci);
14382
14383
14384         dtmf_rec_clear_config(plci);
14385         dtmf_send_clear_config(plci);
14386         dtmf_parameter_clear_config(plci);
14387
14388         adv_voice_clear_config(plci);
14389         adjust_b_clear(plci);
14390 }
14391
14392
14393 static void clear_b1_config(PLCI *plci)
14394 {
14395
14396         dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14397                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14398                         (char *)(FILE_), __LINE__));
14399
14400         adv_voice_clear_config(plci);
14401         adjust_b_clear(plci);
14402
14403         ec_clear_config(plci);
14404
14405
14406         dtmf_rec_clear_config(plci);
14407         dtmf_send_clear_config(plci);
14408         dtmf_parameter_clear_config(plci);
14409
14410
14411         if ((plci->li_bchannel_id != 0)
14412             && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14413         {
14414                 mixer_clear_config(plci);
14415                 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14416                 plci->li_bchannel_id = 0;
14417         }
14418
14419         plci->B1_resource = 0;
14420         plci->B1_facilities = 0;
14421 }
14422
14423
14424 /* -----------------------------------------------------------------
14425    XON protocol local helpers
14426    ----------------------------------------------------------------- */
14427 static void channel_flow_control_remove(PLCI *plci) {
14428         DIVA_CAPI_ADAPTER *a = plci->adapter;
14429         word i;
14430         for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14431                 if (a->ch_flow_plci[i] == plci->Id) {
14432                         a->ch_flow_plci[i] = 0;
14433                         a->ch_flow_control[i] = 0;
14434                 }
14435         }
14436 }
14437
14438 static void channel_x_on(PLCI *plci, byte ch) {
14439         DIVA_CAPI_ADAPTER *a = plci->adapter;
14440         if (a->ch_flow_control[ch] & N_XON_SENT) {
14441                 a->ch_flow_control[ch] &= ~N_XON_SENT;
14442         }
14443 }
14444
14445 static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14446         DIVA_CAPI_ADAPTER *a = plci->adapter;
14447         if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14448                 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14449                 a->ch_flow_plci[ch] = plci->Id;
14450                 a->ch_flow_control_pending++;
14451         }
14452 }
14453
14454 static void channel_request_xon(PLCI *plci, byte ch) {
14455         DIVA_CAPI_ADAPTER *a = plci->adapter;
14456
14457         if (a->ch_flow_control[ch] & N_CH_XOFF) {
14458                 a->ch_flow_control[ch] |= N_XON_REQ;
14459                 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14460                 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14461         }
14462 }
14463
14464 static void channel_xmit_extended_xon(PLCI *plci) {
14465         DIVA_CAPI_ADAPTER *a;
14466         int max_ch = ARRAY_SIZE(a->ch_flow_control);
14467         int i, one_requested = 0;
14468
14469         if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14470                 return;
14471         }
14472
14473         for (i = 0; i < max_ch; i++) {
14474                 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14475                     (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14476                     (plci->Id == a->ch_flow_plci[i])) {
14477                         channel_request_xon(plci, (byte)i);
14478                         one_requested = 1;
14479                 }
14480         }
14481
14482         if (one_requested) {
14483                 channel_xmit_xon(plci);
14484         }
14485 }
14486
14487 /*
14488   Try to xmit next X_ON
14489 */
14490 static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14491         int max_ch = ARRAY_SIZE(a->ch_flow_control);
14492         int i;
14493
14494         if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14495                 return (0);
14496         }
14497
14498         if (a->last_flow_control_ch >= max_ch) {
14499                 a->last_flow_control_ch = 1;
14500         }
14501         for (i = a->last_flow_control_ch; i < max_ch; i++) {
14502                 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14503                     (plci->Id == a->ch_flow_plci[i])) {
14504                         a->last_flow_control_ch = i + 1;
14505                         return (i);
14506                 }
14507         }
14508
14509         for (i = 1; i < a->last_flow_control_ch; i++) {
14510                 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14511                     (plci->Id == a->ch_flow_plci[i])) {
14512                         a->last_flow_control_ch = i + 1;
14513                         return (i);
14514                 }
14515         }
14516
14517         return (0);
14518 }
14519
14520 static void channel_xmit_xon(PLCI *plci) {
14521         DIVA_CAPI_ADAPTER *a = plci->adapter;
14522         byte ch;
14523
14524         if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14525                 return;
14526         }
14527         if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14528                 return;
14529         }
14530         a->ch_flow_control[ch] &= ~N_XON_REQ;
14531         a->ch_flow_control[ch] |= N_XON_SENT;
14532
14533         plci->NL.Req = plci->nl_req = (byte)N_XON;
14534         plci->NL.ReqCh         = ch;
14535         plci->NL.X             = plci->NData;
14536         plci->NL.XNum          = 1;
14537         plci->NData[0].P       = &plci->RBuffer[0];
14538         plci->NData[0].PLength = 0;
14539
14540         plci->adapter->request(&plci->NL);
14541 }
14542
14543 static int channel_can_xon(PLCI *plci, byte ch) {
14544         APPL *APPLptr;
14545         DIVA_CAPI_ADAPTER *a;
14546         word NCCIcode;
14547         dword count;
14548         word Num;
14549         word i;
14550
14551         APPLptr = plci->appl;
14552         a = plci->adapter;
14553
14554         if (!APPLptr)
14555                 return (0);
14556
14557         NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14558
14559         /* count all buffers within the Application pool    */
14560         /* belonging to the same NCCI. XON if a first is    */
14561         /* used.                                            */
14562         count = 0;
14563         Num = 0xffff;
14564         for (i = 0; i < APPLptr->MaxBuffer; i++) {
14565                 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14566                 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14567         }
14568         if ((count > 2) || (Num == 0xffff)) {
14569                 return (0);
14570         }
14571         return (1);
14572 }
14573
14574
14575 /*------------------------------------------------------------------*/
14576
14577 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14578 {
14579         return 1;
14580 }
14581
14582
14583
14584 /**********************************************************************************/
14585 /* function groups the listening applications according to the CIP mask and the   */
14586 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14587 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14588 /* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14589 /* function must be enabled by setting "a->group_optimization_enabled" from the   */
14590 /* OS specific part (per adapter).                                                */
14591 /**********************************************************************************/
14592 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14593 {
14594         word i, j, k, busy, group_found;
14595         dword info_mask_group[MAX_CIP_TYPES];
14596         dword cip_mask_group[MAX_CIP_TYPES];
14597         word appl_number_group_type[MAX_APPL];
14598         PLCI *auxplci;
14599
14600         /* all APPLs within this inc. call are allowed to dial in */
14601         bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
14602
14603         if (!a->group_optimization_enabled)
14604         {
14605                 dbug(1, dprintf("No group optimization"));
14606                 return;
14607         }
14608
14609         dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14610
14611         for (i = 0; i < MAX_CIP_TYPES; i++)
14612         {
14613                 info_mask_group[i] = 0;
14614                 cip_mask_group[i] = 0;
14615         }
14616         for (i = 0; i < MAX_APPL; i++)
14617         {
14618                 appl_number_group_type[i] = 0;
14619         }
14620         for (i = 0; i < max_appl; i++) /* check if any multi instance capable application is present */
14621         {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14622                 if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14623                 {
14624                         dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14625                         return; /* allow good application unfiltered access */
14626                 }
14627         }
14628         for (i = 0; i < max_appl; i++) /* Build CIP Groups */
14629         {
14630                 if (application[i].Id && a->CIP_Mask[i])
14631                 {
14632                         for (k = 0, busy = false; k < a->max_plci; k++)
14633                         {
14634                                 if (a->plci[k].Id)
14635                                 {
14636                                         auxplci = &a->plci[k];
14637                                         if (auxplci->appl == &application[i]) {
14638                                                 /* application has a busy PLCI */
14639                                                 busy = true;
14640                                                 dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14641                                         } else if (test_bit(i, plci->c_ind_mask_table)) {
14642                                                 /* application has an incoming call pending */
14643                                                 busy = true;
14644                                                 dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14645                                         }
14646                                 }
14647                         }
14648
14649                         for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++)     /* build groups with free applications only */
14650                         {
14651                                 if (j == MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14652                                 {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14653                                         appl_number_group_type[i] = MAX_CIP_TYPES;
14654                                         group_found = true;
14655                                         dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14656                                 }
14657                                 else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14658                                 {                                      /* is group already present ?                  */
14659                                         appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14660                                         group_found = true;
14661                                         dbug(1, dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx", appl_number_group_type[i], i + 1, info_mask_group[j]));
14662                                 }
14663                                 else if (!info_mask_group[j])
14664                                 {                                      /* establish a new group                       */
14665                                         appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14666                                         info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14667                                         cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14668                                         group_found = true;
14669                                         dbug(1, dprintf("New Group 0x%x established with appl 0x%x, CIP=0x%lx", appl_number_group_type[i], i + 1, info_mask_group[j]));
14670                                 }
14671                         }
14672                 }
14673         }
14674
14675         for (i = 0; i < max_appl; i++) /* Build group_optimization_mask_table */
14676         {
14677                 if (appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14678                 {
14679                         if (appl_number_group_type[i] == MAX_CIP_TYPES)
14680                         {
14681                                 dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14682                         }
14683                         else
14684                         {
14685                                 dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14686                                 for (j = i + 1; j < max_appl; j++)   /* search other group members and mark them as busy        */
14687                                 {
14688                                         if (appl_number_group_type[i] == appl_number_group_type[j])
14689                                         {
14690                                                 dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14691                                                 /* disable call on other group members */
14692                                                 __clear_bit(j, plci->group_optimization_mask_table);
14693                                                 appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14694                                         }
14695                                 }
14696                         }
14697                 }
14698                 else                                                 /* application should not get a call */
14699                 {
14700                         __clear_bit(i, plci->group_optimization_mask_table);
14701                 }
14702         }
14703
14704 }
14705
14706
14707
14708 /* OS notifies the driver about a application Capi_Register */
14709 word CapiRegister(word id)
14710 {
14711         word i, j, appls_found;
14712
14713         PLCI *plci;
14714         DIVA_CAPI_ADAPTER *a;
14715
14716         for (i = 0, appls_found = 0; i < max_appl; i++)
14717         {
14718                 if (application[i].Id && (application[i].Id != id))
14719                 {
14720                         appls_found++;                       /* an application has been found */
14721                 }
14722         }
14723
14724         if (appls_found) return true;
14725         for (i = 0; i < max_adapter; i++)                   /* scan all adapters...    */
14726         {
14727                 a = &adapter[i];
14728                 if (a->request)
14729                 {
14730                         if (a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14731                         {
14732                                 if (!appls_found)           /* first application does a capi register   */
14733                                 {
14734                                         if ((j = get_plci(a)))                    /* activate L1 of all adapters */
14735                                         {
14736                                                 plci = &a->plci[j - 1];
14737                                                 plci->command = 0;
14738                                                 add_p(plci, OAD, "\x01\xfd");
14739                                                 add_p(plci, CAI, "\x01\x80");
14740                                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14741                                                 add_p(plci, SHIFT | 6, NULL);
14742                                                 add_p(plci, SIN, "\x02\x00\x00");
14743                                                 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14744                                                 sig_req(plci, ASSIGN, DSIG_ID);
14745                                                 add_p(plci, FTY, "\x02\xff\x07"); /* l1 start */
14746                                                 sig_req(plci, SIG_CTRL, 0);
14747                                                 send_req(plci);
14748                                         }
14749                                 }
14750                         }
14751                 }
14752         }
14753         return false;
14754 }
14755
14756 /*------------------------------------------------------------------*/
14757
14758 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14759
14760 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14761 {
14762         word i;
14763         /* Format of vswitch_t:
14764            0 byte length
14765            1 byte VSWITCHIE
14766            2 byte VSWITCH_REQ/VSWITCH_IND
14767            3 byte reserved
14768            4 word VSwitchcommand
14769            6 word returnerror
14770            8... Params
14771         */
14772         if (!plci ||
14773             !plci->appl ||
14774             !plci->State ||
14775             plci->Sig.Ind == NCR_FACILITY
14776                 )
14777                 return;
14778
14779         for (i = 0; i < MAX_MULTI_IE; i++)
14780         {
14781                 if (!parms[i][0]) continue;
14782                 if (parms[i][0] < 7)
14783                 {
14784                         parms[i][0] = 0; /* kill it */
14785                         continue;
14786                 }
14787                 dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14788                 switch (parms[i][4])
14789                 {
14790                 case VSJOIN:
14791                         if (!plci->relatedPTYPLCI ||
14792                             (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14793                         { /* Error */
14794                                 break;
14795                         }
14796                         /* remember all necessary informations */
14797                         if (parms[i][0] != 11 || parms[i][8] != 3) /* Length Test */
14798                         {
14799                                 break;
14800                         }
14801                         if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14802                         {   /* first indication after ECT-Request on Consultation Call */
14803                                 plci->vswitchstate = parms[i][9];
14804                                 parms[i][9] = 2; /* State */
14805                                 /* now ask first Call to join */
14806                         }
14807                         else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14808                         { /* Answer of VSWITCH_REQ from first Call */
14809                                 plci->vswitchstate = parms[i][9];
14810                                 /* tell consultation call to join
14811                                    and the protocol capabilities of the first call */
14812                         }
14813                         else
14814                         { /* Error */
14815                                 break;
14816                         }
14817                         plci->vsprot = parms[i][10]; /* protocol */
14818                         plci->vsprotdialect = parms[i][11]; /* protocoldialect */
14819                         /* send join request to related PLCI */
14820                         parms[i][1] = VSWITCHIE;
14821                         parms[i][2] = VSWITCH_REQ;
14822
14823                         plci->relatedPTYPLCI->command = 0;
14824                         plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14825                         add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14826                         sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14827                         send_req(plci->relatedPTYPLCI);
14828                         break;
14829                 case VSTRANSPORT:
14830                 default:
14831                         if (plci->relatedPTYPLCI &&
14832                             plci->vswitchstate == 3 &&
14833                             plci->relatedPTYPLCI->vswitchstate == 3)
14834                         {
14835                                 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14836                                 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14837                                 send_req(plci->relatedPTYPLCI);
14838                         }
14839                         break;
14840                 }
14841                 parms[i][0] = 0; /* kill it */
14842         }
14843 }
14844
14845
14846 /*------------------------------------------------------------------*/
14847
14848 static int diva_get_dma_descriptor(PLCI *plci, dword   *dma_magic) {
14849         ENTITY e;
14850         IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14851
14852         if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14853                 return (-1);
14854         }
14855
14856         pReq->xdi_dma_descriptor_operation.Req = 0;
14857         pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14858
14859         pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14860         pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
14861         pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14862         pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
14863
14864         e.user[0] = plci->adapter->Id - 1;
14865         plci->adapter->request((ENTITY *)pReq);
14866
14867         if (!pReq->xdi_dma_descriptor_operation.info.operation &&
14868             (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
14869             pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
14870                 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
14871                 dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
14872                                 plci->adapter->Id,
14873                                 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
14874                                 *dma_magic));
14875                 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
14876         } else {
14877                 dbug(1, dprintf("dma_alloc failed"));
14878                 return (-1);
14879         }
14880 }
14881
14882 static void diva_free_dma_descriptor(PLCI *plci, int nr) {
14883         ENTITY e;
14884         IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14885
14886         if (nr < 0) {
14887                 return;
14888         }
14889
14890         pReq->xdi_dma_descriptor_operation.Req = 0;
14891         pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14892
14893         pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
14894         pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
14895         pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14896         pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
14897
14898         e.user[0] = plci->adapter->Id - 1;
14899         plci->adapter->request((ENTITY *)pReq);
14900
14901         if (!pReq->xdi_dma_descriptor_operation.info.operation) {
14902                 dbug(1, dprintf("dma_free(%d)", nr));
14903         } else {
14904                 dbug(1, dprintf("dma_free failed (%d)", nr));
14905         }
14906 }
14907
14908 /*------------------------------------------------------------------*/