GNU Linux-libre 4.19.286-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                                 /* fall through */
4505
4506                         default:
4507                                 if (plci->internal_command_queue[0])
4508                                 {
4509                                         (*(plci->internal_command_queue[0]))(Id, plci, rc);
4510                                         if (plci->internal_command)
4511                                                 return;
4512                                 }
4513                                 break;
4514                         }
4515                         next_internal_command(Id, plci);
4516                 }
4517         }
4518         else /* appl==0 */
4519         {
4520                 Id = ((word)plci->Id << 8) | plci->adapter->Id;
4521                 if (plci->tel) Id |= EXT_CONTROLLER;
4522
4523                 switch (plci->internal_command)
4524                 {
4525                 case BLOCK_PLCI:
4526                         return;
4527
4528                 case START_L1_SIG_ASSIGN_PEND:
4529                 case REM_L1_SIG_ASSIGN_PEND:
4530                         if (global_req == ASSIGN)
4531                         {
4532                                 break;
4533                         }
4534                         else
4535                         {
4536                                 dbug(1, dprintf("***L1 Req rem PLCI"));
4537                                 plci->internal_command = 0;
4538                                 sig_req(plci, REMOVE, 0);
4539                                 send_req(plci);
4540                         }
4541                         break;
4542
4543                         /* Call Deflection Request pending, just no appl ptr assigned */
4544                 case CD_REQ_PEND:
4545                         SSparms[1] = S_CALL_DEFLECTION;
4546                         if (rc != OK)
4547                         {
4548                                 Info = 0x300E; /* not supported */
4549                         }
4550                         for (i = 0; i < max_appl; i++)
4551                         {
4552                                 if (application[i].CDEnable)
4553                                 {
4554                                         if (!application[i].Id) application[i].CDEnable = 0;
4555                                         else
4556                                         {
4557                                                 sendf(&application[i], _FACILITY_R | CONFIRM, Id,
4558                                                       plci->number, "wws", Info, (word)3, SSparms);
4559                                                 if (Info) application[i].CDEnable = 0;
4560                                         }
4561                                 }
4562                         }
4563                         plci->internal_command = 0;
4564                         break;
4565
4566                 case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4567                         return;
4568
4569                 case PERM_COD_CALL:
4570                         plci->internal_command = PERM_COD_CONN_PEND;
4571                         dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc));
4572                         return;
4573
4574                 case PERM_COD_ASSIGN:
4575                         dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc));
4576                         plci->internal_command = 0;
4577                         if (rc != ASSIGN_OK) break;
4578                         plci->internal_command = PERM_COD_CALL;
4579                         sig_req(plci, CALL_REQ, 0);
4580                         send_req(plci);
4581                         return;
4582
4583                 case LISTEN_SIG_ASSIGN_PEND:
4584                         if (rc == ASSIGN_OK)
4585                         {
4586                                 plci->internal_command = 0;
4587                                 dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci->Sig.Id));
4588                                 add_p(plci, ESC, "\x02\x18\x00");             /* support call waiting */
4589                                 sig_req(plci, INDICATE_REQ, 0);
4590                                 send_req(plci);
4591                         }
4592                         else
4593                         {
4594                                 dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc));
4595                                 a->listen_active--;
4596                                 plci_remove(plci);
4597                                 plci->State = IDLE;
4598                         }
4599                         break;
4600
4601                 case USELAW_REQ:
4602                         if (global_req == ASSIGN)
4603                         {
4604                                 if (rc == ASSIGN_OK)
4605                                 {
4606                                         sig_req(plci, LAW_REQ, 0);
4607                                         send_req(plci);
4608                                         dbug(1, dprintf("Auto-Law assigned"));
4609                                 }
4610                                 else
4611                                 {
4612                                         dbug(1, dprintf("Auto-Law assign failed"));
4613                                         a->automatic_law = 3;
4614                                         plci->internal_command = 0;
4615                                         a->automatic_lawPLCI = NULL;
4616                                 }
4617                                 break;
4618                         }
4619                         else if (req == LAW_REQ && rc == OK)
4620                         {
4621                                 dbug(1, dprintf("Auto-Law initiated"));
4622                                 a->automatic_law = 2;
4623                                 plci->internal_command = 0;
4624                         }
4625                         else
4626                         {
4627                                 dbug(1, dprintf("Auto-Law not supported"));
4628                                 a->automatic_law = 3;
4629                                 plci->internal_command = 0;
4630                                 sig_req(plci, REMOVE, 0);
4631                                 send_req(plci);
4632                                 a->automatic_lawPLCI = NULL;
4633                         }
4634                         break;
4635                 }
4636                 plci_remove_check(plci);
4637         }
4638 }
4639
4640 static void data_rc(PLCI *plci, byte ch)
4641 {
4642         dword Id;
4643         DIVA_CAPI_ADAPTER *a;
4644         NCCI *ncci_ptr;
4645         DATA_B3_DESC *data;
4646         word ncci;
4647
4648         if (plci->appl)
4649         {
4650                 TransmitBufferFree(plci->appl, plci->data_sent_ptr);
4651                 a = plci->adapter;
4652                 ncci = a->ch_ncci[ch];
4653                 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4654                 {
4655                         ncci_ptr = &(a->ncci[ncci]);
4656                         dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr->data_out, ncci_ptr->data_pending));
4657                         if (ncci_ptr->data_pending)
4658                         {
4659                                 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4660                                 if (!(data->Flags & 4) && a->ncci_state[ncci])
4661                                 {
4662                                         Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4663                                         if (plci->tel) Id |= EXT_CONTROLLER;
4664                                         sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, data->Number,
4665                                               "ww", data->Handle, 0);
4666                                 }
4667                                 (ncci_ptr->data_out)++;
4668                                 if (ncci_ptr->data_out == MAX_DATA_B3)
4669                                         ncci_ptr->data_out = 0;
4670                                 (ncci_ptr->data_pending)--;
4671                         }
4672                 }
4673         }
4674 }
4675
4676 static void data_ack(PLCI *plci, byte ch)
4677 {
4678         dword Id;
4679         DIVA_CAPI_ADAPTER *a;
4680         NCCI *ncci_ptr;
4681         word ncci;
4682
4683         a = plci->adapter;
4684         ncci = a->ch_ncci[ch];
4685         ncci_ptr = &(a->ncci[ncci]);
4686         if (ncci_ptr->data_ack_pending)
4687         {
4688                 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4689                 {
4690                         Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4691                         if (plci->tel) Id |= EXT_CONTROLLER;
4692                         sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4693                               "ww", ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle, 0);
4694                 }
4695                 (ncci_ptr->data_ack_out)++;
4696                 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4697                         ncci_ptr->data_ack_out = 0;
4698                 (ncci_ptr->data_ack_pending)--;
4699         }
4700 }
4701
4702 static void sig_ind(PLCI *plci)
4703 {
4704         dword x_Id;
4705         dword Id;
4706         dword rId;
4707         word i;
4708         word cip;
4709         dword cip_mask;
4710         byte *ie;
4711         DIVA_CAPI_ADAPTER *a;
4712         API_PARSE saved_parms[MAX_MSG_PARMS + 1];
4713 #define MAXPARMSIDS 31
4714         byte *parms[MAXPARMSIDS];
4715         byte *add_i[4];
4716         byte *multi_fac_parms[MAX_MULTI_IE];
4717         byte *multi_pi_parms[MAX_MULTI_IE];
4718         byte *multi_ssext_parms[MAX_MULTI_IE];
4719         byte *multi_CiPN_parms[MAX_MULTI_IE];
4720
4721         byte *multi_vswitch_parms[MAX_MULTI_IE];
4722
4723         byte ai_len;
4724         byte *esc_chi = "";
4725         byte *esc_law = "";
4726         byte *pty_cai = "";
4727         byte *esc_cr  = "";
4728         byte *esc_profile = "";
4729
4730         byte facility[256];
4731         PLCI *tplci = NULL;
4732         byte chi[] = "\x02\x18\x01";
4733         byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4734         byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4735         /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4736         /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4737         /* SMSG is situated at the end because its 0 (for compatibility reasons */
4738         /* (see Info_Mask Bit 4, first IE. then the message type)           */
4739         static const word parms_id[] =
4740                 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4741                  UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4742                  RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4743                  CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4744         /* 14 FTY repl by ESC_CHI */
4745         /* 18 PI  repl by ESC_LAW */
4746         /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4747         static const word multi_fac_id[] = {1, FTY};
4748         static const word multi_pi_id[]  = {1, PI};
4749         static const word multi_CiPN_id[]  = {1, OAD};
4750         static const word multi_ssext_id[]  = {1, ESC_SSEXT};
4751
4752         static const word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4753
4754         byte *cau;
4755         word ncci;
4756         byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4757         byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4758         byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4759         byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\x00\x00\x00\x00";
4760         byte force_mt_info = false;
4761         byte dir;
4762         dword d;
4763         word w;
4764
4765         a = plci->adapter;
4766         Id = ((word)plci->Id << 8) | a->Id;
4767         PUT_WORD(&SS_Ind[4], 0x0000);
4768
4769         if (plci->sig_remove_id)
4770         {
4771                 plci->Sig.RNR = 2; /* discard */
4772                 dbug(1, dprintf("SIG discard while remove pending"));
4773                 return;
4774         }
4775         if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4776         dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4777                         Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4778         if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4779         {
4780                 plci->Sig.RNR = 1;
4781                 return;
4782         }
4783         if (plci->Sig.Ind == HANGUP && plci->channels)
4784         {
4785                 plci->Sig.RNR = 1;
4786                 plci->hangup_flow_ctrl_timer++;
4787                 /* recover the network layer after timeout */
4788                 if (plci->hangup_flow_ctrl_timer == 100)
4789                 {
4790                         dbug(1, dprintf("Exceptional disc"));
4791                         plci->Sig.RNR = 0;
4792                         plci->hangup_flow_ctrl_timer = 0;
4793                         for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4794                         {
4795                                 if (a->ncci_plci[ncci] == plci->Id)
4796                                 {
4797                                         cleanup_ncci_data(plci, ncci);
4798                                         if (plci->channels)plci->channels--;
4799                                         if (plci->appl)
4800                                                 sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4801                                 }
4802                         }
4803                         if (plci->appl)
4804                                 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4805                         plci_remove(plci);
4806                         plci->State = IDLE;
4807                 }
4808                 return;
4809         }
4810
4811         /* do first parse the info with no OAD in, because OAD will be converted */
4812         /* first the multiple facility IE, then mult. progress ind.              */
4813         /* then the parameters for the info_ind + conn_ind                       */
4814         IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4815         IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4816         IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4817
4818         IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4819
4820         IndParse(plci, parms_id, parms, 0);
4821         IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4822         esc_chi  = parms[14];
4823         esc_law  = parms[18];
4824         pty_cai  = parms[24];
4825         esc_cr   = parms[25];
4826         esc_profile = parms[27];
4827         if (esc_cr[0] && plci)
4828         {
4829                 if (plci->cr_enquiry && plci->appl)
4830                 {
4831                         plci->cr_enquiry = false;
4832                         /* d = MANU_ID            */
4833                         /* w = m_command          */
4834                         /* b = total length       */
4835                         /* b = indication type    */
4836                         /* b = length of all IEs  */
4837                         /* b = IE1                */
4838                         /* S = IE1 length + cont. */
4839                         /* b = IE2                */
4840                         /* S = IE2 length + cont. */
4841                         sendf(plci->appl,
4842                               _MANUFACTURER_I,
4843                               Id,
4844                               0,
4845                               "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4846                               2 + 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], plci->Sig.Ind, 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], ESC, esc_cr, ESC, esc_law);
4847                 }
4848         }
4849         /* create the additional info structure                                  */
4850         add_i[1] = parms[15]; /* KEY of additional info */
4851         add_i[2] = parms[11]; /* UUI of additional info */
4852         ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4853
4854         /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4855         /* indication returns by the card if requested by the function           */
4856         /* AutomaticLaw() after driver init                                      */
4857         if (a->automatic_law < 4)
4858         {
4859                 if (esc_law[0]) {
4860                         if (esc_law[2]) {
4861                                 dbug(0, dprintf("u-Law selected"));
4862                                 a->u_law = 1;
4863                         }
4864                         else {
4865                                 dbug(0, dprintf("a-Law selected"));
4866                                 a->u_law = 0;
4867                         }
4868                         a->automatic_law = 4;
4869                         if (plci == a->automatic_lawPLCI) {
4870                                 plci->internal_command = 0;
4871                                 sig_req(plci, REMOVE, 0);
4872                                 send_req(plci);
4873                                 a->automatic_lawPLCI = NULL;
4874                         }
4875                 }
4876                 if (esc_profile[0])
4877                 {
4878                         dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4879                                         UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
4880                                         GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
4881                                         GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
4882
4883                         a->profile.Global_Options &= 0x000000ffL;
4884                         a->profile.B1_Protocols &= 0x000003ffL;
4885                         a->profile.B2_Protocols &= 0x00001fdfL;
4886                         a->profile.B3_Protocols &= 0x000000b7L;
4887
4888                         a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
4889                                 GL_BCHANNEL_OPERATION_SUPPORTED;
4890                         a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
4891                         a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
4892                         a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
4893                         a->manufacturer_features = GET_DWORD(&esc_profile[46]);
4894                         a->man_profile.private_options = 0;
4895
4896                         if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
4897                         {
4898                                 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
4899                                 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
4900                         }
4901
4902
4903                         if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
4904                                 a->man_profile.private_options |= 1L << PRIVATE_RTP;
4905                         a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
4906                         a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
4907
4908
4909                         if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
4910                                 a->man_profile.private_options |= 1L << PRIVATE_T38;
4911
4912
4913                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
4914                                 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
4915
4916
4917                         if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
4918                                 a->man_profile.private_options |= 1L << PRIVATE_V18;
4919
4920
4921                         if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
4922                                 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
4923
4924
4925                         if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
4926                                 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
4927
4928
4929                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
4930                                 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
4931
4932
4933                         if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
4934                                 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
4935
4936
4937                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
4938                                 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
4939
4940                 }
4941                 else
4942                 {
4943                         a->profile.Global_Options &= 0x0000007fL;
4944                         a->profile.B1_Protocols &= 0x000003dfL;
4945                         a->profile.B2_Protocols &= 0x00001adfL;
4946                         a->profile.B3_Protocols &= 0x000000b7L;
4947                         a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
4948                 }
4949                 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
4950                                                 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
4951                 {
4952                         a->profile.Global_Options |= GL_DTMF_SUPPORTED;
4953                 }
4954                 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
4955                 dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
4956                                 UnMapController(a->Id), a->profile.Global_Options,
4957                                 a->profile.B1_Protocols, a->profile.B2_Protocols,
4958                                 a->profile.B3_Protocols, a->manufacturer_features));
4959         }
4960         /* codec plci for the handset/hook state support is just an internal id  */
4961         if (plci != a->AdvCodecPLCI)
4962         {
4963                 force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
4964                 force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
4965                 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
4966                 SendInfo(plci, Id, parms, force_mt_info);
4967
4968                 VSwitchReqInd(plci, Id, multi_vswitch_parms);
4969
4970         }
4971
4972         /* switch the codec to the b-channel                                     */
4973         if (esc_chi[0] && plci && !plci->SuppState) {
4974                 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
4975                 mixer_set_bchannel_id_esc(plci, plci->b_channel);
4976                 dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
4977                 if (plci->tel == ADV_VOICE && plci->appl) {
4978                         SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
4979                 }
4980         }
4981
4982         if (plci->appl) plci->appl->Number++;
4983
4984         switch (plci->Sig.Ind) {
4985                 /* Response to Get_Supported_Services request */
4986         case S_SUPPORTED:
4987                 dbug(1, dprintf("S_Supported"));
4988                 if (!plci->appl) break;
4989                 if (pty_cai[0] == 4)
4990                 {
4991                         PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
4992                 }
4993                 else
4994                 {
4995                         PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
4996                 }
4997                 PUT_WORD(&CF_Ind[1], 0);
4998                 PUT_WORD(&CF_Ind[4], 0);
4999                 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
5000                 plci_remove(plci);
5001                 break;
5002
5003                 /* Supplementary Service rejected */
5004         case S_SERVICE_REJ:
5005                 dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5006                 if (!pty_cai[0]) break;
5007                 switch (pty_cai[5])
5008                 {
5009                 case ECT_EXECUTE:
5010                 case THREE_PTY_END:
5011                 case THREE_PTY_BEGIN:
5012                         if (!plci->relatedPTYPLCI) break;
5013                         tplci = plci->relatedPTYPLCI;
5014                         rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5015                         if (tplci->tel) rId |= EXT_CONTROLLER;
5016                         if (pty_cai[5] == ECT_EXECUTE)
5017                         {
5018                                 PUT_WORD(&SS_Ind[1], S_ECT);
5019
5020                                 plci->vswitchstate = 0;
5021                                 plci->relatedPTYPLCI->vswitchstate = 0;
5022
5023                         }
5024                         else
5025                         {
5026                                 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5027                         }
5028                         if (pty_cai[2] != 0xff)
5029                         {
5030                                 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5031                         }
5032                         else
5033                         {
5034                                 PUT_WORD(&SS_Ind[4], 0x300E);
5035                         }
5036                         plci->relatedPTYPLCI = NULL;
5037                         plci->ptyState = 0;
5038                         sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5039                         break;
5040
5041                 case CALL_DEFLECTION:
5042                         if (pty_cai[2] != 0xff)
5043                         {
5044                                 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5045                         }
5046                         else
5047                         {
5048                                 PUT_WORD(&SS_Ind[4], 0x300E);
5049                         }
5050                         PUT_WORD(&SS_Ind[1], pty_cai[5]);
5051                         for (i = 0; i < max_appl; i++)
5052                         {
5053                                 if (application[i].CDEnable)
5054                                 {
5055                                         if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5056                                         application[i].CDEnable = false;
5057                                 }
5058                         }
5059                         break;
5060
5061                 case DEACTIVATION_DIVERSION:
5062                 case ACTIVATION_DIVERSION:
5063                 case DIVERSION_INTERROGATE_CFU:
5064                 case DIVERSION_INTERROGATE_CFB:
5065                 case DIVERSION_INTERROGATE_CFNR:
5066                 case DIVERSION_INTERROGATE_NUM:
5067                 case CCBS_REQUEST:
5068                 case CCBS_DEACTIVATE:
5069                 case CCBS_INTERROGATE:
5070                         if (!plci->appl) break;
5071                         if (pty_cai[2] != 0xff)
5072                         {
5073                                 PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5074                         }
5075                         else
5076                         {
5077                                 PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5078                         }
5079                         switch (pty_cai[5])
5080                         {
5081                         case DEACTIVATION_DIVERSION:
5082                                 dbug(1, dprintf("Deact_Div"));
5083                                 Interr_Err_Ind[0] = 0x9;
5084                                 Interr_Err_Ind[3] = 0x6;
5085                                 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5086                                 break;
5087                         case ACTIVATION_DIVERSION:
5088                                 dbug(1, dprintf("Act_Div"));
5089                                 Interr_Err_Ind[0] = 0x9;
5090                                 Interr_Err_Ind[3] = 0x6;
5091                                 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5092                                 break;
5093                         case DIVERSION_INTERROGATE_CFU:
5094                         case DIVERSION_INTERROGATE_CFB:
5095                         case DIVERSION_INTERROGATE_CFNR:
5096                                 dbug(1, dprintf("Interr_Div"));
5097                                 Interr_Err_Ind[0] = 0xa;
5098                                 Interr_Err_Ind[3] = 0x7;
5099                                 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5100                                 break;
5101                         case DIVERSION_INTERROGATE_NUM:
5102                                 dbug(1, dprintf("Interr_Num"));
5103                                 Interr_Err_Ind[0] = 0xa;
5104                                 Interr_Err_Ind[3] = 0x7;
5105                                 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5106                                 break;
5107                         case CCBS_REQUEST:
5108                                 dbug(1, dprintf("CCBS Request"));
5109                                 Interr_Err_Ind[0] = 0xd;
5110                                 Interr_Err_Ind[3] = 0xa;
5111                                 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5112                                 break;
5113                         case CCBS_DEACTIVATE:
5114                                 dbug(1, dprintf("CCBS Deactivate"));
5115                                 Interr_Err_Ind[0] = 0x9;
5116                                 Interr_Err_Ind[3] = 0x6;
5117                                 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5118                                 break;
5119                         case CCBS_INTERROGATE:
5120                                 dbug(1, dprintf("CCBS Interrogate"));
5121                                 Interr_Err_Ind[0] = 0xb;
5122                                 Interr_Err_Ind[3] = 0x8;
5123                                 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5124                                 break;
5125                         }
5126                         PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5127                         sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5128                         plci_remove(plci);
5129                         break;
5130                 case ACTIVATION_MWI:
5131                 case DEACTIVATION_MWI:
5132                         if (pty_cai[5] == ACTIVATION_MWI)
5133                         {
5134                                 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5135                         }
5136                         else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5137
5138                         if (pty_cai[2] != 0xff)
5139                         {
5140                                 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5141                         }
5142                         else
5143                         {
5144                                 PUT_WORD(&SS_Ind[4], 0x300E);
5145                         }
5146
5147                         if (plci->cr_enquiry)
5148                         {
5149                                 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5150                                 plci_remove(plci);
5151                         }
5152                         else
5153                         {
5154                                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5155                         }
5156                         break;
5157                 case CONF_ADD: /* ERROR */
5158                 case CONF_BEGIN:
5159                 case CONF_DROP:
5160                 case CONF_ISOLATE:
5161                 case CONF_REATTACH:
5162                         CONF_Ind[0] = 9;
5163                         CONF_Ind[3] = 6;
5164                         switch (pty_cai[5])
5165                         {
5166                         case CONF_BEGIN:
5167                                 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5168                                 plci->ptyState = 0;
5169                                 break;
5170                         case CONF_DROP:
5171                                 CONF_Ind[0] = 5;
5172                                 CONF_Ind[3] = 2;
5173                                 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5174                                 plci->ptyState = CONNECTED;
5175                                 break;
5176                         case CONF_ISOLATE:
5177                                 CONF_Ind[0] = 5;
5178                                 CONF_Ind[3] = 2;
5179                                 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5180                                 plci->ptyState = CONNECTED;
5181                                 break;
5182                         case CONF_REATTACH:
5183                                 CONF_Ind[0] = 5;
5184                                 CONF_Ind[3] = 2;
5185                                 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5186                                 plci->ptyState = CONNECTED;
5187                                 break;
5188                         case CONF_ADD:
5189                                 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5190                                 plci->relatedPTYPLCI = NULL;
5191                                 tplci = plci->relatedPTYPLCI;
5192                                 if (tplci) tplci->ptyState = CONNECTED;
5193                                 plci->ptyState = CONNECTED;
5194                                 break;
5195                         }
5196
5197                         if (pty_cai[2] != 0xff)
5198                         {
5199                                 PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5200                         }
5201                         else
5202                         {
5203                                 PUT_WORD(&CONF_Ind[4], 0x3303); /* Time-out: network did not respond
5204                                                                   within the required time */
5205                         }
5206
5207                         PUT_DWORD(&CONF_Ind[6], 0x0);
5208                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5209                         break;
5210                 }
5211                 break;
5212
5213                 /* Supplementary Service indicates success */
5214         case S_SERVICE:
5215                 dbug(1, dprintf("Service_Ind"));
5216                 PUT_WORD(&CF_Ind[4], 0);
5217                 switch (pty_cai[5])
5218                 {
5219                 case THREE_PTY_END:
5220                 case THREE_PTY_BEGIN:
5221                 case ECT_EXECUTE:
5222                         if (!plci->relatedPTYPLCI) break;
5223                         tplci = plci->relatedPTYPLCI;
5224                         rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5225                         if (tplci->tel) rId |= EXT_CONTROLLER;
5226                         if (pty_cai[5] == ECT_EXECUTE)
5227                         {
5228                                 PUT_WORD(&SS_Ind[1], S_ECT);
5229
5230                                 if (plci->vswitchstate != 3)
5231                                 {
5232
5233                                         plci->ptyState = IDLE;
5234                                         plci->relatedPTYPLCI = NULL;
5235                                         plci->ptyState = 0;
5236
5237                                 }
5238
5239                                 dbug(1, dprintf("ECT OK"));
5240                                 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5241
5242
5243
5244                         }
5245                         else
5246                         {
5247                                 switch (plci->ptyState)
5248                                 {
5249                                 case S_3PTY_BEGIN:
5250                                         plci->ptyState = CONNECTED;
5251                                         dbug(1, dprintf("3PTY ON"));
5252                                         break;
5253
5254                                 case S_3PTY_END:
5255                                         plci->ptyState = IDLE;
5256                                         plci->relatedPTYPLCI = NULL;
5257                                         plci->ptyState = 0;
5258                                         dbug(1, dprintf("3PTY OFF"));
5259                                         break;
5260                                 }
5261                                 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5262                                 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5263                         }
5264                         break;
5265
5266                 case CALL_DEFLECTION:
5267                         PUT_WORD(&SS_Ind[1], pty_cai[5]);
5268                         for (i = 0; i < max_appl; i++)
5269                         {
5270                                 if (application[i].CDEnable)
5271                                 {
5272                                         if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5273                                         application[i].CDEnable = false;
5274                                 }
5275                         }
5276                         break;
5277
5278                 case DEACTIVATION_DIVERSION:
5279                 case ACTIVATION_DIVERSION:
5280                         if (!plci->appl) break;
5281                         PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5282                         PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5283                         sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5284                         plci_remove(plci);
5285                         break;
5286
5287                 case DIVERSION_INTERROGATE_CFU:
5288                 case DIVERSION_INTERROGATE_CFB:
5289                 case DIVERSION_INTERROGATE_CFNR:
5290                 case DIVERSION_INTERROGATE_NUM:
5291                 case CCBS_REQUEST:
5292                 case CCBS_DEACTIVATE:
5293                 case CCBS_INTERROGATE:
5294                         if (!plci->appl) break;
5295                         switch (pty_cai[5])
5296                         {
5297                         case DIVERSION_INTERROGATE_CFU:
5298                         case DIVERSION_INTERROGATE_CFB:
5299                         case DIVERSION_INTERROGATE_CFNR:
5300                                 dbug(1, dprintf("Interr_Div"));
5301                                 PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5302                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5303                                 break;
5304                         case DIVERSION_INTERROGATE_NUM:
5305                                 dbug(1, dprintf("Interr_Num"));
5306                                 PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5307                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5308                                 break;
5309                         case CCBS_REQUEST:
5310                                 dbug(1, dprintf("CCBS Request"));
5311                                 PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5312                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5313                                 break;
5314                         case CCBS_DEACTIVATE:
5315                                 dbug(1, dprintf("CCBS Deactivate"));
5316                                 PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5317                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5318                                 break;
5319                         case CCBS_INTERROGATE:
5320                                 dbug(1, dprintf("CCBS Interrogate"));
5321                                 PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5322                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5323                                 break;
5324                         }
5325                         PUT_WORD(&pty_cai[4], 0); /* Supplementary Service Reason */
5326                         PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5327                         sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5328                         plci_remove(plci);
5329                         break;
5330
5331                 case ACTIVATION_MWI:
5332                 case DEACTIVATION_MWI:
5333                         if (pty_cai[5] == ACTIVATION_MWI)
5334                         {
5335                                 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5336                         }
5337                         else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5338                         if (plci->cr_enquiry)
5339                         {
5340                                 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5341                                 plci_remove(plci);
5342                         }
5343                         else
5344                         {
5345                                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5346                         }
5347                         break;
5348                 case MWI_INDICATION:
5349                         if (pty_cai[0] >= 0x12)
5350                         {
5351                                 PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5352                                 pty_cai[2] = pty_cai[0] - 2; /* len Parameter */
5353                                 pty_cai[5] = pty_cai[0] - 5; /* Supplementary Service-specific parameter len */
5354                                 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5355                                 {
5356                                         if (plci->internal_command == GET_MWI_STATE) /* result on Message Waiting Listen */
5357                                         {
5358                                                 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5359                                                 plci_remove(plci);
5360                                                 return;
5361                                         }
5362                                         else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5363                                         pty_cai[0] = 0;
5364                                 }
5365                                 else
5366                                 {
5367                                         for (i = 0; i < max_appl; i++)
5368                                         {
5369                                                 if (a->Notification_Mask[i]&SMASK_MWI)
5370                                                 {
5371                                                         sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5372                                                         pty_cai[0] = 0;
5373                                                 }
5374                                         }
5375                                 }
5376
5377                                 if (!pty_cai[0])
5378                                 { /* acknowledge */
5379                                         facility[2] = 0; /* returncode */
5380                                 }
5381                                 else facility[2] = 0xff;
5382                         }
5383                         else
5384                         {
5385                                 /* reject */
5386                                 facility[2] = 0xff; /* returncode */
5387                         }
5388                         facility[0] = 2;
5389                         facility[1] = MWI_RESPONSE; /* Function */
5390                         add_p(plci, CAI, facility);
5391                         add_p(plci, ESC, multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5392                         sig_req(plci, S_SERVICE, 0);
5393                         send_req(plci);
5394                         plci->command = 0;
5395                         next_internal_command(Id, plci);
5396                         break;
5397                 case CONF_ADD: /* OK */
5398                 case CONF_BEGIN:
5399                 case CONF_DROP:
5400                 case CONF_ISOLATE:
5401                 case CONF_REATTACH:
5402                 case CONF_PARTYDISC:
5403                         CONF_Ind[0] = 9;
5404                         CONF_Ind[3] = 6;
5405                         switch (pty_cai[5])
5406                         {
5407                         case CONF_BEGIN:
5408                                 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5409                                 if (pty_cai[0] == 6)
5410                                 {
5411                                         d = pty_cai[6];
5412                                         PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5413                                 }
5414                                 else
5415                                 {
5416                                         PUT_DWORD(&CONF_Ind[6], 0x0);
5417                                 }
5418                                 break;
5419                         case CONF_ISOLATE:
5420                                 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5421                                 CONF_Ind[0] = 5;
5422                                 CONF_Ind[3] = 2;
5423                                 break;
5424                         case CONF_REATTACH:
5425                                 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5426                                 CONF_Ind[0] = 5;
5427                                 CONF_Ind[3] = 2;
5428                                 break;
5429                         case CONF_DROP:
5430                                 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5431                                 CONF_Ind[0] = 5;
5432                                 CONF_Ind[3] = 2;
5433                                 break;
5434                         case CONF_ADD:
5435                                 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5436                                 d = pty_cai[6];
5437                                 PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5438                                 tplci = plci->relatedPTYPLCI;
5439                                 if (tplci) tplci->ptyState = CONNECTED;
5440                                 break;
5441                         case CONF_PARTYDISC:
5442                                 CONF_Ind[0] = 7;
5443                                 CONF_Ind[3] = 4;
5444                                 PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5445                                 d = pty_cai[6];
5446                                 PUT_DWORD(&CONF_Ind[4], d); /* PartyID */
5447                                 break;
5448                         }
5449                         plci->ptyState = CONNECTED;
5450                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5451                         break;
5452                 case CCBS_INFO_RETAIN:
5453                 case CCBS_ERASECALLLINKAGEID:
5454                 case CCBS_STOP_ALERTING:
5455                         CONF_Ind[0] = 5;
5456                         CONF_Ind[3] = 2;
5457                         switch (pty_cai[5])
5458                         {
5459                         case CCBS_INFO_RETAIN:
5460                                 PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5461                                 break;
5462                         case CCBS_STOP_ALERTING:
5463                                 PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5464                                 break;
5465                         case CCBS_ERASECALLLINKAGEID:
5466                                 PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5467                                 CONF_Ind[0] = 7;
5468                                 CONF_Ind[3] = 4;
5469                                 CONF_Ind[6] = 0;
5470                                 CONF_Ind[7] = 0;
5471                                 break;
5472                         }
5473                         w = pty_cai[6];
5474                         PUT_WORD(&CONF_Ind[4], w); /* PartyID */
5475
5476                         if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5477                         {
5478                                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5479                         }
5480                         else
5481                         {
5482                                 for (i = 0; i < max_appl; i++)
5483                                         if (a->Notification_Mask[i] & SMASK_CCBS)
5484                                                 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5485                         }
5486                         break;
5487                 }
5488                 break;
5489         case CALL_HOLD_REJ:
5490                 cau = parms[7];
5491                 if (cau)
5492                 {
5493                         i = _L3_CAUSE | cau[2];
5494                         if (cau[2] == 0) i = 0x3603;
5495                 }
5496                 else
5497                 {
5498                         i = 0x3603;
5499                 }
5500                 PUT_WORD(&SS_Ind[1], S_HOLD);
5501                 PUT_WORD(&SS_Ind[4], i);
5502                 if (plci->SuppState == HOLD_REQUEST)
5503                 {
5504                         plci->SuppState = IDLE;
5505                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5506                 }
5507                 break;
5508
5509         case CALL_HOLD_ACK:
5510                 if (plci->SuppState == HOLD_REQUEST)
5511                 {
5512                         plci->SuppState = CALL_HELD;
5513                         CodecIdCheck(a, plci);
5514                         start_internal_command(Id, plci, hold_save_command);
5515                 }
5516                 break;
5517
5518         case CALL_RETRIEVE_REJ:
5519                 cau = parms[7];
5520                 if (cau)
5521                 {
5522                         i = _L3_CAUSE | cau[2];
5523                         if (cau[2] == 0) i = 0x3603;
5524                 }
5525                 else
5526                 {
5527                         i = 0x3603;
5528                 }
5529                 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5530                 PUT_WORD(&SS_Ind[4], i);
5531                 if (plci->SuppState == RETRIEVE_REQUEST)
5532                 {
5533                         plci->SuppState = CALL_HELD;
5534                         CodecIdCheck(a, plci);
5535                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5536                 }
5537                 break;
5538
5539         case CALL_RETRIEVE_ACK:
5540                 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5541                 if (plci->SuppState == RETRIEVE_REQUEST)
5542                 {
5543                         plci->SuppState = IDLE;
5544                         plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5545                         plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5546                         if (plci->tel)
5547                         {
5548                                 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5549                                 dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5550                                 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5551                                 if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5552                                 {
5553                                         dbug(1, dprintf("Get B-ch"));
5554                                         start_internal_command(Id, plci, retrieve_restore_command);
5555                                 }
5556                                 else
5557                                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5558                         }
5559                         else
5560                                 start_internal_command(Id, plci, retrieve_restore_command);
5561                 }
5562                 break;
5563
5564         case INDICATE_IND:
5565                 if (plci->State != LISTENING) {
5566                         sig_req(plci, HANGUP, 0);
5567                         send_req(plci);
5568                         break;
5569                 }
5570                 cip = find_cip(a, parms[4], parms[6]);
5571                 cip_mask = 1L << cip;
5572                 dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5573                 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5574                 if (!remove_started && !a->adapter_disabled)
5575                 {
5576                         group_optimization(a, plci);
5577                         for_each_set_bit(i, plci->group_optimization_mask_table, max_appl) {
5578                                 if (application[i].Id
5579                                     && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5580                                     && CPN_filter_ok(parms[0], a, i)) {
5581                                         dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5582                                         __set_bit(i, plci->c_ind_mask_table);
5583                                         dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
5584                                         plci->State = INC_CON_PENDING;
5585                                         plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5586                                                 CALL_DIR_IN | CALL_DIR_ANSWER;
5587                                         if (esc_chi[0]) {
5588                                                 plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5589                                                 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5590                                         }
5591                                         /* if a listen on the ext controller is done, check if hook states */
5592                                         /* are supported or if just a on board codec must be activated     */
5593                                         if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5594                                                 if (a->profile.Global_Options & HANDSET)
5595                                                         plci->tel = ADV_VOICE;
5596                                                 else if (a->profile.Global_Options & ON_BOARD_CODEC)
5597                                                         plci->tel = CODEC;
5598                                                 if (plci->tel) Id |= EXT_CONTROLLER;
5599                                                 a->codec_listen[i] = plci;
5600                                         }
5601
5602                                         sendf(&application[i], _CONNECT_I, Id, 0,
5603                                               "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5604                                               parms[0],    /* CalledPartyNumber   */
5605                                               multi_CiPN_parms[0],    /* CallingPartyNumber  */
5606                                               parms[2],    /* CalledPartySubad    */
5607                                               parms[3],    /* CallingPartySubad   */
5608                                               parms[4],    /* BearerCapability    */
5609                                               parms[5],    /* LowLC               */
5610                                               parms[6],    /* HighLC              */
5611                                               ai_len,      /* nested struct add_i */
5612                                               add_i[0],    /* B channel info    */
5613                                               add_i[1],    /* keypad facility   */
5614                                               add_i[2],    /* user user data    */
5615                                               add_i[3],    /* nested facility   */
5616                                               multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5617                                                 );
5618                                         SendSSExtInd(&application[i],
5619                                                      plci,
5620                                                      Id,
5621                                                      multi_ssext_parms);
5622                                         SendSetupInfo(&application[i],
5623                                                       plci,
5624                                                       Id,
5625                                                       parms,
5626                                                       SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5627                                 }
5628                         }
5629                         dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
5630                 }
5631                 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL)) {
5632                         sig_req(plci, HANGUP, 0);
5633                         send_req(plci);
5634                         plci->State = IDLE;
5635                 }
5636                 plci->notifiedcall = 0;
5637                 a->listen_active--;
5638                 listen_check(a);
5639                 break;
5640
5641         case CALL_PEND_NOTIFY:
5642                 plci->notifiedcall = 1;
5643                 listen_check(a);
5644                 break;
5645
5646         case CALL_IND:
5647         case CALL_CON:
5648                 if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5649                 {
5650                         if (plci->internal_command == PERM_COD_CONN_PEND)
5651                         {
5652                                 if (plci->State == ADVANCED_VOICE_NOSIG)
5653                                 {
5654                                         dbug(1, dprintf("***Codec OK"));
5655                                         if (a->AdvSignalPLCI)
5656                                         {
5657                                                 tplci = a->AdvSignalPLCI;
5658                                                 if (tplci->spoofed_msg)
5659                                                 {
5660                                                         dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5661                                                         tplci->command = 0;
5662                                                         tplci->internal_command = 0;
5663                                                         x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5664                                                         switch (tplci->spoofed_msg)
5665                                                         {
5666                                                         case CALL_RES:
5667                                                                 tplci->command = _CONNECT_I | RESPONSE;
5668                                                                 api_load_msg(&tplci->saved_msg, saved_parms);
5669                                                                 add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5670                                                                 if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5671                                                                 {
5672                                                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
5673                                                                         add_p(tplci, LLI, "\x01\x01");
5674                                                                 }
5675                                                                 add_s(tplci, CONN_NR, &saved_parms[2]);
5676                                                                 add_s(tplci, LLC, &saved_parms[4]);
5677                                                                 add_ai(tplci, &saved_parms[5]);
5678                                                                 tplci->State = INC_CON_ACCEPT;
5679                                                                 sig_req(tplci, CALL_RES, 0);
5680                                                                 send_req(tplci);
5681                                                                 break;
5682
5683                                                         case AWAITING_SELECT_B:
5684                                                                 dbug(1, dprintf("Select_B continue"));
5685                                                                 start_internal_command(x_Id, tplci, select_b_command);
5686                                                                 break;
5687
5688                                                         case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5689                                                                 if (!tplci->Sig.Id)
5690                                                                 {
5691                                                                         dbug(1, dprintf("No SigID!"));
5692                                                                         sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5693                                                                         plci_remove(tplci);
5694                                                                         break;
5695                                                                 }
5696                                                                 tplci->command = _MANUFACTURER_R;
5697                                                                 api_load_msg(&tplci->saved_msg, saved_parms);
5698                                                                 dir = saved_parms[2].info[0];
5699                                                                 if (dir == 1) {
5700                                                                         sig_req(tplci, CALL_REQ, 0);
5701                                                                 }
5702                                                                 else if (!dir) {
5703                                                                         sig_req(tplci, LISTEN_REQ, 0);
5704                                                                 }
5705                                                                 send_req(tplci);
5706                                                                 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5707                                                                 break;
5708
5709                                                         case (CALL_REQ | AWAITING_MANUF_CON):
5710                                                                 sig_req(tplci, CALL_REQ, 0);
5711                                                                 send_req(tplci);
5712                                                                 break;
5713
5714                                                         case CALL_REQ:
5715                                                                 if (!tplci->Sig.Id)
5716                                                                 {
5717                                                                         dbug(1, dprintf("No SigID!"));
5718                                                                         sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5719                                                                         plci_remove(tplci);
5720                                                                         break;
5721                                                                 }
5722                                                                 tplci->command = _CONNECT_R;
5723                                                                 api_load_msg(&tplci->saved_msg, saved_parms);
5724                                                                 add_s(tplci, CPN, &saved_parms[1]);
5725                                                                 add_s(tplci, DSA, &saved_parms[3]);
5726                                                                 add_ai(tplci, &saved_parms[9]);
5727                                                                 sig_req(tplci, CALL_REQ, 0);
5728                                                                 send_req(tplci);
5729                                                                 break;
5730
5731                                                         case CALL_RETRIEVE:
5732                                                                 tplci->command = C_RETRIEVE_REQ;
5733                                                                 sig_req(tplci, CALL_RETRIEVE, 0);
5734                                                                 send_req(tplci);
5735                                                                 break;
5736                                                         }
5737                                                         tplci->spoofed_msg = 0;
5738                                                         if (tplci->internal_command == 0)
5739                                                                 next_internal_command(x_Id, tplci);
5740                                                 }
5741                                         }
5742                                         next_internal_command(Id, plci);
5743                                         break;
5744                                 }
5745                                 dbug(1, dprintf("***Codec Hook Init Req"));
5746                                 plci->internal_command = PERM_COD_HOOK;
5747                                 add_p(plci, FTY, "\x01\x09");             /* Get Hook State*/
5748                                 sig_req(plci, TEL_CTRL, 0);
5749                                 send_req(plci);
5750                         }
5751                 }
5752                 else if (plci->command != _MANUFACTURER_R  /* old style permanent connect */
5753                          && plci->State != INC_ACT_PENDING)
5754                 {
5755                         mixer_set_bchannel_id_esc(plci, plci->b_channel);
5756                         if (plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5757                         {
5758                                 chi[2] = plci->b_channel;
5759                                 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5760                         }
5761                         sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5762                         plci->State = INC_ACT_PENDING;
5763                 }
5764                 break;
5765
5766         case TEL_CTRL:
5767                 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5768                 if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5769                         switch (ie[1] & 0x91) {
5770                         case 0x80:   /* hook off */
5771                         case 0x81:
5772                                 if (plci->internal_command == PERM_COD_HOOK)
5773                                 {
5774                                         dbug(1, dprintf("init:hook_off"));
5775                                         plci->hook_state = ie[1];
5776                                         next_internal_command(Id, plci);
5777                                         break;
5778                                 }
5779                                 else /* ignore doubled hook indications */
5780                                 {
5781                                         if (((plci->hook_state) & 0xf0) == 0x80)
5782                                         {
5783                                                 dbug(1, dprintf("ignore hook"));
5784                                                 break;
5785                                         }
5786                                         plci->hook_state = ie[1]&0x91;
5787                                 }
5788                                 /* check for incoming call pending */
5789                                 /* and signal '+'.Appl must decide */
5790                                 /* with connect_res if call must   */
5791                                 /* accepted or not                 */
5792                                 for (i = 0, tplci = NULL; i < max_appl; i++) {
5793                                         if (a->codec_listen[i]
5794                                             && (a->codec_listen[i]->State == INC_CON_PENDING
5795                                                 || a->codec_listen[i]->State == INC_CON_ALERT)) {
5796                                                 tplci = a->codec_listen[i];
5797                                                 tplci->appl = &application[i];
5798                                         }
5799                                 }
5800                                 /* no incoming call, do outgoing call */
5801                                 /* and signal '+' if outg. setup   */
5802                                 if (!a->AdvSignalPLCI && !tplci) {
5803                                         if ((i = get_plci(a))) {
5804                                                 a->AdvSignalPLCI = &a->plci[i - 1];
5805                                                 tplci = a->AdvSignalPLCI;
5806                                                 tplci->tel  = ADV_VOICE;
5807                                                 PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5808                                                 if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5809                                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
5810                                                         add_p(tplci, LLI, "\x01\x01");
5811                                                 }
5812                                                 add_p(tplci, CAI, voice_cai);
5813                                                 add_p(tplci, OAD, a->TelOAD);
5814                                                 add_p(tplci, OSA, a->TelOSA);
5815                                                 add_p(tplci, SHIFT | 6, NULL);
5816                                                 add_p(tplci, SIN, "\x02\x01\x00");
5817                                                 add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5818                                                 sig_req(tplci, ASSIGN, DSIG_ID);
5819                                                 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5820                                                 a->AdvSignalPLCI->command = 0;
5821                                                 tplci->appl = a->AdvSignalAppl;
5822                                                 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5823                                                 send_req(tplci);
5824                                         }
5825
5826                                 }
5827
5828                                 if (!tplci) break;
5829                                 Id = ((word)tplci->Id << 8) | a->Id;
5830                                 Id |= EXT_CONTROLLER;
5831                                 sendf(tplci->appl,
5832                                       _FACILITY_I,
5833                                       Id,
5834                                       0,
5835                                       "ws", (word)0, "\x01+");
5836                                 break;
5837
5838                         case 0x90:   /* hook on  */
5839                         case 0x91:
5840                                 if (plci->internal_command == PERM_COD_HOOK)
5841                                 {
5842                                         dbug(1, dprintf("init:hook_on"));
5843                                         plci->hook_state = ie[1] & 0x91;
5844                                         next_internal_command(Id, plci);
5845                                         break;
5846                                 }
5847                                 else /* ignore doubled hook indications */
5848                                 {
5849                                         if (((plci->hook_state) & 0xf0) == 0x90) break;
5850                                         plci->hook_state = ie[1] & 0x91;
5851                                 }
5852                                 /* hangup the adv. voice call and signal '-' to the appl */
5853                                 if (a->AdvSignalPLCI) {
5854                                         Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5855                                         if (plci->tel) Id |= EXT_CONTROLLER;
5856                                         sendf(a->AdvSignalAppl,
5857                                               _FACILITY_I,
5858                                               Id,
5859                                               0,
5860                                               "ws", (word)0, "\x01-");
5861                                         a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5862                                         a->AdvSignalPLCI->command = 0;
5863                                         sig_req(a->AdvSignalPLCI, HANGUP, 0);
5864                                         send_req(a->AdvSignalPLCI);
5865                                 }
5866                                 break;
5867                         }
5868                 }
5869                 break;
5870
5871         case RESUME:
5872                 __clear_bit(plci->appl->Id - 1, plci->c_ind_mask_table);
5873                 PUT_WORD(&resume_cau[4], GOOD);
5874                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
5875                 break;
5876
5877         case SUSPEND:
5878                 bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5879
5880                 if (plci->NL.Id && !plci->nl_remove_id) {
5881                         mixer_remove(plci);
5882                         nl_req_ncci(plci, REMOVE, 0);
5883                 }
5884                 if (!plci->sig_remove_id) {
5885                         plci->internal_command = 0;
5886                         sig_req(plci, REMOVE, 0);
5887                 }
5888                 send_req(plci);
5889                 if (!plci->channels) {
5890                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
5891                         sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
5892                 }
5893                 break;
5894
5895         case SUSPEND_REJ:
5896                 break;
5897
5898         case HANGUP:
5899                 plci->hangup_flow_ctrl_timer = 0;
5900                 if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
5901                 cau = parms[7];
5902                 if (cau) {
5903                         i = _L3_CAUSE | cau[2];
5904                         if (cau[2] == 0) i = 0;
5905                         else if (cau[2] == 8) i = _L1_ERROR;
5906                         else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
5907                         else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
5908                 }
5909                 else {
5910                         i = _L3_ERROR;
5911                 }
5912
5913                 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
5914                 {
5915                         for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
5916                                 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
5917                 }
5918                 else
5919                 {
5920                         bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5921                 }
5922                 if (!plci->appl)
5923                 {
5924                         if (plci->State == LISTENING)
5925                         {
5926                                 plci->notifiedcall = 0;
5927                                 a->listen_active--;
5928                         }
5929                         plci->State = INC_DIS_PENDING;
5930                         if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
5931                         {
5932                                 plci->State = IDLE;
5933                                 if (plci->NL.Id && !plci->nl_remove_id)
5934                                 {
5935                                         mixer_remove(plci);
5936                                         nl_req_ncci(plci, REMOVE, 0);
5937                                 }
5938                                 if (!plci->sig_remove_id)
5939                                 {
5940                                         plci->internal_command = 0;
5941                                         sig_req(plci, REMOVE, 0);
5942                                 }
5943                                 send_req(plci);
5944                         }
5945                 }
5946                 else
5947                 {
5948                         /* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
5949                         /* result in a second HANGUP! Don't generate another        */
5950                         /* DISCONNECT                                               */
5951                         if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
5952                         {
5953                                 if (plci->State == RESUMING)
5954                                 {
5955                                         PUT_WORD(&resume_cau[4], i);
5956                                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
5957                                 }
5958                                 plci->State = INC_DIS_PENDING;
5959                                 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
5960                         }
5961                 }
5962                 break;
5963
5964         case SSEXT_IND:
5965                 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5966                 break;
5967
5968         case VSWITCH_REQ:
5969                 VSwitchReqInd(plci, Id, multi_vswitch_parms);
5970                 break;
5971         case VSWITCH_IND:
5972                 if (plci->relatedPTYPLCI &&
5973                     plci->vswitchstate == 3 &&
5974                     plci->relatedPTYPLCI->vswitchstate == 3 &&
5975                     parms[MAXPARMSIDS - 1][0])
5976                 {
5977                         add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
5978                         sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
5979                         send_req(plci->relatedPTYPLCI);
5980                 }
5981                 else VSwitchReqInd(plci, Id, multi_vswitch_parms);
5982                 break;
5983
5984         }
5985 }
5986
5987
5988 static void SendSetupInfo(APPL *appl, PLCI *plci, dword Id, byte **parms, byte Info_Sent_Flag)
5989 {
5990         word i;
5991         byte *ie;
5992         word Info_Number;
5993         byte *Info_Element;
5994         word Info_Mask = 0;
5995
5996         dbug(1, dprintf("SetupInfo"));
5997
5998         for (i = 0; i < MAXPARMSIDS; i++) {
5999                 ie = parms[i];
6000                 Info_Number = 0;
6001                 Info_Element = ie;
6002                 if (ie[0]) {
6003                         switch (i) {
6004                         case 0:
6005                                 dbug(1, dprintf("CPN "));
6006                                 Info_Number = 0x0070;
6007                                 Info_Mask = 0x80;
6008                                 Info_Sent_Flag = true;
6009                                 break;
6010                         case 8:  /* display      */
6011                                 dbug(1, dprintf("display(%d)", i));
6012                                 Info_Number = 0x0028;
6013                                 Info_Mask = 0x04;
6014                                 Info_Sent_Flag = true;
6015                                 break;
6016                         case 16: /* Channel Id */
6017                                 dbug(1, dprintf("CHI"));
6018                                 Info_Number = 0x0018;
6019                                 Info_Mask = 0x100;
6020                                 Info_Sent_Flag = true;
6021                                 mixer_set_bchannel_id(plci, Info_Element);
6022                                 break;
6023                         case 19: /* Redirected Number */
6024                                 dbug(1, dprintf("RDN"));
6025                                 Info_Number = 0x0074;
6026                                 Info_Mask = 0x400;
6027                                 Info_Sent_Flag = true;
6028                                 break;
6029                         case 20: /* Redirected Number extended */
6030                                 dbug(1, dprintf("RDX"));
6031                                 Info_Number = 0x0073;
6032                                 Info_Mask = 0x400;
6033                                 Info_Sent_Flag = true;
6034                                 break;
6035                         case 22: /* Redirecing Number  */
6036                                 dbug(1, dprintf("RIN"));
6037                                 Info_Number = 0x0076;
6038                                 Info_Mask = 0x400;
6039                                 Info_Sent_Flag = true;
6040                                 break;
6041                         default:
6042                                 Info_Number = 0;
6043                                 break;
6044                         }
6045                 }
6046
6047                 if (i == MAXPARMSIDS - 2) { /* to indicate the message type "Setup" */
6048                         Info_Number = 0x8000 | 5;
6049                         Info_Mask = 0x10;
6050                         Info_Element = "";
6051                 }
6052
6053                 if (Info_Sent_Flag && Info_Number) {
6054                         if (plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask) {
6055                                 sendf(appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6056                         }
6057                 }
6058         }
6059 }
6060
6061
6062 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6063 {
6064         word i;
6065         word j;
6066         word k;
6067         byte *ie;
6068         word Info_Number;
6069         byte *Info_Element;
6070         word Info_Mask = 0;
6071         static byte charges[5] = {4, 0, 0, 0, 0};
6072         static byte cause[] = {0x02, 0x80, 0x00};
6073         APPL *appl;
6074
6075         dbug(1, dprintf("InfoParse "));
6076
6077         if (
6078                 !plci->appl
6079                 && !plci->State
6080                 && plci->Sig.Ind != NCR_FACILITY
6081                 )
6082         {
6083                 dbug(1, dprintf("NoParse "));
6084                 return;
6085         }
6086         cause[2] = 0;
6087         for (i = 0; i < MAXPARMSIDS; i++) {
6088                 ie = parms[i];
6089                 Info_Number = 0;
6090                 Info_Element = ie;
6091                 if (ie[0]) {
6092                         switch (i) {
6093                         case 0:
6094                                 dbug(1, dprintf("CPN "));
6095                                 Info_Number = 0x0070;
6096                                 Info_Mask   = 0x80;
6097                                 break;
6098                         case 7: /* ESC_CAU */
6099                                 dbug(1, dprintf("cau(0x%x)", ie[2]));
6100                                 Info_Number = 0x0008;
6101                                 Info_Mask = 0x00;
6102                                 cause[2] = ie[2];
6103                                 Info_Element = NULL;
6104                                 break;
6105                         case 8:  /* display      */
6106                                 dbug(1, dprintf("display(%d)", i));
6107                                 Info_Number = 0x0028;
6108                                 Info_Mask = 0x04;
6109                                 break;
6110                         case 9:  /* Date display */
6111                                 dbug(1, dprintf("date(%d)", i));
6112                                 Info_Number = 0x0029;
6113                                 Info_Mask = 0x02;
6114                                 break;
6115                         case 10: /* charges */
6116                                 for (j = 0; j < 4; j++) charges[1 + j] = 0;
6117                                 for (j = 0; j < ie[0] && !(ie[1 + j] & 0x80); j++);
6118                                 for (k = 1, j++; j < ie[0] && k <= 4; j++, k++) charges[k] = ie[1 + j];
6119                                 Info_Number = 0x4000;
6120                                 Info_Mask = 0x40;
6121                                 Info_Element = charges;
6122                                 break;
6123                         case 11: /* user user info */
6124                                 dbug(1, dprintf("uui"));
6125                                 Info_Number = 0x007E;
6126                                 Info_Mask = 0x08;
6127                                 break;
6128                         case 12: /* congestion receiver ready */
6129                                 dbug(1, dprintf("clRDY"));
6130                                 Info_Number = 0x00B0;
6131                                 Info_Mask = 0x08;
6132                                 Info_Element = "";
6133                                 break;
6134                         case 13: /* congestion receiver not ready */
6135                                 dbug(1, dprintf("clNRDY"));
6136                                 Info_Number = 0x00BF;
6137                                 Info_Mask = 0x08;
6138                                 Info_Element = "";
6139                                 break;
6140                         case 15: /* Keypad Facility */
6141                                 dbug(1, dprintf("KEY"));
6142                                 Info_Number = 0x002C;
6143                                 Info_Mask = 0x20;
6144                                 break;
6145                         case 16: /* Channel Id */
6146                                 dbug(1, dprintf("CHI"));
6147                                 Info_Number = 0x0018;
6148                                 Info_Mask = 0x100;
6149                                 mixer_set_bchannel_id(plci, Info_Element);
6150                                 break;
6151                         case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6152                                 dbug(1, dprintf("q9cau(0x%x)", ie[2]));
6153                                 if (!cause[2] || cause[2] < 0x80) break;  /* eg. layer 1 error */
6154                                 Info_Number = 0x0008;
6155                                 Info_Mask = 0x01;
6156                                 if (cause[2] != ie[2]) Info_Element = cause;
6157                                 break;
6158                         case 19: /* Redirected Number */
6159                                 dbug(1, dprintf("RDN"));
6160                                 Info_Number = 0x0074;
6161                                 Info_Mask = 0x400;
6162                                 break;
6163                         case 22: /* Redirecing Number  */
6164                                 dbug(1, dprintf("RIN"));
6165                                 Info_Number = 0x0076;
6166                                 Info_Mask = 0x400;
6167                                 break;
6168                         case 23: /* Notification Indicator  */
6169                                 dbug(1, dprintf("NI"));
6170                                 Info_Number = (word)NI;
6171                                 Info_Mask = 0x210;
6172                                 break;
6173                         case 26: /* Call State  */
6174                                 dbug(1, dprintf("CST"));
6175                                 Info_Number = (word)CST;
6176                                 Info_Mask = 0x01; /* do with cause i.e. for now */
6177                                 break;
6178                         case MAXPARMSIDS - 2:  /* Escape Message Type, must be the last indication */
6179                                 dbug(1, dprintf("ESC/MT[0x%x]", ie[3]));
6180                                 Info_Number = 0x8000 | ie[3];
6181                                 if (iesent) Info_Mask = 0xffff;
6182                                 else  Info_Mask = 0x10;
6183                                 Info_Element = "";
6184                                 break;
6185                         default:
6186                                 Info_Number  = 0;
6187                                 Info_Mask    = 0;
6188                                 Info_Element = "";
6189                                 break;
6190                         }
6191                 }
6192
6193                 if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6194                 {
6195                         for (j = 0; j < max_appl; j++)
6196                         {
6197                                 appl = &application[j];
6198                                 if (Info_Number
6199                                     && appl->Id
6200                                     && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6201                                 {
6202                                         dbug(1, dprintf("NCR_Ind"));
6203                                         iesent = true;
6204                                         sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6205                                 }
6206                         }
6207                 }
6208                 else if (!plci->appl)
6209                 { /* overlap receiving broadcast */
6210                         if (Info_Number == CPN
6211                             || Info_Number == KEY
6212                             || Info_Number == NI
6213                             || Info_Number == DSP
6214                             || Info_Number == UUI)
6215                         {
6216                                 for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
6217                                         dbug(1, dprintf("Ovl_Ind"));
6218                                         iesent = true;
6219                                         sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6220                                 }
6221                         }
6222                 }               /* all other signalling states */
6223                 else if (Info_Number
6224                          && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6225                 {
6226                         dbug(1, dprintf("Std_Ind"));
6227                         iesent = true;
6228                         sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6229                 }
6230         }
6231 }
6232
6233
6234 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6235                         dword info_mask, byte setupParse)
6236 {
6237         word i;
6238         word j;
6239         byte *ie;
6240         word Info_Number;
6241         byte *Info_Element;
6242         APPL *appl;
6243         word Info_Mask = 0;
6244         byte iesent = 0;
6245
6246         if (
6247                 !plci->appl
6248                 && !plci->State
6249                 && plci->Sig.Ind != NCR_FACILITY
6250                 && !setupParse
6251                 )
6252         {
6253                 dbug(1, dprintf("NoM-IEParse "));
6254                 return 0;
6255         }
6256         dbug(1, dprintf("M-IEParse "));
6257
6258         for (i = 0; i < MAX_MULTI_IE; i++)
6259         {
6260                 ie = parms[i];
6261                 Info_Number = 0;
6262                 Info_Element = ie;
6263                 if (ie[0])
6264                 {
6265                         dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci->Sig.Ind, ie_type));
6266                         Info_Number = (word)ie_type;
6267                         Info_Mask = (word)info_mask;
6268                 }
6269
6270                 if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6271                 {
6272                         for (j = 0; j < max_appl; j++)
6273                         {
6274                                 appl = &application[j];
6275                                 if (Info_Number
6276                                     && appl->Id
6277                                     && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6278                                 {
6279                                         iesent = true;
6280                                         dbug(1, dprintf("Mlt_NCR_Ind"));
6281                                         sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6282                                 }
6283                         }
6284                 }
6285                 else if (!plci->appl && Info_Number)
6286                 {                                        /* overlap receiving broadcast */
6287                         for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
6288                                 iesent = true;
6289                                 dbug(1, dprintf("Mlt_Ovl_Ind"));
6290                                 sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6291                         }
6292                 }                                        /* all other signalling states */
6293                 else if (Info_Number
6294                          && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6295                 {
6296                         iesent = true;
6297                         dbug(1, dprintf("Mlt_Std_Ind"));
6298                         sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6299                 }
6300         }
6301         return iesent;
6302 }
6303
6304 static void SendSSExtInd(APPL *appl, PLCI *plci, dword Id, byte **parms)
6305 {
6306         word i;
6307         /* Format of multi_ssext_parms[i][]:
6308            0 byte length
6309            1 byte SSEXTIE
6310            2 byte SSEXT_REQ/SSEXT_IND
6311            3 byte length
6312            4 word SSExtCommand
6313            6... Params
6314         */
6315         if (
6316                 plci
6317                 && plci->State
6318                 && plci->Sig.Ind != NCR_FACILITY
6319                 )
6320                 for (i = 0; i < MAX_MULTI_IE; i++)
6321                 {
6322                         if (parms[i][0] < 6) continue;
6323                         if (parms[i][2] == SSEXT_REQ) continue;
6324
6325                         if (appl)
6326                         {
6327                                 parms[i][0] = 0; /* kill it */
6328                                 sendf(appl, _MANUFACTURER_I,
6329                                       Id,
6330                                       0,
6331                                       "dwS",
6332                                       _DI_MANU_ID,
6333                                       _DI_SSEXT_CTRL,
6334                                       &parms[i][3]);
6335                         }
6336                         else if (plci->appl)
6337                         {
6338                                 parms[i][0] = 0; /* kill it */
6339                                 sendf(plci->appl, _MANUFACTURER_I,
6340                                       Id,
6341                                       0,
6342                                       "dwS",
6343                                       _DI_MANU_ID,
6344                                       _DI_SSEXT_CTRL,
6345                                       &parms[i][3]);
6346                         }
6347                 }
6348 };
6349
6350 static void nl_ind(PLCI *plci)
6351 {
6352         byte ch;
6353         word ncci;
6354         dword Id;
6355         DIVA_CAPI_ADAPTER *a;
6356         word NCCIcode;
6357         APPL *APPLptr;
6358         word count;
6359         word Num;
6360         word i, ncpi_state;
6361         byte len, ncci_state;
6362         word msg;
6363         word info = 0;
6364         word fax_feature_bits;
6365         byte fax_send_edata_ack;
6366         static byte v120_header_buffer[2 + 3];
6367         static word fax_info[] = {
6368                 0,                     /* T30_SUCCESS                        */
6369                 _FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
6370                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
6371                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
6372                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
6373                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
6374                 _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
6375                 _FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
6376                 _FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
6377                 _FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
6378                 _FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
6379                 _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
6380                 _FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
6381                 _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
6382                 _FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
6383                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
6384                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
6385                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
6386                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
6387                 _FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
6388                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
6389                 _FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
6390                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
6391                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
6392                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
6393                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
6394                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
6395                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
6396                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
6397                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
6398                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
6399                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
6400                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
6401                 0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
6402                 0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
6403                 0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
6404                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
6405                 _FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
6406                 _FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
6407                 _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
6408                 _FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
6409                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6410                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
6411                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
6412                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
6413                 _FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
6414                 _FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
6415         };
6416
6417         byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6418
6419
6420         static word rtp_info[] = {
6421                 GOOD,                  /* RTP_SUCCESS                       */
6422                 0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
6423         };
6424
6425         static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6426                 {
6427                         0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6428                         0x00000000, 0x00000000, 0x00000000, 0x00000000
6429                 };
6430
6431         ch = plci->NL.IndCh;
6432         a = plci->adapter;
6433         ncci = a->ch_ncci[ch];
6434         Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6435         if (plci->tel) Id |= EXT_CONTROLLER;
6436         APPLptr = plci->appl;
6437         dbug(1, dprintf("NL_IND-Id(NL:0x%x)=0x%08lx,plci=%x,tel=%x,state=0x%x,ch=0x%x,chs=%d,Ind=%x",
6438                         plci->NL.Id, Id, plci->Id, plci->tel, plci->State, ch, plci->channels, plci->NL.Ind & 0x0f));
6439
6440         /* in the case if no connect_active_Ind was sent to the appl we wait for */
6441
6442         if (plci->nl_remove_id)
6443         {
6444                 plci->NL.RNR = 2; /* discard */
6445                 dbug(1, dprintf("NL discard while remove pending"));
6446                 return;
6447         }
6448         if ((plci->NL.Ind & 0x0f) == N_CONNECT)
6449         {
6450                 if (plci->State == INC_DIS_PENDING
6451                     || plci->State == OUTG_DIS_PENDING
6452                     || plci->State == IDLE)
6453                 {
6454                         plci->NL.RNR = 2; /* discard */
6455                         dbug(1, dprintf("discard n_connect"));
6456                         return;
6457                 }
6458                 if (plci->State < INC_ACT_PENDING)
6459                 {
6460                         plci->NL.RNR = 1; /* flow control */
6461                         channel_x_off(plci, ch, N_XON_CONNECT_IND);
6462                         return;
6463                 }
6464         }
6465
6466         if (!APPLptr)                         /* no application or invalid data */
6467         {                                    /* while reloading the DSP        */
6468                 dbug(1, dprintf("discard1"));
6469                 plci->NL.RNR = 2;
6470                 return;
6471         }
6472
6473         if (((plci->NL.Ind & 0x0f) == N_UDATA)
6474             && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6475                 || (plci->B2_prot == 7)
6476                 || (plci->B3_prot == 7)))
6477         {
6478                 plci->ncpi_buffer[0] = 0;
6479
6480                 ncpi_state = plci->ncpi_state;
6481                 if (plci->NL.complete == 1)
6482                 {
6483                         byte *data = &plci->NL.RBuffer->P[0];
6484
6485                         if ((plci->NL.RBuffer->length >= 12)
6486                             && ((*data == DSP_UDATA_INDICATION_DCD_ON)
6487                                 || (*data == DSP_UDATA_INDICATION_CTS_ON)))
6488                         {
6489                                 word conn_opt, ncpi_opt = 0x00;
6490 /*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6491
6492                                 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6493                                         plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6494                                 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6495                                         plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6496
6497                                 data++;    /* indication code */
6498                                 data += 2; /* timestamp */
6499                                 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6500                                         ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6501                                 data++;    /* connected norm */
6502                                 conn_opt = GET_WORD(data);
6503                                 data += 2; /* connected options */
6504
6505                                 PUT_WORD(&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6506
6507                                 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6508                                 {
6509                                         ncpi_opt |= MDM_NCPI_ECM_V42;
6510                                 }
6511                                 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6512                                 {
6513                                         ncpi_opt |= MDM_NCPI_ECM_MNP;
6514                                 }
6515                                 else
6516                                 {
6517                                         ncpi_opt |= MDM_NCPI_TRANSPARENT;
6518                                 }
6519                                 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6520                                 {
6521                                         ncpi_opt |= MDM_NCPI_COMPRESSED;
6522                                 }
6523                                 PUT_WORD(&(plci->ncpi_buffer[3]), ncpi_opt);
6524                                 plci->ncpi_buffer[0] = 4;
6525
6526                                 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6527                         }
6528                 }
6529                 if (plci->B3_prot == 7)
6530                 {
6531                         if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6532                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6533                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6534                         {
6535                                 a->ncci_state[ncci] = INC_ACT_PENDING;
6536                                 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6537                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6538                         }
6539                 }
6540
6541                 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
6542                       & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6543                     || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6544                     || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6545
6546                 {
6547                         plci->NL.RNR = 2;
6548                         return;
6549                 }
6550         }
6551
6552         if (plci->NL.complete == 2)
6553         {
6554                 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6555                     && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6556                 {
6557                         switch (plci->RData[0].P[0])
6558                         {
6559
6560                         case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6561                                 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6562                                         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01X");
6563                                 break;
6564                         case DTMF_UDATA_INDICATION_ANSWER_TONE:
6565                                 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6566                                         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01Y");
6567                                 break;
6568                         case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6569                                 dtmf_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6570                                 break;
6571                         case DTMF_UDATA_INDICATION_DIGITS_SENT:
6572                                 dtmf_confirmation(Id, plci);
6573                                 break;
6574
6575
6576                         case UDATA_INDICATION_MIXER_TAP_DATA:
6577                                 capidtmf_recv_process_block(&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6578                                 i = capidtmf_indication(&(plci->capidtmf_state), dtmf_code_buffer + 1);
6579                                 if (i != 0)
6580                                 {
6581                                         dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6582                                         dtmf_indication(Id, plci, dtmf_code_buffer, (word)(i + 1));
6583                                 }
6584                                 break;
6585
6586
6587                         case UDATA_INDICATION_MIXER_COEFS_SET:
6588                                 mixer_indication_coefs_set(Id, plci);
6589                                 break;
6590                         case UDATA_INDICATION_XCONNECT_FROM:
6591                                 mixer_indication_xconnect_from(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6592                                 break;
6593                         case UDATA_INDICATION_XCONNECT_TO:
6594                                 mixer_indication_xconnect_to(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6595                                 break;
6596
6597
6598                         case LEC_UDATA_INDICATION_DISABLE_DETECT:
6599                                 ec_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6600                                 break;
6601
6602
6603
6604                         default:
6605                                 break;
6606                         }
6607                 }
6608                 else
6609                 {
6610                         if ((plci->RData[0].PLength != 0)
6611                             && ((plci->B2_prot == B2_V120_ASYNC)
6612                                 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6613                                 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6614                         {
6615
6616                                 sendf(plci->appl, _DATA_B3_I, Id, 0,
6617                                       "dwww",
6618                                       plci->RData[1].P,
6619                                       (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6620                                       plci->RNum,
6621                                       plci->RFlags);
6622
6623                         }
6624                         else
6625                         {
6626
6627                                 sendf(plci->appl, _DATA_B3_I, Id, 0,
6628                                       "dwww",
6629                                       plci->RData[0].P,
6630                                       plci->RData[0].PLength,
6631                                       plci->RNum,
6632                                       plci->RFlags);
6633
6634                         }
6635                 }
6636                 return;
6637         }
6638
6639         fax_feature_bits = 0;
6640         if ((plci->NL.Ind & 0x0f) == N_CONNECT ||
6641             (plci->NL.Ind & 0x0f) == N_CONNECT_ACK ||
6642             (plci->NL.Ind & 0x0f) == N_DISC ||
6643             (plci->NL.Ind & 0x0f) == N_EDATA ||
6644             (plci->NL.Ind & 0x0f) == N_DISC_ACK)
6645         {
6646                 info = 0;
6647                 plci->ncpi_buffer[0] = 0;
6648                 switch (plci->B3_prot) {
6649                 case  0: /*XPARENT*/
6650                 case  1: /*T.90 NL*/
6651                         break;    /* no network control protocol info - jfr */
6652                 case  2: /*ISO8202*/
6653                 case  3: /*X25 DCE*/
6654                         for (i = 0; i < plci->NL.RLength; i++) plci->ncpi_buffer[4 + i] = plci->NL.RBuffer->P[i];
6655                         plci->ncpi_buffer[0] = (byte)(i + 3);
6656                         plci->ncpi_buffer[1] = (byte)(plci->NL.Ind & N_D_BIT ? 1 : 0);
6657                         plci->ncpi_buffer[2] = 0;
6658                         plci->ncpi_buffer[3] = 0;
6659                         break;
6660                 case  4: /*T.30 - FAX*/
6661                 case  5: /*T.30 - FAX*/
6662                         if (plci->NL.RLength >= sizeof(T30_INFO))
6663                         {
6664                                 dbug(1, dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6665                                 len = 9;
6666                                 PUT_WORD(&(plci->ncpi_buffer[1]), ((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6667                                 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6668                                 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6669                                 if (plci->B3_prot == 5)
6670                                 {
6671                                         if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6672                                                 i |= 0x8000; /* This is not an ECM connection */
6673                                         if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6674                                                 i |= 0x4000; /* This is a connection with MMR compression */
6675                                         if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6676                                                 i |= 0x2000; /* This is a connection with MR compression */
6677                                         if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6678                                                 i |= 0x0004; /* More documents */
6679                                         if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6680                                                 i |= 0x0002; /* Fax-polling indication */
6681                                 }
6682                                 dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits, i));
6683                                 PUT_WORD(&(plci->ncpi_buffer[3]), i);
6684                                 PUT_WORD(&(plci->ncpi_buffer[5]), ((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6685                                 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6686                                 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6687                                 plci->ncpi_buffer[len] = 0;
6688                                 if (((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6689                                 {
6690                                         plci->ncpi_buffer[len] = 20;
6691                                         for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6692                                                 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6693                                 }
6694                                 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6695                                 {
6696                                         if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6697                                                 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6698                                         else
6699                                                 info = _FAX_PROTOCOL_ERROR;
6700                                 }
6701
6702                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6703                                     & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6704                                 {
6705                                         i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6706                                         while (i < plci->NL.RBuffer->length)
6707                                                 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6708                                 }
6709
6710                                 plci->ncpi_buffer[0] = len;
6711                                 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6712                                 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6713
6714                                 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6715                                 if (((plci->NL.Ind & 0x0f) == N_CONNECT_ACK)
6716                                     || (((plci->NL.Ind & 0x0f) == N_CONNECT)
6717                                         && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6718                                     || (((plci->NL.Ind & 0x0f) == N_EDATA)
6719                                         && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6720                                             || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6721                                             || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6722                                 {
6723                                         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6724                                 }
6725                                 if (((plci->NL.Ind & 0x0f) == N_DISC)
6726                                     || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)
6727                                     || (((plci->NL.Ind & 0x0f) == N_EDATA)
6728                                         && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6729                                 {
6730                                         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6731                                 }
6732                         }
6733                         break;
6734
6735                 case B3_RTP:
6736                         if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6737                         {
6738                                 if (plci->NL.RLength != 0)
6739                                 {
6740                                         info = rtp_info[plci->NL.RBuffer->P[0]];
6741                                         plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6742                                         for (i = 1; i < plci->NL.RLength; i++)
6743                                                 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6744                                 }
6745                         }
6746                         break;
6747
6748                 }
6749                 plci->NL.RNR = 2;
6750         }
6751         switch (plci->NL.Ind & 0x0f) {
6752         case N_EDATA:
6753                 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6754                 {
6755                         dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6756                                         ((T30_INFO *)plci->NL.RBuffer->P)->code));
6757                         fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6758
6759                         if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6760                             && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6761                             && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6762                             && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6763                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6764                             && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6765                         {
6766                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6767                                 sendf(plci->appl, _MANUFACTURER_I, Id, 0, "dwbS", _DI_MANU_ID, _DI_NEGOTIATE_B3,
6768                                       (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6769                                 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6770                                 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6771                                         fax_send_edata_ack = false;
6772                         }
6773
6774                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6775                         {
6776                                 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6777                                 {
6778                                 case EDATA_T30_DIS:
6779                                         if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6780                                             && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6781                                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6782                                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6783                                         {
6784                                                 a->ncci_state[ncci] = INC_ACT_PENDING;
6785                                                 if (plci->B3_prot == 4)
6786                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6787                                                 else
6788                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6789                                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6790                                         }
6791                                         break;
6792
6793                                 case EDATA_T30_TRAIN_OK:
6794                                         if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6795                                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6796                                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6797                                         {
6798                                                 if (plci->B3_prot == 4)
6799                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6800                                                 else
6801                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6802                                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6803                                         }
6804                                         break;
6805
6806                                 case EDATA_T30_EOP_CAPI:
6807                                         if (a->ncci_state[ncci] == CONNECTED)
6808                                         {
6809                                                 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", GOOD, plci->ncpi_buffer);
6810                                                 a->ncci_state[ncci] = INC_DIS_PENDING;
6811                                                 plci->ncpi_state = 0;
6812                                                 fax_send_edata_ack = false;
6813                                         }
6814                                         break;
6815                                 }
6816                         }
6817                         else
6818                         {
6819                                 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6820                                 {
6821                                 case EDATA_T30_TRAIN_OK:
6822                                         if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6823                                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6824                                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6825                                         {
6826                                                 if (plci->B3_prot == 4)
6827                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6828                                                 else
6829                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6830                                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6831                                         }
6832                                         break;
6833                                 }
6834                         }
6835                         if (fax_send_edata_ack)
6836                         {
6837                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6838                                 plci->fax_edata_ack_length = 1;
6839                                 start_internal_command(Id, plci, fax_edata_ack_command);
6840                         }
6841                 }
6842                 else
6843                 {
6844                         dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6845                 }
6846                 break;
6847         case N_CONNECT:
6848                 if (!a->ch_ncci[ch])
6849                 {
6850                         ncci = get_ncci(plci, ch, 0);
6851                         Id = (Id & 0xffff) | (((dword) ncci) << 16);
6852                 }
6853                 dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6854                                 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6855
6856                 msg = _CONNECT_B3_I;
6857                 if (a->ncci_state[ncci] == IDLE)
6858                         plci->channels++;
6859                 else if (plci->B3_prot == 1)
6860                         msg = _CONNECT_B3_T90_ACTIVE_I;
6861
6862                 a->ncci_state[ncci] = INC_CON_PENDING;
6863                 if (plci->B3_prot == 4)
6864                         sendf(plci->appl, msg, Id, 0, "s", "");
6865                 else
6866                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6867                 break;
6868         case N_CONNECT_ACK:
6869                 dbug(1, dprintf("N_connect_Ack"));
6870                 if (plci->internal_command_queue[0]
6871                     && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6872                         || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6873                         || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6874                 {
6875                         (*(plci->internal_command_queue[0]))(Id, plci, 0);
6876                         if (!plci->internal_command)
6877                                 next_internal_command(Id, plci);
6878                         break;
6879                 }
6880                 msg = _CONNECT_B3_ACTIVE_I;
6881                 if (plci->B3_prot == 1)
6882                 {
6883                         if (a->ncci_state[ncci] != OUTG_CON_PENDING)
6884                                 msg = _CONNECT_B3_T90_ACTIVE_I;
6885                         a->ncci_state[ncci] = INC_ACT_PENDING;
6886                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6887                 }
6888                 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
6889                 {
6890                         if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6891                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6892                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6893                         {
6894                                 a->ncci_state[ncci] = INC_ACT_PENDING;
6895                                 if (plci->B3_prot == 4)
6896                                         sendf(plci->appl, msg, Id, 0, "s", "");
6897                                 else
6898                                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6899                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6900                         }
6901                 }
6902                 else
6903                 {
6904                         a->ncci_state[ncci] = INC_ACT_PENDING;
6905                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6906                 }
6907                 if (plci->adjust_b_restore)
6908                 {
6909                         plci->adjust_b_restore = false;
6910                         start_internal_command(Id, plci, adjust_b_restore);
6911                 }
6912                 break;
6913         case N_DISC:
6914         case N_DISC_ACK:
6915                 if (plci->internal_command_queue[0]
6916                     && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
6917                         || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
6918                         || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
6919                 {
6920                         (*(plci->internal_command_queue[0]))(Id, plci, 0);
6921                         if (!plci->internal_command)
6922                                 next_internal_command(Id, plci);
6923                 }
6924                 ncci_state = a->ncci_state[ncci];
6925                 ncci_remove(plci, ncci, false);
6926
6927                 /* with N_DISC or N_DISC_ACK the IDI frees the respective   */
6928                 /* channel, so we cannot store the state in ncci_state! The */
6929                 /* information which channel we received a N_DISC is thus   */
6930                 /* stored in the inc_dis_ncci_table buffer.                 */
6931                 for (i = 0; plci->inc_dis_ncci_table[i]; i++);
6932                 plci->inc_dis_ncci_table[i] = (byte) ncci;
6933
6934                 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
6935                 if (!plci->channels
6936                     && (plci->B1_resource == 16)
6937                     && (plci->State <= CONNECTED))
6938                 {
6939                         len = 9;
6940                         i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
6941                         PUT_WORD(&plci->ncpi_buffer[1], i);
6942                         PUT_WORD(&plci->ncpi_buffer[3], 0);
6943                         i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
6944                         PUT_WORD(&plci->ncpi_buffer[5], i);
6945                         PUT_WORD(&plci->ncpi_buffer[7], 0);
6946                         plci->ncpi_buffer[len] = 0;
6947                         plci->ncpi_buffer[0] = len;
6948                         if (plci->B3_prot == 4)
6949                                 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "s", "");
6950                         else
6951                         {
6952
6953                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6954                                     & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6955                                 {
6956                                         plci->ncpi_buffer[++len] = 0;
6957                                         plci->ncpi_buffer[++len] = 0;
6958                                         plci->ncpi_buffer[++len] = 0;
6959                                         plci->ncpi_buffer[0] = len;
6960                                 }
6961
6962                                 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "S", plci->ncpi_buffer);
6963                         }
6964                         sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
6965                         plci->ncpi_state = 0;
6966                         sig_req(plci, HANGUP, 0);
6967                         send_req(plci);
6968                         plci->State = OUTG_DIS_PENDING;
6969                         /* disc here */
6970                 }
6971                 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6972                          && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6973                          && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
6974                 {
6975                         if (ncci_state == IDLE)
6976                         {
6977                                 if (plci->channels)
6978                                         plci->channels--;
6979                                 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
6980                                         if (plci->State == SUSPENDING) {
6981                                                 sendf(plci->appl,
6982                                                       _FACILITY_I,
6983                                                       Id & 0xffffL,
6984                                                       0,
6985                                                       "ws", (word)3, "\x03\x04\x00\x00");
6986                                                 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
6987                                         }
6988                                         plci_remove(plci);
6989                                         plci->State = IDLE;
6990                                 }
6991                         }
6992                 }
6993                 else if (plci->channels)
6994                 {
6995                         sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
6996                         plci->ncpi_state = 0;
6997                         if ((ncci_state == OUTG_REJ_PENDING)
6998                             && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
6999                         {
7000                                 sig_req(plci, HANGUP, 0);
7001                                 send_req(plci);
7002                                 plci->State = OUTG_DIS_PENDING;
7003                         }
7004                 }
7005                 break;
7006         case N_RESET:
7007                 a->ncci_state[ncci] = INC_RES_PENDING;
7008                 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7009                 break;
7010         case N_RESET_ACK:
7011                 a->ncci_state[ncci] = CONNECTED;
7012                 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7013                 break;
7014
7015         case N_UDATA:
7016                 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7017                 {
7018                         plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7019                         plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7020                         plci->NL.R = plci->RData;
7021                         plci->NL.RNum = 1;
7022                         return;
7023                 }
7024                 /* fall through */
7025         case N_BDATA:
7026         case N_DATA:
7027                 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7028                     || (a->ncci_state[ncci] == IDLE)
7029                     || (a->ncci_state[ncci] == INC_DIS_PENDING))
7030                 {
7031                         plci->NL.RNR = 2;
7032                         break;
7033                 }
7034                 if ((a->ncci_state[ncci] != CONNECTED)
7035                     && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7036                     && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7037                 {
7038                         dbug(1, dprintf("flow control"));
7039                         plci->NL.RNR = 1; /* flow control  */
7040                         channel_x_off(plci, ch, 0);
7041                         break;
7042                 }
7043
7044                 NCCIcode = ncci | (((word)a->Id) << 8);
7045
7046                 /* count all buffers within the Application pool    */
7047                 /* belonging to the same NCCI. If this is below the */
7048                 /* number of buffers available per NCCI we accept   */
7049                 /* this packet, otherwise we reject it              */
7050                 count = 0;
7051                 Num = 0xffff;
7052                 for (i = 0; i < APPLptr->MaxBuffer; i++) {
7053                         if (NCCIcode == APPLptr->DataNCCI[i]) count++;
7054                         if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
7055                 }
7056
7057                 if (count >= APPLptr->MaxNCCIData || Num == 0xffff)
7058                 {
7059                         dbug(3, dprintf("Flow-Control"));
7060                         plci->NL.RNR = 1;
7061                         if (++(APPLptr->NCCIDataFlowCtrlTimer) >=
7062                             (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7063                         {
7064                                 plci->NL.RNR = 2;
7065                                 dbug(3, dprintf("DiscardData"));
7066                         } else {
7067                                 channel_x_off(plci, ch, 0);
7068                         }
7069                         break;
7070                 }
7071                 else
7072                 {
7073                         APPLptr->NCCIDataFlowCtrlTimer = 0;
7074                 }
7075
7076                 plci->RData[0].P = ReceiveBufferGet(APPLptr, Num);
7077                 if (!plci->RData[0].P) {
7078                         plci->NL.RNR = 1;
7079                         channel_x_off(plci, ch, 0);
7080                         break;
7081                 }
7082
7083                 APPLptr->DataNCCI[Num] = NCCIcode;
7084                 APPLptr->DataFlags[Num] = (plci->Id << 8) | (plci->NL.Ind >> 4);
7085                 dbug(3, dprintf("Buffer(%d), Max = %d", Num, APPLptr->MaxBuffer));
7086
7087                 plci->RNum = Num;
7088                 plci->RFlags = plci->NL.Ind >> 4;
7089                 plci->RData[0].PLength = APPLptr->MaxDataLength;
7090                 plci->NL.R = plci->RData;
7091                 if ((plci->NL.RLength != 0)
7092                     && ((plci->B2_prot == B2_V120_ASYNC)
7093                         || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7094                         || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7095                 {
7096                         plci->RData[1].P = plci->RData[0].P;
7097                         plci->RData[1].PLength = plci->RData[0].PLength;
7098                         plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7099                         if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7100                                 plci->RData[0].PLength = 1;
7101                         else
7102                                 plci->RData[0].PLength = 2;
7103                         if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7104                                 plci->RFlags |= 0x0010;
7105                         if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7106                                 plci->RFlags |= 0x8000;
7107                         plci->NL.RNum = 2;
7108                 }
7109                 else
7110                 {
7111                         if ((plci->NL.Ind & 0x0f) == N_UDATA)
7112                                 plci->RFlags |= 0x0010;
7113
7114                         else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7115                                 plci->RFlags |= 0x0001;
7116
7117                         plci->NL.RNum = 1;
7118                 }
7119                 break;
7120         case N_DATA_ACK:
7121                 data_ack(plci, ch);
7122                 break;
7123         default:
7124                 plci->NL.RNR = 2;
7125                 break;
7126         }
7127 }
7128
7129 /*------------------------------------------------------------------*/
7130 /* find a free PLCI */
7131 /*------------------------------------------------------------------*/
7132
7133 static word get_plci(DIVA_CAPI_ADAPTER *a)
7134 {
7135         word i, j;
7136         PLCI *plci;
7137
7138         for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
7139         if (i == a->max_plci) {
7140                 dbug(1, dprintf("get_plci: out of PLCIs"));
7141                 return 0;
7142         }
7143         plci = &a->plci[i];
7144         plci->Id = (byte)(i + 1);
7145
7146         plci->Sig.Id = 0;
7147         plci->NL.Id = 0;
7148         plci->sig_req = 0;
7149         plci->nl_req = 0;
7150
7151         plci->appl = NULL;
7152         plci->relatedPTYPLCI = NULL;
7153         plci->State = IDLE;
7154         plci->SuppState = IDLE;
7155         plci->channels = 0;
7156         plci->tel = 0;
7157         plci->B1_resource = 0;
7158         plci->B2_prot = 0;
7159         plci->B3_prot = 0;
7160
7161         plci->command = 0;
7162         plci->m_command = 0;
7163         init_internal_command_queue(plci);
7164         plci->number = 0;
7165         plci->req_in_start = 0;
7166         plci->req_in = 0;
7167         plci->req_out = 0;
7168         plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7169         plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7170         plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7171
7172         plci->data_sent = false;
7173         plci->send_disc = 0;
7174         plci->sig_global_req = 0;
7175         plci->sig_remove_id = 0;
7176         plci->nl_global_req = 0;
7177         plci->nl_remove_id = 0;
7178         plci->adv_nl = 0;
7179         plci->manufacturer = false;
7180         plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7181         plci->spoofed_msg = 0;
7182         plci->ptyState = 0;
7183         plci->cr_enquiry = false;
7184         plci->hangup_flow_ctrl_timer = 0;
7185
7186         plci->ncci_ring_list = 0;
7187         for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
7188         bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
7189         bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
7190         plci->fax_connect_info_length = 0;
7191         plci->nsf_control_bits = 0;
7192         plci->ncpi_state = 0x00;
7193         plci->ncpi_buffer[0] = 0;
7194
7195         plci->requested_options_conn = 0;
7196         plci->requested_options = 0;
7197         plci->notifiedcall = 0;
7198         plci->vswitchstate = 0;
7199         plci->vsprot = 0;
7200         plci->vsprotdialect = 0;
7201         init_b1_config(plci);
7202         dbug(1, dprintf("get_plci(%x)", plci->Id));
7203         return i + 1;
7204 }
7205
7206 /*------------------------------------------------------------------*/
7207 /* put a parameter in the parameter buffer                          */
7208 /*------------------------------------------------------------------*/
7209
7210 static void add_p(PLCI *plci, byte code, byte *p)
7211 {
7212         word p_length;
7213
7214         p_length = 0;
7215         if (p) p_length = p[0];
7216         add_ie(plci, code, p, p_length);
7217 }
7218
7219 /*------------------------------------------------------------------*/
7220 /* put a structure in the parameter buffer                          */
7221 /*------------------------------------------------------------------*/
7222 static void add_s(PLCI *plci, byte code, API_PARSE *p)
7223 {
7224         if (p) add_ie(plci, code, p->info, (word)p->length);
7225 }
7226
7227 /*------------------------------------------------------------------*/
7228 /* put multiple structures in the parameter buffer                  */
7229 /*------------------------------------------------------------------*/
7230 static void add_ss(PLCI *plci, byte code, API_PARSE *p)
7231 {
7232         byte i;
7233
7234         if (p) {
7235                 dbug(1, dprintf("add_ss(%x,len=%d)", code, p->length));
7236                 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7237                         dbug(1, dprintf("add_ss_ie(%x,len=%d)", p->info[i - 1], p->info[i]));
7238                         add_ie(plci, p->info[i - 1], (byte *)&(p->info[i]), (word)p->info[i]);
7239                 }
7240         }
7241 }
7242
7243 /*------------------------------------------------------------------*/
7244 /* return the channel number sent by the application in a esc_chi   */
7245 /*------------------------------------------------------------------*/
7246 static byte getChannel(API_PARSE *p)
7247 {
7248         byte i;
7249
7250         if (p) {
7251                 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7252                         if (p->info[i] == 2) {
7253                                 if (p->info[i - 1] == ESC && p->info[i + 1] == CHI) return (p->info[i + 2]);
7254                         }
7255                 }
7256         }
7257         return 0;
7258 }
7259
7260
7261 /*------------------------------------------------------------------*/
7262 /* put an information element in the parameter buffer               */
7263 /*------------------------------------------------------------------*/
7264
7265 static void add_ie(PLCI *plci, byte code, byte *p, word p_length)
7266 {
7267         word i;
7268
7269         if (!(code & 0x80) && !p_length) return;
7270
7271         if (plci->req_in == plci->req_in_start) {
7272                 plci->req_in += 2;
7273         }
7274         else {
7275                 plci->req_in--;
7276         }
7277         plci->RBuffer[plci->req_in++] = code;
7278
7279         if (p) {
7280                 plci->RBuffer[plci->req_in++] = (byte)p_length;
7281                 for (i = 0; i < p_length; i++) plci->RBuffer[plci->req_in++] = p[1 + i];
7282         }
7283
7284         plci->RBuffer[plci->req_in++] = 0;
7285 }
7286
7287 /*------------------------------------------------------------------*/
7288 /* put a unstructured data into the buffer                          */
7289 /*------------------------------------------------------------------*/
7290
7291 static void add_d(PLCI *plci, word length, byte *p)
7292 {
7293         word i;
7294
7295         if (plci->req_in == plci->req_in_start) {
7296                 plci->req_in += 2;
7297         }
7298         else {
7299                 plci->req_in--;
7300         }
7301         for (i = 0; i < length; i++) plci->RBuffer[plci->req_in++] = p[i];
7302 }
7303
7304 /*------------------------------------------------------------------*/
7305 /* put parameters from the Additional Info parameter in the         */
7306 /* parameter buffer                                                 */
7307 /*------------------------------------------------------------------*/
7308
7309 static void add_ai(PLCI *plci, API_PARSE *ai)
7310 {
7311         word i;
7312         API_PARSE ai_parms[5];
7313
7314         for (i = 0; i < 5; i++) ai_parms[i].length = 0;
7315
7316         if (!ai->length)
7317                 return;
7318         if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7319                 return;
7320
7321         add_s(plci, KEY, &ai_parms[1]);
7322         add_s(plci, UUI, &ai_parms[2]);
7323         add_ss(plci, FTY, &ai_parms[3]);
7324 }
7325
7326 /*------------------------------------------------------------------*/
7327 /* put parameter for b1 protocol in the parameter buffer            */
7328 /*------------------------------------------------------------------*/
7329
7330 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7331                    word b1_facilities)
7332 {
7333         API_PARSE bp_parms[8];
7334         API_PARSE mdm_cfg[9];
7335         API_PARSE global_config[2];
7336         byte cai[256];
7337         byte resource[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7338         byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7339         word i;
7340
7341         API_PARSE mdm_cfg_v18[4];
7342         word j, n, w;
7343         dword d;
7344
7345
7346         for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7347         for (i = 0; i < 2; i++) global_config[i].length = 0;
7348
7349         dbug(1, dprintf("add_b1"));
7350         api_save_msg(bp, "s", &plci->B_protocol);
7351
7352         if (b_channel_info == 2) {
7353                 plci->B1_resource = 0;
7354                 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7355                 add_p(plci, CAI, "\x01\x00");
7356                 dbug(1, dprintf("Cai=1,0 (no resource)"));
7357                 return 0;
7358         }
7359
7360         if (plci->tel == CODEC_PERMANENT) return 0;
7361         else if (plci->tel == CODEC) {
7362                 plci->B1_resource = 1;
7363                 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7364                 add_p(plci, CAI, "\x01\x01");
7365                 dbug(1, dprintf("Cai=1,1 (Codec)"));
7366                 return 0;
7367         }
7368         else if (plci->tel == ADV_VOICE) {
7369                 plci->B1_resource = add_b1_facilities(plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7370                 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7371                 voice_cai[1] = plci->B1_resource;
7372                 PUT_WORD(&voice_cai[5], plci->appl->MaxDataLength);
7373                 add_p(plci, CAI, voice_cai);
7374                 dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai[1]));
7375                 return 0;
7376         }
7377         plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7378         if (plci->call_dir & CALL_DIR_OUT)
7379                 plci->call_dir |= CALL_DIR_ORIGINATE;
7380         else if (plci->call_dir & CALL_DIR_IN)
7381                 plci->call_dir |= CALL_DIR_ANSWER;
7382
7383         if (!bp->length) {
7384                 plci->B1_resource = 0x5;
7385                 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7386                 add_p(plci, CAI, "\x01\x05");
7387                 return 0;
7388         }
7389
7390         dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7391         if (bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7392         if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7393         {
7394                 bp_parms[6].length = 0;
7395                 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7396                 {
7397                         dbug(1, dprintf("b-form.!"));
7398                         return _WRONG_MESSAGE_FORMAT;
7399                 }
7400         }
7401         else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7402         {
7403                 dbug(1, dprintf("b-form.!"));
7404                 return _WRONG_MESSAGE_FORMAT;
7405         }
7406
7407         if (bp_parms[6].length)
7408         {
7409                 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7410                 {
7411                         return _WRONG_MESSAGE_FORMAT;
7412                 }
7413                 switch (GET_WORD(global_config[0].info))
7414                 {
7415                 case 1:
7416                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7417                         break;
7418                 case 2:
7419                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7420                         break;
7421                 }
7422         }
7423         dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7424
7425
7426         if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7427             && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7428         {
7429                 plci->B1_resource = add_b1_facilities(plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7430                 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7431                 cai[1] = plci->B1_resource;
7432                 cai[2] = 0;
7433                 cai[3] = 0;
7434                 cai[4] = 0;
7435                 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7436                 for (i = 0; i < bp_parms[3].length; i++)
7437                         cai[7 + i] = bp_parms[3].info[1 + i];
7438                 cai[0] = 6 + bp_parms[3].length;
7439                 add_p(plci, CAI, cai);
7440                 return 0;
7441         }
7442
7443
7444         if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7445             && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7446         {
7447                 plci->B1_resource = add_b1_facilities(plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7448                 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7449                 cai[1] = plci->B1_resource;
7450                 cai[2] = 0;
7451                 cai[3] = 0;
7452                 cai[4] = 0;
7453                 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7454                 cai[0] = 6;
7455                 add_p(plci, CAI, cai);
7456                 return 0;
7457         }
7458
7459
7460         if ((GET_WORD(bp_parms[0].info) >= 32)
7461             || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7462                 && ((GET_WORD(bp_parms[0].info) != 3)
7463                     || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7464                     || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7465         {
7466                 return _B1_NOT_SUPPORTED;
7467         }
7468         plci->B1_resource = add_b1_facilities(plci, resource[GET_WORD(bp_parms[0].info)],
7469                                               (word)(b1_facilities & ~B1_FACILITY_VOICE));
7470         adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7471         cai[0] = 6;
7472         cai[1] = plci->B1_resource;
7473         for (i = 2; i < sizeof(cai); i++) cai[i] = 0;
7474
7475         if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7476             || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7477             || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7478         { /* B1 - modem */
7479                 for (i = 0; i < 7; i++) mdm_cfg[i].length = 0;
7480
7481                 if (bp_parms[3].length)
7482                 {
7483                         if (api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwww", mdm_cfg))
7484                         {
7485                                 return (_WRONG_MESSAGE_FORMAT);
7486                         }
7487
7488                         cai[2] = 0; /* Bit rate for adaptation */
7489
7490                         dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7491
7492                         PUT_WORD(&cai[13], 0);                          /* Min Tx speed */
7493                         PUT_WORD(&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7494                         PUT_WORD(&cai[17], 0);                          /* Min Rx speed */
7495                         PUT_WORD(&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7496
7497                         cai[3] = 0; /* Async framing parameters */
7498                         switch (GET_WORD(mdm_cfg[2].info))
7499                         {       /* Parity     */
7500                         case 1: /* odd parity */
7501                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7502                                 dbug(1, dprintf("MDM: odd parity"));
7503                                 break;
7504
7505                         case 2: /* even parity */
7506                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7507                                 dbug(1, dprintf("MDM: even parity"));
7508                                 break;
7509
7510                         default:
7511                                 dbug(1, dprintf("MDM: no parity"));
7512                                 break;
7513                         }
7514
7515                         switch (GET_WORD(mdm_cfg[3].info))
7516                         {       /* stop bits   */
7517                         case 1: /* 2 stop bits */
7518                                 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7519                                 dbug(1, dprintf("MDM: 2 stop bits"));
7520                                 break;
7521
7522                         default:
7523                                 dbug(1, dprintf("MDM: 1 stop bit"));
7524                                 break;
7525                         }
7526
7527                         switch (GET_WORD(mdm_cfg[1].info))
7528                         {     /* char length */
7529                         case 5:
7530                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7531                                 dbug(1, dprintf("MDM: 5 bits"));
7532                                 break;
7533
7534                         case 6:
7535                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7536                                 dbug(1, dprintf("MDM: 6 bits"));
7537                                 break;
7538
7539                         case 7:
7540                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7541                                 dbug(1, dprintf("MDM: 7 bits"));
7542                                 break;
7543
7544                         default:
7545                                 dbug(1, dprintf("MDM: 8 bits"));
7546                                 break;
7547                         }
7548
7549                         cai[7] = 0; /* Line taking options */
7550                         cai[8] = 0; /* Modulation negotiation options */
7551                         cai[9] = 0; /* Modulation options */
7552
7553                         if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7554                         {
7555                                 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7556                                 dbug(1, dprintf("MDM: Reverse direction"));
7557                         }
7558
7559                         if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7560                         {
7561                                 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7562                                 dbug(1, dprintf("MDM: Disable retrain"));
7563                         }
7564
7565                         if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7566                         {
7567                                 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7568                                 dbug(1, dprintf("MDM: Disable ring tone"));
7569                         }
7570
7571                         if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7572                         {
7573                                 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7574                                 dbug(1, dprintf("MDM: 1800 guard tone"));
7575                         }
7576                         else if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_550)
7577                         {
7578                                 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7579                                 dbug(1, dprintf("MDM: 550 guard tone"));
7580                         }
7581
7582                         if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7583                         {
7584                                 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7585                                 dbug(1, dprintf("MDM: V100"));
7586                         }
7587                         else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7588                         {
7589                                 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7590                                 dbug(1, dprintf("MDM: IN CLASS"));
7591                         }
7592                         else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7593                         {
7594                                 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7595                                 dbug(1, dprintf("MDM: DISABLED"));
7596                         }
7597                         cai[0] = 20;
7598
7599                         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7600                             && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7601                         {
7602                                 plci->requested_options |= 1L << PRIVATE_V18;
7603                         }
7604                         if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7605                                 plci->requested_options |= 1L << PRIVATE_VOWN;
7606
7607                         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
7608                             & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7609                         {
7610                                 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwws", mdm_cfg))
7611                                 {
7612                                         i = 27;
7613                                         if (mdm_cfg[6].length >= 4)
7614                                         {
7615                                                 d = GET_DWORD(&mdm_cfg[6].info[1]);
7616                                                 cai[7] |= (byte) d;          /* line taking options */
7617                                                 cai[9] |= (byte)(d >> 8);    /* modulation options */
7618                                                 cai[++i] = (byte)(d >> 16);  /* vown modulation options */
7619                                                 cai[++i] = (byte)(d >> 24);
7620                                                 if (mdm_cfg[6].length >= 8)
7621                                                 {
7622                                                         d = GET_DWORD(&mdm_cfg[6].info[5]);
7623                                                         cai[10] |= (byte) d;        /* disabled modulations mask */
7624                                                         cai[11] |= (byte)(d >> 8);
7625                                                         if (mdm_cfg[6].length >= 12)
7626                                                         {
7627                                                                 d = GET_DWORD(&mdm_cfg[6].info[9]);
7628                                                                 cai[12] = (byte) d;          /* enabled modulations mask */
7629                                                                 cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */
7630                                                                 cai[++i] = (byte)(d >> 16);
7631                                                                 cai[++i] = (byte)(d >> 24);
7632                                                                 cai[++i] = 0;
7633                                                                 if (mdm_cfg[6].length >= 14)
7634                                                                 {
7635                                                                         w = GET_WORD(&mdm_cfg[6].info[13]);
7636                                                                         if (w != 0)
7637                                                                                 PUT_WORD(&cai[13], w);  /* min tx speed */
7638                                                                         if (mdm_cfg[6].length >= 16)
7639                                                                         {
7640                                                                                 w = GET_WORD(&mdm_cfg[6].info[15]);
7641                                                                                 if (w != 0)
7642                                                                                         PUT_WORD(&cai[15], w);  /* max tx speed */
7643                                                                                 if (mdm_cfg[6].length >= 18)
7644                                                                                 {
7645                                                                                         w = GET_WORD(&mdm_cfg[6].info[17]);
7646                                                                                         if (w != 0)
7647                                                                                                 PUT_WORD(&cai[17], w);  /* min rx speed */
7648                                                                                         if (mdm_cfg[6].length >= 20)
7649                                                                                         {
7650                                                                                                 w = GET_WORD(&mdm_cfg[6].info[19]);
7651                                                                                                 if (w != 0)
7652                                                                                                         PUT_WORD(&cai[19], w);  /* max rx speed */
7653                                                                                                 if (mdm_cfg[6].length >= 22)
7654                                                                                                 {
7655                                                                                                         w = GET_WORD(&mdm_cfg[6].info[21]);
7656                                                                                                         cai[23] = (byte)(-((short) w));  /* transmit level */
7657                                                                                                         if (mdm_cfg[6].length >= 24)
7658                                                                                                         {
7659                                                                                                                 w = GET_WORD(&mdm_cfg[6].info[23]);
7660                                                                                                                 cai[22] |= (byte) w;        /* info options mask */
7661                                                                                                                 cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */
7662                                                                                                         }
7663                                                                                                 }
7664                                                                                         }
7665                                                                                 }
7666                                                                         }
7667                                                                 }
7668                                                         }
7669                                                 }
7670                                         }
7671                                         cai[27] = i - 27;
7672                                         i++;
7673                                         if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwwss", mdm_cfg))
7674                                         {
7675                                                 if (!api_parse(&mdm_cfg[7].info[1], (word)mdm_cfg[7].length, "sss", mdm_cfg_v18))
7676                                                 {
7677                                                         for (n = 0; n < 3; n++)
7678                                                         {
7679                                                                 cai[i] = (byte)(mdm_cfg_v18[n].length);
7680                                                                 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7681                                                                         cai[i + j] = mdm_cfg_v18[n].info[j];
7682                                                                 i += cai[i] + 1;
7683                                                         }
7684                                                 }
7685                                         }
7686                                         cai[0] = (byte)(i - 1);
7687                                 }
7688                         }
7689
7690                 }
7691         }
7692         if (GET_WORD(bp_parms[0].info) == 2 ||                         /* V.110 async */
7693             GET_WORD(bp_parms[0].info) == 3)                           /* V.110 sync */
7694         {
7695                 if (bp_parms[3].length) {
7696                         dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms[3].info[1])));
7697                         switch (GET_WORD(&bp_parms[3].info[1])) {                 /* Rate */
7698                         case 0:
7699                         case 56000:
7700                                 if (GET_WORD(bp_parms[0].info) == 3) {                  /* V.110 sync 56k */
7701                                         dbug(1, dprintf("56k sync HSCX"));
7702                                         cai[1] = 8;
7703                                         cai[2] = 0;
7704                                         cai[3] = 0;
7705                                 }
7706                                 else if (GET_WORD(bp_parms[0].info) == 2) {
7707                                         dbug(1, dprintf("56k async DSP"));
7708                                         cai[2] = 9;
7709                                 }
7710                                 break;
7711                         case 50:     cai[2] = 1;  break;
7712                         case 75:     cai[2] = 1;  break;
7713                         case 110:    cai[2] = 1;  break;
7714                         case 150:    cai[2] = 1;  break;
7715                         case 200:    cai[2] = 1;  break;
7716                         case 300:    cai[2] = 1;  break;
7717                         case 600:    cai[2] = 1;  break;
7718                         case 1200:   cai[2] = 2;  break;
7719                         case 2400:   cai[2] = 3;  break;
7720                         case 4800:   cai[2] = 4;  break;
7721                         case 7200:   cai[2] = 10; break;
7722                         case 9600:   cai[2] = 5;  break;
7723                         case 12000:  cai[2] = 13; break;
7724                         case 24000:  cai[2] = 0;  break;
7725                         case 14400:  cai[2] = 11; break;
7726                         case 19200:  cai[2] = 6;  break;
7727                         case 28800:  cai[2] = 12; break;
7728                         case 38400:  cai[2] = 7;  break;
7729                         case 48000:  cai[2] = 8;  break;
7730                         case 76:     cai[2] = 15; break;  /* 75/1200     */
7731                         case 1201:   cai[2] = 14; break;  /* 1200/75     */
7732                         case 56001:  cai[2] = 9;  break;  /* V.110 56000 */
7733
7734                         default:
7735                                 return _B1_PARM_NOT_SUPPORTED;
7736                         }
7737                         cai[3] = 0;
7738                         if (cai[1] == 13)                                        /* v.110 async */
7739                         {
7740                                 if (bp_parms[3].length >= 8)
7741                                 {
7742                                         switch (GET_WORD(&bp_parms[3].info[3]))
7743                                         {       /* char length */
7744                                         case 5:
7745                                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7746                                                 break;
7747                                         case 6:
7748                                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7749                                                 break;
7750                                         case 7:
7751                                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7752                                                 break;
7753                                         }
7754                                         switch (GET_WORD(&bp_parms[3].info[5]))
7755                                         {       /* Parity     */
7756                                         case 1: /* odd parity */
7757                                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7758                                                 break;
7759                                         case 2: /* even parity */
7760                                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7761                                                 break;
7762                                         }
7763                                         switch (GET_WORD(&bp_parms[3].info[7]))
7764                                         {       /* stop bits   */
7765                                         case 1: /* 2 stop bits */
7766                                                 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7767                                                 break;
7768                                         }
7769                                 }
7770                         }
7771                 }
7772                 else if (cai[1] == 8 || GET_WORD(bp_parms[0].info) == 3) {
7773                         dbug(1, dprintf("V.110 default 56k sync"));
7774                         cai[1] = 8;
7775                         cai[2] = 0;
7776                         cai[3] = 0;
7777                 }
7778                 else {
7779                         dbug(1, dprintf("V.110 default 9600 async"));
7780                         cai[2] = 5;
7781                 }
7782         }
7783         PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7784         dbug(1, dprintf("CAI[%d]=%x,%x,%x,%x,%x,%x", cai[0], cai[1], cai[2], cai[3], cai[4], cai[5], cai[6]));
7785 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7786
7787         add_p(plci, CAI, cai);
7788         return 0;
7789 }
7790
7791 /*------------------------------------------------------------------*/
7792 /* put parameter for b2 and B3  protocol in the parameter buffer    */
7793 /*------------------------------------------------------------------*/
7794
7795 static word add_b23(PLCI *plci, API_PARSE *bp)
7796 {
7797         word i, fax_control_bits;
7798         byte pos, len;
7799         byte SAPI = 0x40;  /* default SAPI 16 for x.31 */
7800         API_PARSE bp_parms[8];
7801         API_PARSE *b1_config;
7802         API_PARSE *b2_config;
7803         API_PARSE b2_config_parms[8];
7804         API_PARSE *b3_config;
7805         API_PARSE b3_config_parms[6];
7806         API_PARSE global_config[2];
7807
7808         static byte llc[3] = {2,0,0};
7809         static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7810         static byte nlc[256];
7811         static byte lli[12] = {1,1};
7812
7813         const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7814         const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7815
7816         const byte llc3[] = {4,3,2,2,6,6,0};
7817         const byte header[] = {0,2,3,3,0,0,0};
7818
7819         for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7820         for (i = 0; i < 6; i++) b2_config_parms[i].length = 0;
7821         for (i = 0; i < 5; i++) b3_config_parms[i].length = 0;
7822
7823         lli[0] = 1;
7824         lli[1] = 1;
7825         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7826                 lli[1] |= 2;
7827         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7828                 lli[1] |= 4;
7829
7830         if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7831                 lli[1] |= 0x10;
7832                 if (plci->rx_dma_descriptor <= 0) {
7833                         plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
7834                         if (plci->rx_dma_descriptor >= 0)
7835                                 plci->rx_dma_descriptor++;
7836                 }
7837                 if (plci->rx_dma_descriptor > 0) {
7838                         lli[0] = 6;
7839                         lli[1] |= 0x40;
7840                         lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7841                         lli[3] = (byte)plci->rx_dma_magic;
7842                         lli[4] = (byte)(plci->rx_dma_magic >>  8);
7843                         lli[5] = (byte)(plci->rx_dma_magic >> 16);
7844                         lli[6] = (byte)(plci->rx_dma_magic >> 24);
7845                 }
7846         }
7847
7848         if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7849                 lli[1] |= 0x20;
7850         }
7851
7852         dbug(1, dprintf("add_b23"));
7853         api_save_msg(bp, "s", &plci->B_protocol);
7854
7855         if (!bp->length && plci->tel)
7856         {
7857                 plci->adv_nl = true;
7858                 dbug(1, dprintf("Default adv.Nl"));
7859                 add_p(plci, LLI, lli);
7860                 plci->B2_prot = 1 /*XPARENT*/;
7861                 plci->B3_prot = 0 /*XPARENT*/;
7862                 llc[1] = 2;
7863                 llc[2] = 4;
7864                 add_p(plci, LLC, llc);
7865                 dlc[0] = 2;
7866                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7867                 add_p(plci, DLC, dlc);
7868                 return 0;
7869         }
7870
7871         if (!bp->length) /*default*/
7872         {
7873                 dbug(1, dprintf("ret default"));
7874                 add_p(plci, LLI, lli);
7875                 plci->B2_prot = 0 /*X.75   */;
7876                 plci->B3_prot = 0 /*XPARENT*/;
7877                 llc[1] = 1;
7878                 llc[2] = 4;
7879                 add_p(plci, LLC, llc);
7880                 dlc[0] = 2;
7881                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7882                 add_p(plci, DLC, dlc);
7883                 return 0;
7884         }
7885         dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7886         if ((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT;
7887
7888         if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7889         {
7890                 bp_parms[6].length = 0;
7891                 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7892                 {
7893                         dbug(1, dprintf("b-form.!"));
7894                         return _WRONG_MESSAGE_FORMAT;
7895                 }
7896         }
7897         else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7898         {
7899                 dbug(1, dprintf("b-form.!"));
7900                 return _WRONG_MESSAGE_FORMAT;
7901         }
7902
7903         if (plci->tel == ADV_VOICE) /* transparent B on advanced voice */
7904         {
7905                 if (GET_WORD(bp_parms[1].info) != 1
7906                     || GET_WORD(bp_parms[2].info) != 0) return _B2_NOT_SUPPORTED;
7907                 plci->adv_nl = true;
7908         }
7909         else if (plci->tel) return _B2_NOT_SUPPORTED;
7910
7911
7912         if ((GET_WORD(bp_parms[1].info) == B2_RTP)
7913             && (GET_WORD(bp_parms[2].info) == B3_RTP)
7914             && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7915         {
7916                 add_p(plci, LLI, lli);
7917                 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
7918                 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
7919                 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
7920                 llc[2] = 4;
7921                 add_p(plci, LLC, llc);
7922                 dlc[0] = 2;
7923                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7924                 dlc[3] = 3; /* Addr A */
7925                 dlc[4] = 1; /* Addr B */
7926                 dlc[5] = 7; /* modulo mode */
7927                 dlc[6] = 7; /* window size */
7928                 dlc[7] = 0; /* XID len Lo  */
7929                 dlc[8] = 0; /* XID len Hi  */
7930                 for (i = 0; i < bp_parms[4].length; i++)
7931                         dlc[9 + i] = bp_parms[4].info[1 + i];
7932                 dlc[0] = (byte)(8 + bp_parms[4].length);
7933                 add_p(plci, DLC, dlc);
7934                 for (i = 0; i < bp_parms[5].length; i++)
7935                         nlc[1 + i] = bp_parms[5].info[1 + i];
7936                 nlc[0] = (byte)(bp_parms[5].length);
7937                 add_p(plci, NLC, nlc);
7938                 return 0;
7939         }
7940
7941
7942
7943         if ((GET_WORD(bp_parms[1].info) >= 32)
7944             || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
7945                 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
7946                     || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
7947
7948         {
7949                 return _B2_NOT_SUPPORTED;
7950         }
7951         if ((GET_WORD(bp_parms[2].info) >= 32)
7952             || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
7953         {
7954                 return _B3_NOT_SUPPORTED;
7955         }
7956         if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
7957             && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7958                 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7959                 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
7960         {
7961                 return (add_modem_b23(plci, bp_parms));
7962         }
7963
7964         add_p(plci, LLI, lli);
7965
7966         plci->B2_prot = (byte)GET_WORD(bp_parms[1].info);
7967         plci->B3_prot = (byte)GET_WORD(bp_parms[2].info);
7968         if (plci->B2_prot == 12) SAPI = 0; /* default SAPI D-channel */
7969
7970         if (bp_parms[6].length)
7971         {
7972                 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7973                 {
7974                         return _WRONG_MESSAGE_FORMAT;
7975                 }
7976                 switch (GET_WORD(global_config[0].info))
7977                 {
7978                 case 1:
7979                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7980                         break;
7981                 case 2:
7982                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7983                         break;
7984                 }
7985         }
7986         dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7987
7988
7989         if (plci->B2_prot == B2_PIAFS)
7990                 llc[1] = PIAFS_CRC;
7991         else
7992 /* IMPLEMENT_PIAFS */
7993         {
7994                 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
7995                         llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
7996         }
7997         llc[2] = llc3[GET_WORD(bp_parms[2].info)];
7998
7999         add_p(plci, LLC, llc);
8000
8001         dlc[0] = 2;
8002         PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8003                  header[GET_WORD(bp_parms[2].info)]);
8004
8005         b1_config = &bp_parms[3];
8006         nlc[0] = 0;
8007         if (plci->B3_prot == 4
8008             || plci->B3_prot == 5)
8009         {
8010                 for (i = 0; i < sizeof(T30_INFO); i++) nlc[i] = 0;
8011                 nlc[0] = sizeof(T30_INFO);
8012                 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8013                         ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8014                 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8015                 if (b1_config->length >= 2)
8016                 {
8017                         ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1]) / 2400);
8018                 }
8019         }
8020         b2_config = &bp_parms[4];
8021
8022
8023         if (llc[1] == PIAFS_CRC)
8024         {
8025                 if (plci->B3_prot != B3_TRANSPARENT)
8026                 {
8027                         return _B_STACK_NOT_SUPPORTED;
8028                 }
8029                 if (b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8030                         return _WRONG_MESSAGE_FORMAT;
8031                 }
8032                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8033                 dlc[3] = 0; /* Addr A */
8034                 dlc[4] = 0; /* Addr B */
8035                 dlc[5] = 0; /* modulo mode */
8036                 dlc[6] = 0; /* window size */
8037                 if (b2_config->length >= 7) {
8038                         dlc[7] = 7;
8039                         dlc[8] = 0;
8040                         dlc[9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8041                         dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8042                         dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8043                         dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8044                         dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8045                         dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8046                         dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8047                         dlc[0] = 15;
8048                         if (b2_config->length >= 8) { /* PIAFS control abilities */
8049                                 dlc[7] = 10;
8050                                 dlc[16] = 2; /* Length of PIAFS extension */
8051                                 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8052                                 dlc[18] = b2_config_parms[4].info[0]; /* value */
8053                                 dlc[0] = 18;
8054                         }
8055                 }
8056                 else /* default values, 64K, variable, no compression */
8057                 {
8058                         dlc[7] = 7;
8059                         dlc[8] = 0;
8060                         dlc[9] = 0x03; /* PIAFS protocol Speed configuration */
8061                         dlc[10] = 0x03; /* V.42bis P0 */
8062                         dlc[11] = 0;    /* V.42bis P0 */
8063                         dlc[12] = 0;    /* V.42bis P1 */
8064                         dlc[13] = 0;    /* V.42bis P1 */
8065                         dlc[14] = 0;    /* V.42bis P2 */
8066                         dlc[15] = 0;    /* V.42bis P2 */
8067                         dlc[0] = 15;
8068                 }
8069                 add_p(plci, DLC, dlc);
8070         }
8071         else
8072
8073                 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8074                 {
8075                         if (plci->B3_prot != B3_TRANSPARENT)
8076                                 return _B_STACK_NOT_SUPPORTED;
8077
8078                         dlc[0] = 6;
8079                         PUT_WORD(&dlc[1], GET_WORD(&dlc[1]) + 2);
8080                         dlc[3] = 0x08;
8081                         dlc[4] = 0x01;
8082                         dlc[5] = 127;
8083                         dlc[6] = 7;
8084                         if (b2_config->length != 0)
8085                         {
8086                                 if ((llc[1] == V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8087                                         return _WRONG_MESSAGE_FORMAT;
8088                                 }
8089                                 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8090                                 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8091                                 if (b2_config->info[3] != 128)
8092                                 {
8093                                         dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8094                                         return _B2_PARM_NOT_SUPPORTED;
8095                                 }
8096                                 dlc[5] = (byte)(b2_config->info[3] - 1);
8097                                 dlc[6] = b2_config->info[4];
8098                                 if (llc[1] == V120_V42BIS) {
8099                                         if (b2_config->length >= 10) {
8100                                                 dlc[7] = 6;
8101                                                 dlc[8] = 0;
8102                                                 dlc[9] = b2_config_parms[4].info[0];
8103                                                 dlc[10] = b2_config_parms[4].info[1];
8104                                                 dlc[11] = b2_config_parms[5].info[0];
8105                                                 dlc[12] = b2_config_parms[5].info[1];
8106                                                 dlc[13] = b2_config_parms[6].info[0];
8107                                                 dlc[14] = b2_config_parms[6].info[1];
8108                                                 dlc[0] = 14;
8109                                                 dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8110                                                 dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8111                                                 dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8112                                         }
8113                                         else {
8114                                                 dlc[6] = 14;
8115                                         }
8116                                 }
8117                         }
8118                 }
8119                 else
8120                 {
8121                         if (b2_config->length)
8122                         {
8123                                 dbug(1, dprintf("B2-Config"));
8124                                 if (llc[1] == X75_V42BIS) {
8125                                         if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8126                                         {
8127                                                 return _WRONG_MESSAGE_FORMAT;
8128                                         }
8129                                 }
8130                                 else {
8131                                         if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8132                                         {
8133                                                 return _WRONG_MESSAGE_FORMAT;
8134                                         }
8135                                 }
8136                                 /* if B2 Protocol is LAPD, b2_config structure is different */
8137                                 if (llc[1] == 6)
8138                                 {
8139                                         dlc[0] = 4;
8140                                         if (b2_config->length >= 1) dlc[2] = b2_config->info[1];      /* TEI */
8141                                         else dlc[2] = 0x01;
8142                                         if ((b2_config->length >= 2) && (plci->B2_prot == 12))
8143                                         {
8144                                                 SAPI = b2_config->info[2];    /* SAPI */
8145                                         }
8146                                         dlc[1] = SAPI;
8147                                         if ((b2_config->length >= 3) && (b2_config->info[3] == 128))
8148                                         {
8149                                                 dlc[3] = 127;      /* Mode */
8150                                         }
8151                                         else
8152                                         {
8153                                                 dlc[3] = 7;        /* Mode */
8154                                         }
8155
8156                                         if (b2_config->length >= 4) dlc[4] = b2_config->info[4];      /* Window */
8157                                         else dlc[4] = 1;
8158                                         dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8159                                         if (b2_config->length > 5) return _B2_PARM_NOT_SUPPORTED;
8160                                 }
8161                                 else
8162                                 {
8163                                         dlc[0] = (byte)(b2_config_parms[4].length + 6);
8164                                         dlc[3] = b2_config->info[1];
8165                                         dlc[4] = b2_config->info[2];
8166                                         if (b2_config->info[3] != 8 && b2_config->info[3] != 128) {
8167                                                 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8168                                                 return _B2_PARM_NOT_SUPPORTED;
8169                                         }
8170
8171                                         dlc[5] = (byte)(b2_config->info[3] - 1);
8172                                         dlc[6] = b2_config->info[4];
8173                                         if (dlc[6] > dlc[5]) {
8174                                                 dbug(1, dprintf("2D-dlc= %x %x %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4], dlc[5], dlc[6]));
8175                                                 return _B2_PARM_NOT_SUPPORTED;
8176                                         }
8177
8178                                         if (llc[1] == X75_V42BIS) {
8179                                                 if (b2_config->length >= 10) {
8180                                                         dlc[7] = 6;
8181                                                         dlc[8] = 0;
8182                                                         dlc[9] = b2_config_parms[4].info[0];
8183                                                         dlc[10] = b2_config_parms[4].info[1];
8184                                                         dlc[11] = b2_config_parms[5].info[0];
8185                                                         dlc[12] = b2_config_parms[5].info[1];
8186                                                         dlc[13] = b2_config_parms[6].info[0];
8187                                                         dlc[14] = b2_config_parms[6].info[1];
8188                                                         dlc[0] = 14;
8189                                                         dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8190                                                         dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8191                                                         dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8192                                                 }
8193                                                 else {
8194                                                         dlc[6] = 14;
8195                                                 }
8196
8197                                         }
8198                                         else {
8199                                                 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8200                                                 for (i = 0; i < b2_config_parms[4].length; i++)
8201                                                         dlc[11 + i] = b2_config_parms[4].info[1 + i];
8202                                         }
8203                                 }
8204                         }
8205                 }
8206         add_p(plci, DLC, dlc);
8207
8208         b3_config = &bp_parms[5];
8209         if (b3_config->length)
8210         {
8211                 if (plci->B3_prot == 4
8212                     || plci->B3_prot == 5)
8213                 {
8214                         if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8215                         {
8216                                 return _WRONG_MESSAGE_FORMAT;
8217                         }
8218                         i = GET_WORD((byte *)(b3_config_parms[0].info));
8219                         ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8220                                                                     ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8221                         ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8222                         fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8223                         if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8224                                 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8225                         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8226                         {
8227
8228                                 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8229                                     & (1L << PRIVATE_FAX_PAPER_FORMATS))
8230                                 {
8231                                         ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8232                                                 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8233                                                 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8234                                 }
8235
8236                                 ((T30_INFO *)&nlc[1])->recording_properties =
8237                                         T30_RECORDING_WIDTH_ISO_A3 |
8238                                         (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8239                                         (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8240                         }
8241                         if (plci->B3_prot == 5)
8242                         {
8243                                 if (i & 0x0002) /* Accept incoming fax-polling requests */
8244                                         fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8245                                 if (i & 0x2000) /* Do not use MR compression */
8246                                         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8247                                 if (i & 0x4000) /* Do not use MMR compression */
8248                                         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8249                                 if (i & 0x8000) /* Do not use ECM */
8250                                         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8251                                 if (plci->fax_connect_info_length != 0)
8252                                 {
8253                                         ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8254                                         ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8255                                         ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8256                                         fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8257                                                 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8258                                 }
8259                         }
8260                         /* copy station id to NLC */
8261                         for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
8262                         {
8263                                 if (i < b3_config_parms[2].length)
8264                                 {
8265                                         ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1 + i];
8266                                 }
8267                                 else
8268                                 {
8269                                         ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8270                                 }
8271                         }
8272                         ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8273                         /* copy head line to NLC */
8274                         if (b3_config_parms[3].length)
8275                         {
8276
8277                                 pos = (byte)(fax_head_line_time(&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8278                                 if (pos != 0)
8279                                 {
8280                                         if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8281                                                 pos = 0;
8282                                         else
8283                                         {
8284                                                 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8285                                                 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8286                                                 len = (byte)b3_config_parms[2].length;
8287                                                 if (len > 20)
8288                                                         len = 20;
8289                                                 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8290                                                 {
8291                                                         for (i = 0; i < len; i++)
8292                                                                 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1 + i];
8293                                                         nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8294                                                         nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8295                                                 }
8296                                         }
8297                                 }
8298
8299                                 len = (byte)b3_config_parms[3].length;
8300                                 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8301                                         len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8302                                 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8303                                 nlc[0] += (byte)(pos + len);
8304                                 for (i = 0; i < len; i++)
8305                                         nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] =  ((byte *)b3_config_parms[3].info)[1 + i];
8306                         } else
8307                                 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8308
8309                         plci->nsf_control_bits = 0;
8310                         if (plci->B3_prot == 5)
8311                         {
8312                                 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8313                                     && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8314                                 {
8315                                         plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8316                                 }
8317                                 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8318                                     && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8319                                 {
8320                                         plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8321                                 }
8322                                 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8323                                     & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8324                                 {
8325                                         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8326                                             & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8327                                         {
8328                                                 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8329                                                 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8330                                                         fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8331                                         }
8332                                         len = nlc[0];
8333                                         pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8334                                         if (pos < plci->fax_connect_info_length)
8335                                         {
8336                                                 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8337                                                         nlc[++len] = plci->fax_connect_info_buffer[pos++];
8338                                         }
8339                                         else
8340                                                 nlc[++len] = 0;
8341                                         if (pos < plci->fax_connect_info_length)
8342                                         {
8343                                                 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8344                                                         nlc[++len] = plci->fax_connect_info_buffer[pos++];
8345                                         }
8346                                         else
8347                                                 nlc[++len] = 0;
8348                                         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8349                                             & (1L << PRIVATE_FAX_NONSTANDARD))
8350                                         {
8351                                                 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8352                                                 {
8353                                                         if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos + 1] >= 2))
8354                                                                 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos + 2]);
8355                                                         for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8356                                                                 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8357                                                 }
8358                                                 else
8359                                                 {
8360                                                         if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8361                                                         {
8362                                                                 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8363                                                                 nlc[++len] = 0;
8364                                                         }
8365                                                         else
8366                                                         {
8367                                                                 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8368                                                                         plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8369                                                                 nlc[++len] = (byte)(b3_config_parms[4].length);
8370                                                                 for (i = 0; i < b3_config_parms[4].length; i++)
8371                                                                         nlc[++len] = b3_config_parms[4].info[1 + i];
8372                                                         }
8373                                                 }
8374                                         }
8375                                         nlc[0] = len;
8376                                         if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8377                                             && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8378                                         {
8379                                                 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8380                                         }
8381                                 }
8382                         }
8383
8384                         PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8385                         len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8386                         for (i = 0; i < len; i++)
8387                                 plci->fax_connect_info_buffer[i] = nlc[1 + i];
8388                         ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8389                         i += ((T30_INFO *)&nlc[1])->head_line_len;
8390                         while (i < nlc[0])
8391                                 plci->fax_connect_info_buffer[len++] = nlc[++i];
8392                         plci->fax_connect_info_length = len;
8393                 }
8394                 else
8395                 {
8396                         nlc[0] = 14;
8397                         if (b3_config->length != 16)
8398                                 return _B3_PARM_NOT_SUPPORTED;
8399                         for (i = 0; i < 12; i++) nlc[1 + i] = b3_config->info[1 + i];
8400                         if (GET_WORD(&b3_config->info[13]) != 8 && GET_WORD(&b3_config->info[13]) != 128)
8401                                 return _B3_PARM_NOT_SUPPORTED;
8402                         nlc[13] = b3_config->info[13];
8403                         if (GET_WORD(&b3_config->info[15]) >= nlc[13])
8404                                 return _B3_PARM_NOT_SUPPORTED;
8405                         nlc[14] = b3_config->info[15];
8406                 }
8407         }
8408         else
8409         {
8410                 if (plci->B3_prot == 4
8411                     || plci->B3_prot == 5 /*T.30 - FAX*/) return _B3_PARM_NOT_SUPPORTED;
8412         }
8413         add_p(plci, NLC, nlc);
8414         return 0;
8415 }
8416
8417 /*----------------------------------------------------------------*/
8418 /*      make the same as add_b23, but only for the modem related  */
8419 /*      L2 and L3 B-Chan protocol.                                */
8420 /*                                                                */
8421 /*      Enabled L2 and L3 Configurations:                         */
8422 /*        If L1 == Modem all negotiation                          */
8423 /*          only L2 == Modem with full negotiation is allowed     */
8424 /*        If L1 == Modem async or sync                            */
8425 /*          only L2 == Transparent is allowed                     */
8426 /*        L3 == Modem or L3 == Transparent are allowed            */
8427 /*      B2 Configuration for modem:                               */
8428 /*          word : enable/disable compression, bitoptions         */
8429 /*      B3 Configuration for modem:                               */
8430 /*          empty                                                 */
8431 /*----------------------------------------------------------------*/
8432 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms)
8433 {
8434         static byte lli[12] = {1,1};
8435         static byte llc[3] = {2,0,0};
8436         static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8437         API_PARSE mdm_config[2];
8438         word i;
8439         word b2_config = 0;
8440
8441         for (i = 0; i < 2; i++) mdm_config[i].length = 0;
8442         for (i = 0; i < sizeof(dlc); i++) dlc[i] = 0;
8443
8444         if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8445              && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8446             || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8447                 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8448         {
8449                 return (_B_STACK_NOT_SUPPORTED);
8450         }
8451         if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8452             && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8453         {
8454                 return (_B_STACK_NOT_SUPPORTED);
8455         }
8456
8457         plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8458         plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8459
8460         if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8461         {
8462                 if (api_parse(&bp_parms[4].info[1],
8463                               (word)bp_parms[4].length, "w",
8464                               mdm_config))
8465                 {
8466                         return (_WRONG_MESSAGE_FORMAT);
8467                 }
8468                 b2_config = GET_WORD(mdm_config[0].info);
8469         }
8470
8471         /* OK, L2 is modem */
8472
8473         lli[0] = 1;
8474         lli[1] = 1;
8475         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8476                 lli[1] |= 2;
8477         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8478                 lli[1] |= 4;
8479
8480         if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8481                 lli[1] |= 0x10;
8482                 if (plci->rx_dma_descriptor <= 0) {
8483                         plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
8484                         if (plci->rx_dma_descriptor >= 0)
8485                                 plci->rx_dma_descriptor++;
8486                 }
8487                 if (plci->rx_dma_descriptor > 0) {
8488                         lli[1] |= 0x40;
8489                         lli[0] = 6;
8490                         lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8491                         lli[3] = (byte)plci->rx_dma_magic;
8492                         lli[4] = (byte)(plci->rx_dma_magic >>  8);
8493                         lli[5] = (byte)(plci->rx_dma_magic >> 16);
8494                         lli[6] = (byte)(plci->rx_dma_magic >> 24);
8495                 }
8496         }
8497
8498         if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8499                 lli[1] |= 0x20;
8500         }
8501
8502         llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8503                 /*V42*/ 10 : /*V42_IN*/ 9;
8504         llc[2] = 4;                      /* pass L3 always transparent */
8505         add_p(plci, LLI, lli);
8506         add_p(plci, LLC, llc);
8507         i =  1;
8508         PUT_WORD(&dlc[i], plci->appl->MaxDataLength);
8509         i += 2;
8510         if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8511         {
8512                 if (bp_parms[4].length)
8513                 {
8514                         dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8515                         dlc[i++] = 3; /* Addr A */
8516                         dlc[i++] = 1; /* Addr B */
8517                         dlc[i++] = 7; /* modulo mode */
8518                         dlc[i++] = 7; /* window size */
8519                         dlc[i++] = 0; /* XID len Lo  */
8520                         dlc[i++] = 0; /* XID len Hi  */
8521
8522                         if (b2_config & MDM_B2_DISABLE_V42bis)
8523                         {
8524                                 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8525                         }
8526                         if (b2_config & MDM_B2_DISABLE_MNP)
8527                         {
8528                                 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8529                         }
8530                         if (b2_config & MDM_B2_DISABLE_TRANS)
8531                         {
8532                                 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8533                         }
8534                         if (b2_config & MDM_B2_DISABLE_V42)
8535                         {
8536                                 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8537                         }
8538                         if (b2_config & MDM_B2_DISABLE_COMP)
8539                         {
8540                                 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8541                         }
8542                         i++;
8543                 }
8544         }
8545         else
8546         {
8547                 dlc[i++] = 3; /* Addr A */
8548                 dlc[i++] = 1; /* Addr B */
8549                 dlc[i++] = 7; /* modulo mode */
8550                 dlc[i++] = 7; /* window size */
8551                 dlc[i++] = 0; /* XID len Lo  */
8552                 dlc[i++] = 0; /* XID len Hi  */
8553                 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8554                         DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8555                         DLC_MODEMPROT_DISABLE_V42_DETECT |
8556                         DLC_MODEMPROT_DISABLE_COMPRESSION;
8557         }
8558         dlc[0] = (byte)(i - 1);
8559 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8560         add_p(plci, DLC, dlc);
8561         return (0);
8562 }
8563
8564
8565 /*------------------------------------------------------------------*/
8566 /* send a request for the signaling entity                          */
8567 /*------------------------------------------------------------------*/
8568
8569 static void sig_req(PLCI *plci, byte req, byte Id)
8570 {
8571         if (!plci) return;
8572         if (plci->adapter->adapter_disabled) return;
8573         dbug(1, dprintf("sig_req(%x)", req));
8574         if (req == REMOVE)
8575                 plci->sig_remove_id = plci->Sig.Id;
8576         if (plci->req_in == plci->req_in_start) {
8577                 plci->req_in += 2;
8578                 plci->RBuffer[plci->req_in++] = 0;
8579         }
8580         PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8581         plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
8582         plci->RBuffer[plci->req_in++] = req;  /* request */
8583         plci->RBuffer[plci->req_in++] = 0;    /* channel */
8584         plci->req_in_start = plci->req_in;
8585 }
8586
8587 /*------------------------------------------------------------------*/
8588 /* send a request for the network layer entity                      */
8589 /*------------------------------------------------------------------*/
8590
8591 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8592 {
8593         if (!plci) return;
8594         if (plci->adapter->adapter_disabled) return;
8595         dbug(1, dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8596         if (req == REMOVE)
8597         {
8598                 plci->nl_remove_id = plci->NL.Id;
8599                 ncci_remove(plci, 0, (byte)(ncci != 0));
8600                 ncci = 0;
8601         }
8602         if (plci->req_in == plci->req_in_start) {
8603                 plci->req_in += 2;
8604                 plci->RBuffer[plci->req_in++] = 0;
8605         }
8606         PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8607         plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */
8608         plci->RBuffer[plci->req_in++] = req;  /* request */
8609         plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
8610         plci->req_in_start = plci->req_in;
8611 }
8612
8613 static void send_req(PLCI *plci)
8614 {
8615         ENTITY *e;
8616         word l;
8617 /*  word i; */
8618
8619         if (!plci) return;
8620         if (plci->adapter->adapter_disabled) return;
8621         channel_xmit_xon(plci);
8622
8623         /* if nothing to do, return */
8624         if (plci->req_in == plci->req_out) return;
8625         dbug(1, dprintf("send_req(in=%d,out=%d)", plci->req_in, plci->req_out));
8626
8627         if (plci->nl_req || plci->sig_req) return;
8628
8629         l = GET_WORD(&plci->RBuffer[plci->req_out]);
8630         plci->req_out += 2;
8631         plci->XData[0].P = &plci->RBuffer[plci->req_out];
8632         plci->req_out += l;
8633         if (plci->RBuffer[plci->req_out] == 1)
8634         {
8635                 e = &plci->NL;
8636                 plci->req_out++;
8637                 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8638                 e->ReqCh = plci->RBuffer[plci->req_out++];
8639                 if (!(e->Id & 0x1f))
8640                 {
8641                         e->Id = NL_ID;
8642                         plci->RBuffer[plci->req_out - 4] = CAI;
8643                         plci->RBuffer[plci->req_out - 3] = 1;
8644                         plci->RBuffer[plci->req_out - 2] = (plci->Sig.Id == 0xff) ? 0 : plci->Sig.Id;
8645                         plci->RBuffer[plci->req_out - 1] = 0;
8646                         l += 3;
8647                         plci->nl_global_req = plci->nl_req;
8648                 }
8649                 dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8650         }
8651         else
8652         {
8653                 e = &plci->Sig;
8654                 if (plci->RBuffer[plci->req_out])
8655                         e->Id = plci->RBuffer[plci->req_out];
8656                 plci->req_out++;
8657                 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8658                 e->ReqCh = plci->RBuffer[plci->req_out++];
8659                 if (!(e->Id & 0x1f))
8660                         plci->sig_global_req = plci->sig_req;
8661                 dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8662         }
8663         plci->XData[0].PLength = l;
8664         e->X = plci->XData;
8665         plci->adapter->request(e);
8666         dbug(1, dprintf("send_ok"));
8667 }
8668
8669 static void send_data(PLCI *plci)
8670 {
8671         DIVA_CAPI_ADAPTER *a;
8672         DATA_B3_DESC *data;
8673         NCCI   *ncci_ptr;
8674         word ncci;
8675
8676         if (!plci->nl_req && plci->ncci_ring_list)
8677         {
8678                 a = plci->adapter;
8679                 ncci = plci->ncci_ring_list;
8680                 do
8681                 {
8682                         ncci = a->ncci_next[ncci];
8683                         ncci_ptr = &(a->ncci[ncci]);
8684                         if (!(a->ncci_ch[ncci]
8685                               && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8686                         {
8687                                 if (ncci_ptr->data_pending)
8688                                 {
8689                                         if ((a->ncci_state[ncci] == CONNECTED)
8690                                             || (a->ncci_state[ncci] == INC_ACT_PENDING)
8691                                             || (plci->send_disc == ncci))
8692                                         {
8693                                                 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8694                                                 if ((plci->B2_prot == B2_V120_ASYNC)
8695                                                     || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8696                                                     || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8697                                                 {
8698                                                         plci->NData[1].P = TransmitBufferGet(plci->appl, data->P);
8699                                                         plci->NData[1].PLength = data->Length;
8700                                                         if (data->Flags & 0x10)
8701                                                                 plci->NData[0].P = v120_break_header;
8702                                                         else
8703                                                                 plci->NData[0].P = v120_default_header;
8704                                                         plci->NData[0].PLength = 1;
8705                                                         plci->NL.XNum = 2;
8706                                                         plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8707                                                 }
8708                                                 else
8709                                                 {
8710                                                         plci->NData[0].P = TransmitBufferGet(plci->appl, data->P);
8711                                                         plci->NData[0].PLength = data->Length;
8712                                                         if (data->Flags & 0x10)
8713                                                                 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8714
8715                                                         else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8716                                                                 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8717
8718                                                         else
8719                                                                 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8720                                                 }
8721                                                 plci->NL.X = plci->NData;
8722                                                 plci->NL.ReqCh = a->ncci_ch[ncci];
8723                                                 dbug(1, dprintf("%x:DREQ(%x:%x)", a->Id, plci->NL.Id, plci->NL.Req));
8724                                                 plci->data_sent = true;
8725                                                 plci->data_sent_ptr = data->P;
8726                                                 a->request(&plci->NL);
8727                                         }
8728                                         else {
8729                                                 cleanup_ncci_data(plci, ncci);
8730                                         }
8731                                 }
8732                                 else if (plci->send_disc == ncci)
8733                                 {
8734                                         /* dprintf("N_DISC"); */
8735                                         plci->NData[0].PLength = 0;
8736                                         plci->NL.ReqCh = a->ncci_ch[ncci];
8737                                         plci->NL.Req = plci->nl_req = N_DISC;
8738                                         a->request(&plci->NL);
8739                                         plci->command = _DISCONNECT_B3_R;
8740                                         plci->send_disc = 0;
8741                                 }
8742                         }
8743                 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8744                 plci->ncci_ring_list = ncci;
8745         }
8746 }
8747
8748 static void listen_check(DIVA_CAPI_ADAPTER *a)
8749 {
8750         word i, j;
8751         PLCI *plci;
8752         byte activnotifiedcalls = 0;
8753
8754         dbug(1, dprintf("listen_check(%d,%d)", a->listen_active, a->max_listen));
8755         if (!remove_started && !a->adapter_disabled)
8756         {
8757                 for (i = 0; i < a->max_plci; i++)
8758                 {
8759                         plci = &(a->plci[i]);
8760                         if (plci->notifiedcall) activnotifiedcalls++;
8761                 }
8762                 dbug(1, dprintf("listen_check(%d)", activnotifiedcalls));
8763
8764                 for (i = a->listen_active; i < ((word)(a->max_listen + activnotifiedcalls)); i++) {
8765                         if ((j = get_plci(a))) {
8766                                 a->listen_active++;
8767                                 plci = &a->plci[j - 1];
8768                                 plci->State = LISTENING;
8769
8770                                 add_p(plci, OAD, "\x01\xfd");
8771
8772                                 add_p(plci, KEY, "\x04\x43\x41\x32\x30");
8773
8774                                 add_p(plci, CAI, "\x01\xc0");
8775                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
8776                                 add_p(plci, LLI, "\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */
8777                                 add_p(plci, SHIFT | 6, NULL);
8778                                 add_p(plci, SIN, "\x02\x00\x00");
8779                                 plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
8780                                 sig_req(plci, ASSIGN, DSIG_ID);
8781                                 send_req(plci);
8782                         }
8783                 }
8784         }
8785 }
8786
8787 /*------------------------------------------------------------------*/
8788 /* functions for all parameters sent in INDs                        */
8789 /*------------------------------------------------------------------*/
8790
8791 static void IndParse(PLCI *plci, const word *parms_id, byte **parms, byte multiIEsize)
8792 {
8793         word ploc;            /* points to current location within packet */
8794         byte w;
8795         byte wlen;
8796         byte codeset, lock;
8797         byte *in;
8798         word i;
8799         word code;
8800         word mIEindex = 0;
8801         ploc = 0;
8802         codeset = 0;
8803         lock = 0;
8804
8805         in = plci->Sig.RBuffer->P;
8806         for (i = 0; i < parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
8807         {                            /* element but parms array is larger      */
8808                 parms[i] = (byte *)"";
8809         }
8810         for (i = 0; i < multiIEsize; i++)
8811         {
8812                 parms[i] = (byte *)"";
8813         }
8814
8815         while (ploc < plci->Sig.RBuffer->length - 1) {
8816
8817                 /* read information element id and length                   */
8818                 w = in[ploc];
8819
8820                 if (w & 0x80) {
8821 /*    w &=0xf0; removed, cannot detect congestion levels */
8822 /*    upper 4 bit masked with w==SHIFT now               */
8823                         wlen = 0;
8824                 }
8825                 else {
8826                         wlen = (byte)(in[ploc + 1] + 1);
8827                 }
8828                 /* check if length valid (not exceeding end of packet)      */
8829                 if ((ploc + wlen) > 270) return;
8830                 if (lock & 0x80) lock &= 0x7f;
8831                 else codeset = lock;
8832
8833                 if ((w & 0xf0) == SHIFT) {
8834                         codeset = in[ploc];
8835                         if (!(codeset & 0x08)) lock = (byte)(codeset & 7);
8836                         codeset &= 7;
8837                         lock |= 0x80;
8838                 }
8839                 else {
8840                         if (w == ESC && wlen >= 3) code = in[ploc + 2] | 0x800;
8841                         else code = w;
8842                         code |= (codeset << 8);
8843
8844                         for (i = 1; i < parms_id[0] + 1 && parms_id[i] != code; i++);
8845
8846                         if (i < parms_id[0] + 1) {
8847                                 if (!multiIEsize) { /* with multiIEs use next field index,          */
8848                                         mIEindex = i - 1;    /* with normal IEs use same index like parms_id */
8849                                 }
8850
8851                                 parms[mIEindex] = &in[ploc + 1];
8852                                 dbug(1, dprintf("mIE[%d]=0x%x", *parms[mIEindex], in[ploc]));
8853                                 if (parms_id[i] == OAD
8854                                     || parms_id[i] == CONN_NR
8855                                     || parms_id[i] == CAD) {
8856                                         if (in[ploc + 2] & 0x80) {
8857                                                 in[ploc + 0] = (byte)(in[ploc + 1] + 1);
8858                                                 in[ploc + 1] = (byte)(in[ploc + 2] & 0x7f);
8859                                                 in[ploc + 2] = 0x80;
8860                                                 parms[mIEindex] = &in[ploc];
8861                                         }
8862                                 }
8863                                 mIEindex++;       /* effects multiIEs only */
8864                         }
8865                 }
8866
8867                 ploc += (wlen + 1);
8868         }
8869         return;
8870 }
8871
8872 /*------------------------------------------------------------------*/
8873 /* try to match a cip from received BC and HLC                      */
8874 /*------------------------------------------------------------------*/
8875
8876 static byte ie_compare(byte *ie1, byte *ie2)
8877 {
8878         word i;
8879         if (!ie1 || !ie2) return false;
8880         if (!ie1[0]) return false;
8881         for (i = 0; i < (word)(ie1[0] + 1); i++) if (ie1[i] != ie2[i]) return false;
8882         return true;
8883 }
8884
8885 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
8886 {
8887         word i;
8888         word j;
8889
8890         for (i = 9; i && !ie_compare(bc, cip_bc[i][a->u_law]); i--);
8891
8892         for (j = 16; j < 29 &&
8893                      (!ie_compare(bc, cip_bc[j][a->u_law]) || !ie_compare(hlc, cip_hlc[j])); j++);
8894         if (j == 29) return i;
8895         return j;
8896 }
8897
8898
8899 static byte AddInfo(byte **add_i,
8900                     byte **fty_i,
8901                     byte *esc_chi,
8902                     byte *facility)
8903 {
8904         byte i;
8905         byte j;
8906         byte k;
8907         byte flen;
8908         byte len = 0;
8909         /* facility is a nested structure */
8910         /* FTY can be more than once      */
8911
8912         if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
8913         {
8914                 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
8915         }
8916
8917         else
8918         {
8919                 add_i[0] = (byte *)"";
8920         }
8921         if (!fty_i[0][0])
8922         {
8923                 add_i[3] = (byte *)"";
8924         }
8925         else
8926         {    /* facility array found  */
8927                 for (i = 0, j = 1; i < MAX_MULTI_IE && fty_i[i][0]; i++)
8928                 {
8929                         dbug(1, dprintf("AddIFac[%d]", fty_i[i][0]));
8930                         len += fty_i[i][0];
8931                         len += 2;
8932                         flen = fty_i[i][0];
8933                         facility[j++] = 0x1c; /* copy fac IE */
8934                         for (k = 0; k <= flen; k++, j++)
8935                         {
8936                                 facility[j] = fty_i[i][k];
8937 /*      dbug(1, dprintf("%x ",facility[j])); */
8938                         }
8939                 }
8940                 facility[0] = len;
8941                 add_i[3] = facility;
8942         }
8943 /*  dbug(1, dprintf("FacArrLen=%d ",len)); */
8944         len = add_i[0][0] + add_i[1][0] + add_i[2][0] + add_i[3][0];
8945         len += 4;                          /* calculate length of all */
8946         return (len);
8947 }
8948
8949 /*------------------------------------------------------------------*/
8950 /* voice and codec features                                         */
8951 /*------------------------------------------------------------------*/
8952
8953 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
8954 {
8955         byte voice_chi[] = "\x02\x18\x01";
8956         byte channel;
8957
8958         channel = chi[chi[0]] & 0x3;
8959         dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel));
8960         voice_chi[2] = (channel) ? channel : 1;
8961         add_p(plci, FTY, "\x02\x01\x07");             /* B On, default on 1 */
8962         add_p(plci, ESC, voice_chi);                  /* Channel */
8963         sig_req(plci, TEL_CTRL, 0);
8964         send_req(plci);
8965         if (a->AdvSignalPLCI)
8966         {
8967                 adv_voice_write_coefs(a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
8968         }
8969 }
8970
8971 static void VoiceChannelOff(PLCI *plci)
8972 {
8973         dbug(1, dprintf("ExtDevOFF"));
8974         add_p(plci, FTY, "\x02\x01\x08");             /* B Off */
8975         sig_req(plci, TEL_CTRL, 0);
8976         send_req(plci);
8977         if (plci->adapter->AdvSignalPLCI)
8978         {
8979                 adv_voice_clear_config(plci->adapter->AdvSignalPLCI);
8980         }
8981 }
8982
8983
8984 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
8985                             byte hook_listen)
8986 {
8987         word j;
8988         PLCI *splci;
8989
8990         /* check if hardware supports handset with hook states (adv.codec) */
8991         /* or if just a on board codec is supported                        */
8992         /* the advanced codec plci is just for internal use                */
8993
8994         /* diva Pro with on-board codec:                                   */
8995         if (a->profile.Global_Options & HANDSET)
8996         {
8997                 /* new call, but hook states are already signalled */
8998                 if (a->AdvCodecFLAG)
8999                 {
9000                         if (a->AdvSignalAppl != appl || a->AdvSignalPLCI)
9001                         {
9002                                 dbug(1, dprintf("AdvSigPlci=0x%x", a->AdvSignalPLCI));
9003                                 return 0x2001; /* codec in use by another application */
9004                         }
9005                         if (plci != NULL)
9006                         {
9007                                 a->AdvSignalPLCI = plci;
9008                                 plci->tel = ADV_VOICE;
9009                         }
9010                         return 0;                      /* adv codec still used */
9011                 }
9012                 if ((j = get_plci(a)))
9013                 {
9014                         splci = &a->plci[j - 1];
9015                         splci->tel = CODEC_PERMANENT;
9016                         /* hook_listen indicates if a facility_req with handset/hook support */
9017                         /* was sent. Otherwise if just a call on an external device was made */
9018                         /* the codec will be used but the hook info will be discarded (just  */
9019                         /* the external controller is in use                                 */
9020                         if (hook_listen) splci->State = ADVANCED_VOICE_SIG;
9021                         else
9022                         {
9023                                 splci->State = ADVANCED_VOICE_NOSIG;
9024                                 if (plci)
9025                                 {
9026                                         plci->spoofed_msg = SPOOFING_REQUIRED;
9027                                 }
9028                                 /* indicate D-ch connect if  */
9029                         }                                        /* codec is connected OK     */
9030                         if (plci != NULL)
9031                         {
9032                                 a->AdvSignalPLCI = plci;
9033                                 plci->tel = ADV_VOICE;
9034                         }
9035                         a->AdvSignalAppl = appl;
9036                         a->AdvCodecFLAG = true;
9037                         a->AdvCodecPLCI = splci;
9038                         add_p(splci, CAI, "\x01\x15");
9039                         add_p(splci, LLI, "\x01\x00");
9040                         add_p(splci, ESC, "\x02\x18\x00");
9041                         add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9042                         splci->internal_command = PERM_COD_ASSIGN;
9043                         dbug(1, dprintf("Codec Assign"));
9044                         sig_req(splci, ASSIGN, DSIG_ID);
9045                         send_req(splci);
9046                 }
9047                 else
9048                 {
9049                         return 0x2001; /* wrong state, no more plcis */
9050                 }
9051         }
9052         else if (a->profile.Global_Options & ON_BOARD_CODEC)
9053         {
9054                 if (hook_listen) return 0x300B;               /* Facility not supported */
9055                 /* no hook with SCOM      */
9056                 if (plci != NULL) plci->tel = CODEC;
9057                 dbug(1, dprintf("S/SCOM codec"));
9058                 /* first time we use the scom-s codec we must shut down the internal   */
9059                 /* handset application of the card. This can be done by an assign with */
9060                 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9061                 if (!a->scom_appl_disable) {
9062                         if ((j = get_plci(a))) {
9063                                 splci = &a->plci[j - 1];
9064                                 add_p(splci, CAI, "\x01\x80");
9065                                 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9066                                 sig_req(splci, ASSIGN, 0xC0);  /* 0xc0 is the TEL_ID */
9067                                 send_req(splci);
9068                                 a->scom_appl_disable = true;
9069                         }
9070                         else{
9071                                 return 0x2001; /* wrong state, no more plcis */
9072                         }
9073                 }
9074         }
9075         else return 0x300B;               /* Facility not supported */
9076
9077         return 0;
9078 }
9079
9080
9081 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9082 {
9083
9084         dbug(1, dprintf("CodecIdCheck"));
9085
9086         if (a->AdvSignalPLCI == plci)
9087         {
9088                 dbug(1, dprintf("PLCI owns codec"));
9089                 VoiceChannelOff(a->AdvCodecPLCI);
9090                 if (a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9091                 {
9092                         dbug(1, dprintf("remove temp codec PLCI"));
9093                         plci_remove(a->AdvCodecPLCI);
9094                         a->AdvCodecFLAG  = 0;
9095                         a->AdvCodecPLCI  = NULL;
9096                         a->AdvSignalAppl = NULL;
9097                 }
9098                 a->AdvSignalPLCI = NULL;
9099         }
9100 }
9101
9102 /* -------------------------------------------------------------------
9103    Ask for physical address of card on PCI bus
9104    ------------------------------------------------------------------- */
9105 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *a,
9106                                        IDI_SYNC_REQ *preq) {
9107         a->sdram_bar = 0;
9108         if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9109                 ENTITY *e = (ENTITY *)preq;
9110
9111                 e->user[0] = a->Id - 1;
9112                 preq->xdi_sdram_bar.info.bar    = 0;
9113                 preq->xdi_sdram_bar.Req         = 0;
9114                 preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9115
9116                 (*(a->request))(e);
9117
9118                 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9119                 dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9120         }
9121 }
9122
9123 /* -------------------------------------------------------------------
9124    Ask XDI about extended features
9125    ------------------------------------------------------------------- */
9126 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a) {
9127         IDI_SYNC_REQ *preq;
9128         char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
9129
9130         char features[4];
9131         preq = (IDI_SYNC_REQ *)&buffer[0];
9132
9133         if (!diva_xdi_extended_features) {
9134                 ENTITY *e = (ENTITY *)preq;
9135                 diva_xdi_extended_features |= 0x80000000;
9136
9137                 e->user[0] = a->Id - 1;
9138                 preq->xdi_extended_features.Req = 0;
9139                 preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9140                 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9141                 preq->xdi_extended_features.info.features = &features[0];
9142
9143                 (*(a->request))(e);
9144
9145                 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9146                         /*
9147                           Check features located in the byte '0'
9148                         */
9149                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9150                                 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9151                         }
9152                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9153                                 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9154                                 dbug(1, dprintf("XDI provides RxDMA"));
9155                         }
9156                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9157                                 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9158                         }
9159                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9160                                 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9161                                 dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9162                         }
9163
9164                 }
9165         }
9166
9167         diva_ask_for_xdi_sdram_bar(a, preq);
9168 }
9169
9170 /*------------------------------------------------------------------*/
9171 /* automatic law                                                    */
9172 /*------------------------------------------------------------------*/
9173 /* called from OS specific part after init time to get the Law              */
9174 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9175 void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9176 {
9177         word j;
9178         PLCI *splci;
9179
9180         if (a->automatic_law) {
9181                 return;
9182         }
9183         if ((j = get_plci(a))) {
9184                 diva_get_extended_adapter_features(a);
9185                 splci = &a->plci[j - 1];
9186                 a->automatic_lawPLCI = splci;
9187                 a->automatic_law = 1;
9188                 add_p(splci, CAI, "\x01\x80");
9189                 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9190                 splci->internal_command = USELAW_REQ;
9191                 splci->command = 0;
9192                 splci->number = 0;
9193                 sig_req(splci, ASSIGN, DSIG_ID);
9194                 send_req(splci);
9195         }
9196 }
9197
9198 /* called from OS specific part if an application sends an Capi20Release */
9199 word CapiRelease(word Id)
9200 {
9201         word i, j, appls_found;
9202         PLCI *plci;
9203         APPL   *this;
9204         DIVA_CAPI_ADAPTER *a;
9205
9206         if (!Id)
9207         {
9208                 dbug(0, dprintf("A: CapiRelease(Id==0)"));
9209                 return (_WRONG_APPL_ID);
9210         }
9211
9212         this = &application[Id - 1];               /* get application pointer */
9213
9214         for (i = 0, appls_found = 0; i < max_appl; i++)
9215         {
9216                 if (application[i].Id)       /* an application has been found        */
9217                 {
9218                         appls_found++;
9219                 }
9220         }
9221
9222         for (i = 0; i < max_adapter; i++)             /* scan all adapters...    */
9223         {
9224                 a = &adapter[i];
9225                 if (a->request)
9226                 {
9227                         a->Info_Mask[Id - 1] = 0;
9228                         a->CIP_Mask[Id - 1] = 0;
9229                         a->Notification_Mask[Id - 1] = 0;
9230                         a->codec_listen[Id - 1] = NULL;
9231                         a->requested_options_table[Id - 1] = 0;
9232                         for (j = 0; j < a->max_plci; j++)           /* and all PLCIs connected */
9233                         {                                      /* with this application   */
9234                                 plci = &a->plci[j];
9235                                 if (plci->Id)                         /* if plci owns no application */
9236                                 {                                    /* it may be not jet connected */
9237                                         if (plci->State == INC_CON_PENDING
9238                                             || plci->State == INC_CON_ALERT)
9239                                         {
9240                                                 if (test_bit(Id - 1, plci->c_ind_mask_table))
9241                                                 {
9242                                                         __clear_bit(Id - 1, plci->c_ind_mask_table);
9243                                                         if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9244                                                         {
9245                                                                 sig_req(plci, HANGUP, 0);
9246                                                                 send_req(plci);
9247                                                                 plci->State = OUTG_DIS_PENDING;
9248                                                         }
9249                                                 }
9250                                         }
9251                                         if (test_bit(Id - 1, plci->c_ind_mask_table))
9252                                         {
9253                                                 __clear_bit(Id - 1, plci->c_ind_mask_table);
9254                                                 if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9255                                                 {
9256                                                         if (!plci->appl)
9257                                                         {
9258                                                                 plci_remove(plci);
9259                                                                 plci->State = IDLE;
9260                                                         }
9261                                                 }
9262                                         }
9263                                         if (plci->appl == this)
9264                                         {
9265                                                 plci->appl = NULL;
9266                                                 plci_remove(plci);
9267                                                 plci->State = IDLE;
9268                                         }
9269                                 }
9270                         }
9271                         listen_check(a);
9272
9273                         if (a->flag_dynamic_l1_down)
9274                         {
9275                                 if (appls_found == 1)            /* last application does a capi release */
9276                                 {
9277                                         if ((j = get_plci(a)))
9278                                         {
9279                                                 plci = &a->plci[j - 1];
9280                                                 plci->command = 0;
9281                                                 add_p(plci, OAD, "\x01\xfd");
9282                                                 add_p(plci, CAI, "\x01\x80");
9283                                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9284                                                 add_p(plci, SHIFT | 6, NULL);
9285                                                 add_p(plci, SIN, "\x02\x00\x00");
9286                                                 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9287                                                 sig_req(plci, ASSIGN, DSIG_ID);
9288                                                 add_p(plci, FTY, "\x02\xff\x06"); /* l1 down */
9289                                                 sig_req(plci, SIG_CTRL, 0);
9290                                                 send_req(plci);
9291                                         }
9292                                 }
9293                         }
9294                         if (a->AdvSignalAppl == this)
9295                         {
9296                                 this->NullCREnable = false;
9297                                 if (a->AdvCodecPLCI)
9298                                 {
9299                                         plci_remove(a->AdvCodecPLCI);
9300                                         a->AdvCodecPLCI->tel = 0;
9301                                         a->AdvCodecPLCI->adv_nl = 0;
9302                                 }
9303                                 a->AdvSignalAppl = NULL;
9304                                 a->AdvSignalPLCI = NULL;
9305                                 a->AdvCodecFLAG = 0;
9306                                 a->AdvCodecPLCI = NULL;
9307                         }
9308                 }
9309         }
9310
9311         this->Id = 0;
9312
9313         return GOOD;
9314 }
9315
9316 static word plci_remove_check(PLCI *plci)
9317 {
9318         if (!plci) return true;
9319         if (!plci->NL.Id && bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9320         {
9321                 if (plci->Sig.Id == 0xff)
9322                         plci->Sig.Id = 0;
9323                 if (!plci->Sig.Id)
9324                 {
9325                         dbug(1, dprintf("plci_remove_complete(%x)", plci->Id));
9326                         dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci->tel, plci->Sig.Id));
9327                         if (plci->Id)
9328                         {
9329                                 CodecIdCheck(plci->adapter, plci);
9330                                 clear_b1_config(plci);
9331                                 ncci_remove(plci, 0, false);
9332                                 plci_free_msg_in_queue(plci);
9333                                 channel_flow_control_remove(plci);
9334                                 plci->Id = 0;
9335                                 plci->State = IDLE;
9336                                 plci->channels = 0;
9337                                 plci->appl = NULL;
9338                                 plci->notifiedcall = 0;
9339                         }
9340                         listen_check(plci->adapter);
9341                         return true;
9342                 }
9343         }
9344         return false;
9345 }
9346
9347
9348 /*------------------------------------------------------------------*/
9349
9350 static byte plci_nl_busy(PLCI *plci)
9351 {
9352         /* only applicable for non-multiplexed protocols */
9353         return (plci->nl_req
9354                 || (plci->ncci_ring_list
9355                     && plci->adapter->ncci_ch[plci->ncci_ring_list]
9356                     && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9357 }
9358
9359
9360 /*------------------------------------------------------------------*/
9361 /* DTMF facilities                                                  */
9362 /*------------------------------------------------------------------*/
9363
9364
9365 static struct
9366 {
9367         byte send_mask;
9368         byte listen_mask;
9369         byte character;
9370         byte code;
9371 } dtmf_digit_map[] =
9372 {
9373         { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9374         { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9375         { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9376         { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9377         { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9378         { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9379         { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9380         { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9381         { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9382         { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9383         { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9384         { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9385         { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9386         { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9387         { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9388         { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9389         { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9390         { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9391         { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9392         { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9393
9394         { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9395         { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9396         { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9397         { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9398         { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9399         { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9400         { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9401         { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9402         { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9403         { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9404         { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9405         { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9406         { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9407         { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9408         { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9409         { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9410         { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9411         { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9412         { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9413         { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9414         { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9415         { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9416         { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9417         { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9418         { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9419         { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9420         { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9421         { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9422         { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9423         { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9424         { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9425         { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9426         { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9427         { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9428         { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9429         { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9430         { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9431         { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9432         { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9433         { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9434         { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9435         { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9436         { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9437         { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9438         { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9439         { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9440         { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9441         { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9442         { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9443         { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9444         { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9445         { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9446
9447 };
9448
9449 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9450
9451
9452 static void dtmf_enable_receiver(PLCI *plci, byte enable_mask)
9453 {
9454         word min_digit_duration, min_gap_duration;
9455
9456         dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9457                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9458                         (char *)(FILE_), __LINE__, enable_mask));
9459
9460         if (enable_mask != 0)
9461         {
9462                 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9463                 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9464                 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9465                 PUT_WORD(&plci->internal_req_buffer[1], min_digit_duration);
9466                 PUT_WORD(&plci->internal_req_buffer[3], min_gap_duration);
9467                 plci->NData[0].PLength = 5;
9468
9469                 PUT_WORD(&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9470                 plci->NData[0].PLength += 2;
9471                 capidtmf_recv_enable(&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9472
9473         }
9474         else
9475         {
9476                 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9477                 plci->NData[0].PLength = 1;
9478
9479                 capidtmf_recv_disable(&(plci->capidtmf_state));
9480
9481         }
9482         plci->NData[0].P = plci->internal_req_buffer;
9483         plci->NL.X = plci->NData;
9484         plci->NL.ReqCh = 0;
9485         plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9486         plci->adapter->request(&plci->NL);
9487 }
9488
9489
9490 static void dtmf_send_digits(PLCI *plci, byte *digit_buffer, word digit_count)
9491 {
9492         word w, i;
9493
9494         dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9495                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9496                         (char *)(FILE_), __LINE__, digit_count));
9497
9498         plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9499         w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9500         PUT_WORD(&plci->internal_req_buffer[1], w);
9501         w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9502         PUT_WORD(&plci->internal_req_buffer[3], w);
9503         for (i = 0; i < digit_count; i++)
9504         {
9505                 w = 0;
9506                 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9507                        && (digit_buffer[i] != dtmf_digit_map[w].character))
9508                 {
9509                         w++;
9510                 }
9511                 plci->internal_req_buffer[5 + i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9512                         dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9513         }
9514         plci->NData[0].PLength = 5 + digit_count;
9515         plci->NData[0].P = plci->internal_req_buffer;
9516         plci->NL.X = plci->NData;
9517         plci->NL.ReqCh = 0;
9518         plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9519         plci->adapter->request(&plci->NL);
9520 }
9521
9522
9523 static void dtmf_rec_clear_config(PLCI *plci)
9524 {
9525
9526         dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9527                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9528                         (char *)(FILE_), __LINE__));
9529
9530         plci->dtmf_rec_active = 0;
9531         plci->dtmf_rec_pulse_ms = 0;
9532         plci->dtmf_rec_pause_ms = 0;
9533
9534         capidtmf_init(&(plci->capidtmf_state), plci->adapter->u_law);
9535
9536 }
9537
9538
9539 static void dtmf_send_clear_config(PLCI *plci)
9540 {
9541
9542         dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9543                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9544                         (char *)(FILE_), __LINE__));
9545
9546         plci->dtmf_send_requests = 0;
9547         plci->dtmf_send_pulse_ms = 0;
9548         plci->dtmf_send_pause_ms = 0;
9549 }
9550
9551
9552 static void dtmf_prepare_switch(dword Id, PLCI *plci)
9553 {
9554
9555         dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9556                         UnMapId(Id), (char *)(FILE_), __LINE__));
9557
9558         while (plci->dtmf_send_requests != 0)
9559                 dtmf_confirmation(Id, plci);
9560 }
9561
9562
9563 static word dtmf_save_config(dword Id, PLCI *plci, byte Rc)
9564 {
9565
9566         dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9567                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9568
9569         return (GOOD);
9570 }
9571
9572
9573 static word dtmf_restore_config(dword Id, PLCI *plci, byte Rc)
9574 {
9575         word Info;
9576
9577         dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9578                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9579
9580         Info = GOOD;
9581         if (plci->B1_facilities & B1_FACILITY_DTMFR)
9582         {
9583                 switch (plci->adjust_b_state)
9584                 {
9585                 case ADJUST_B_RESTORE_DTMF_1:
9586                         plci->internal_command = plci->adjust_b_command;
9587                         if (plci_nl_busy(plci))
9588                         {
9589                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9590                                 break;
9591                         }
9592                         dtmf_enable_receiver(plci, plci->dtmf_rec_active);
9593                         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9594                         break;
9595                 case ADJUST_B_RESTORE_DTMF_2:
9596                         if ((Rc != OK) && (Rc != OK_FC))
9597                         {
9598                                 dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9599                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9600                                 Info = _WRONG_STATE;
9601                                 break;
9602                         }
9603                         break;
9604                 }
9605         }
9606         return (Info);
9607 }
9608
9609
9610 static void dtmf_command(dword Id, PLCI *plci, byte Rc)
9611 {
9612         word internal_command, Info;
9613         byte mask;
9614         byte result[4];
9615
9616         dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9617                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9618                         plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9619                         plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9620
9621         Info = GOOD;
9622         result[0] = 2;
9623         PUT_WORD(&result[1], DTMF_SUCCESS);
9624         internal_command = plci->internal_command;
9625         plci->internal_command = 0;
9626         mask = 0x01;
9627         switch (plci->dtmf_cmd)
9628         {
9629
9630         case DTMF_LISTEN_TONE_START:
9631                 mask <<= 1; /* fall through */
9632         case DTMF_LISTEN_MF_START:
9633                 mask <<= 1; /* fall through */
9634
9635         case DTMF_LISTEN_START:
9636                 switch (internal_command)
9637                 {
9638                 default:
9639                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9640                                                                   B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9641                         /* fall through */
9642                 case DTMF_COMMAND_1:
9643                         if (adjust_b_process(Id, plci, Rc) != GOOD)
9644                         {
9645                                 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9646                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9647                                 Info = _FACILITY_NOT_SUPPORTED;
9648                                 break;
9649                         }
9650                         if (plci->internal_command)
9651                                 return;
9652                         /* fall through */
9653                 case DTMF_COMMAND_2:
9654                         if (plci_nl_busy(plci))
9655                         {
9656                                 plci->internal_command = DTMF_COMMAND_2;
9657                                 return;
9658                         }
9659                         plci->internal_command = DTMF_COMMAND_3;
9660                         dtmf_enable_receiver(plci, (byte)(plci->dtmf_rec_active | mask));
9661                         return;
9662                 case DTMF_COMMAND_3:
9663                         if ((Rc != OK) && (Rc != OK_FC))
9664                         {
9665                                 dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9666                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9667                                 Info = _FACILITY_NOT_SUPPORTED;
9668                                 break;
9669                         }
9670
9671                         plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9672
9673                         plci->dtmf_rec_active |= mask;
9674                         break;
9675                 }
9676                 break;
9677
9678
9679         case DTMF_LISTEN_TONE_STOP:
9680                 mask <<= 1; /* fall through */
9681         case DTMF_LISTEN_MF_STOP:
9682                 mask <<= 1; /* fall through */
9683
9684         case DTMF_LISTEN_STOP:
9685                 switch (internal_command)
9686                 {
9687                 default:
9688                         plci->dtmf_rec_active &= ~mask;
9689                         if (plci->dtmf_rec_active)
9690                                 break;
9691 /*
9692   case DTMF_COMMAND_1:
9693   if (plci->dtmf_rec_active)
9694   {
9695   if (plci_nl_busy (plci))
9696   {
9697   plci->internal_command = DTMF_COMMAND_1;
9698   return;
9699   }
9700   plci->dtmf_rec_active &= ~mask;
9701   plci->internal_command = DTMF_COMMAND_2;
9702   dtmf_enable_receiver (plci, false);
9703   return;
9704   }
9705   Rc = OK;
9706   case DTMF_COMMAND_2:
9707   if ((Rc != OK) && (Rc != OK_FC))
9708   {
9709   dbug (1, dprintf("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9710   UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9711   Info = _FACILITY_NOT_SUPPORTED;
9712   break;
9713   }
9714 */
9715                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
9716                                                                   ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9717                         /* fall through */
9718                 case DTMF_COMMAND_3:
9719                         if (adjust_b_process(Id, plci, Rc) != GOOD)
9720                         {
9721                                 dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9722                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9723                                 Info = _FACILITY_NOT_SUPPORTED;
9724                                 break;
9725                         }
9726                         if (plci->internal_command)
9727                                 return;
9728                         break;
9729                 }
9730                 break;
9731
9732
9733         case DTMF_SEND_TONE:
9734                 mask <<= 1; /* fall through */
9735         case DTMF_SEND_MF:
9736                 mask <<= 1; /* fall through */
9737
9738         case DTMF_DIGITS_SEND:
9739                 switch (internal_command)
9740                 {
9741                 default:
9742                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9743                                                                   ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9744                                            DTMF_COMMAND_1);
9745                         /* fall through */
9746                 case DTMF_COMMAND_1:
9747                         if (adjust_b_process(Id, plci, Rc) != GOOD)
9748                         {
9749                                 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9750                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9751                                 Info = _FACILITY_NOT_SUPPORTED;
9752                                 break;
9753                         }
9754                         if (plci->internal_command)
9755                                 return;
9756                         /* fall through */
9757                 case DTMF_COMMAND_2:
9758                         if (plci_nl_busy(plci))
9759                         {
9760                                 plci->internal_command = DTMF_COMMAND_2;
9761                                 return;
9762                         }
9763                         plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9764                         plci->internal_command = DTMF_COMMAND_3;
9765                         dtmf_send_digits(plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9766                         return;
9767                 case DTMF_COMMAND_3:
9768                         if ((Rc != OK) && (Rc != OK_FC))
9769                         {
9770                                 dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9771                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9772                                 if (plci->dtmf_send_requests != 0)
9773                                         (plci->dtmf_send_requests)--;
9774                                 Info = _FACILITY_NOT_SUPPORTED;
9775                                 break;
9776                         }
9777                         return;
9778                 }
9779                 break;
9780         }
9781         sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9782               "wws", Info, SELECTOR_DTMF, result);
9783 }
9784
9785
9786 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
9787 {
9788         word Info;
9789         word i, j;
9790         byte mask;
9791         API_PARSE dtmf_parms[5];
9792         byte result[40];
9793
9794         dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9795                         UnMapId(Id), (char *)(FILE_), __LINE__));
9796
9797         Info = GOOD;
9798         result[0] = 2;
9799         PUT_WORD(&result[1], DTMF_SUCCESS);
9800         if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9801         {
9802                 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9803                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9804                 Info = _FACILITY_NOT_SUPPORTED;
9805         }
9806         else if (api_parse(&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9807         {
9808                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9809                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9810                 Info = _WRONG_MESSAGE_FORMAT;
9811         }
9812
9813         else if ((GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9814                  || (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9815         {
9816                 if (!((a->requested_options_table[appl->Id - 1])
9817                       & (1L << PRIVATE_DTMF_TONE)))
9818                 {
9819                         dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9820                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9821                         PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9822                 }
9823                 else
9824                 {
9825                         for (i = 0; i < 32; i++)
9826                                 result[4 + i] = 0;
9827                         if (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9828                         {
9829                                 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9830                                 {
9831                                         if (dtmf_digit_map[i].listen_mask != 0)
9832                                                 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9833                                 }
9834                         }
9835                         else
9836                         {
9837                                 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9838                                 {
9839                                         if (dtmf_digit_map[i].send_mask != 0)
9840                                                 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9841                                 }
9842                         }
9843                         result[0] = 3 + 32;
9844                         result[3] = 32;
9845                 }
9846         }
9847
9848         else if (plci == NULL)
9849         {
9850                 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9851                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9852                 Info = _WRONG_IDENTIFIER;
9853         }
9854         else
9855         {
9856                 if (!plci->State
9857                     || !plci->NL.Id || plci->nl_remove_id)
9858                 {
9859                         dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9860                                         UnMapId(Id), (char *)(FILE_), __LINE__));
9861                         Info = _WRONG_STATE;
9862                 }
9863                 else
9864                 {
9865                         plci->command = 0;
9866                         plci->dtmf_cmd = GET_WORD(dtmf_parms[0].info);
9867                         mask = 0x01;
9868                         switch (plci->dtmf_cmd)
9869                         {
9870
9871                         case DTMF_LISTEN_TONE_START:
9872                         case DTMF_LISTEN_TONE_STOP:
9873                                 mask <<= 1; /* fall through */
9874                         case DTMF_LISTEN_MF_START:
9875                         case DTMF_LISTEN_MF_STOP:
9876                                 mask <<= 1;
9877                                 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
9878                                       & (1L << PRIVATE_DTMF_TONE)))
9879                                 {
9880                                         dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9881                                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9882                                         PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9883                                         break;
9884                                 }
9885                                 /* fall through */
9886
9887                         case DTMF_LISTEN_START:
9888                         case DTMF_LISTEN_STOP:
9889                                 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
9890                                     && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
9891                                 {
9892                                         dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9893                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
9894                                         Info = _FACILITY_NOT_SUPPORTED;
9895                                         break;
9896                                 }
9897                                 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
9898                                 {
9899                                         if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
9900                                         {
9901                                                 plci->dtmf_rec_pulse_ms = 0;
9902                                                 plci->dtmf_rec_pause_ms = 0;
9903                                         }
9904                                         else
9905                                         {
9906                                                 plci->dtmf_rec_pulse_ms = GET_WORD(dtmf_parms[1].info);
9907                                                 plci->dtmf_rec_pause_ms = GET_WORD(dtmf_parms[2].info);
9908                                         }
9909                                 }
9910                                 start_internal_command(Id, plci, dtmf_command);
9911                                 return (false);
9912
9913
9914                         case DTMF_SEND_TONE:
9915                                 mask <<= 1; /* fall through */
9916                         case DTMF_SEND_MF:
9917                                 mask <<= 1;
9918                                 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
9919                                       & (1L << PRIVATE_DTMF_TONE)))
9920                                 {
9921                                         dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9922                                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9923                                         PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9924                                         break;
9925                                 }
9926                                 /* fall through */
9927
9928                         case DTMF_DIGITS_SEND:
9929                                 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
9930                                 {
9931                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9932                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
9933                                         Info = _WRONG_MESSAGE_FORMAT;
9934                                         break;
9935                                 }
9936                                 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
9937                                 {
9938                                         plci->dtmf_send_pulse_ms = GET_WORD(dtmf_parms[1].info);
9939                                         plci->dtmf_send_pause_ms = GET_WORD(dtmf_parms[2].info);
9940                                 }
9941                                 i = 0;
9942                                 j = 0;
9943                                 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
9944                                 {
9945                                         j = 0;
9946                                         while ((j < DTMF_DIGIT_MAP_ENTRIES)
9947                                                && ((dtmf_parms[3].info[i + 1] != dtmf_digit_map[j].character)
9948                                                    || ((dtmf_digit_map[j].send_mask & mask) == 0)))
9949                                         {
9950                                                 j++;
9951                                         }
9952                                         i++;
9953                                 }
9954                                 if (j == DTMF_DIGIT_MAP_ENTRIES)
9955                                 {
9956                                         dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
9957                                                         UnMapId(Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
9958                                         PUT_WORD(&result[1], DTMF_INCORRECT_DIGIT);
9959                                         break;
9960                                 }
9961                                 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
9962                                 {
9963                                         dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
9964                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
9965                                         Info = _WRONG_STATE;
9966                                         break;
9967                                 }
9968                                 api_save_msg(dtmf_parms, "wwws", &plci->saved_msg);
9969                                 start_internal_command(Id, plci, dtmf_command);
9970                                 return (false);
9971
9972                         default:
9973                                 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9974                                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
9975                                 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9976                         }
9977                 }
9978         }
9979         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
9980               "wws", Info, SELECTOR_DTMF, result);
9981         return (false);
9982 }
9983
9984
9985 static void dtmf_confirmation(dword Id, PLCI *plci)
9986 {
9987         word i;
9988         byte result[4];
9989
9990         dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
9991                         UnMapId(Id), (char *)(FILE_), __LINE__));
9992
9993         result[0] = 2;
9994         PUT_WORD(&result[1], DTMF_SUCCESS);
9995         if (plci->dtmf_send_requests != 0)
9996         {
9997                 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
9998                       "wws", GOOD, SELECTOR_DTMF, result);
9999                 (plci->dtmf_send_requests)--;
10000                 for (i = 0; i < plci->dtmf_send_requests; i++)
10001                         plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i + 1];
10002         }
10003 }
10004
10005
10006 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length)
10007 {
10008         word i, j, n;
10009
10010         dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10011                         UnMapId(Id), (char *)(FILE_), __LINE__));
10012
10013         n = 0;
10014         for (i = 1; i < length; i++)
10015         {
10016                 j = 0;
10017                 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10018                        && ((msg[i] != dtmf_digit_map[j].code)
10019                            || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10020                 {
10021                         j++;
10022                 }
10023                 if (j < DTMF_DIGIT_MAP_ENTRIES)
10024                 {
10025
10026                         if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10027                             && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10028                             && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10029                         {
10030                                 if (n + 1 == i)
10031                                 {
10032                                         for (i = length; i > n + 1; i--)
10033                                                 msg[i] = msg[i - 1];
10034                                         length++;
10035                                         i++;
10036                                 }
10037                                 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10038                         }
10039                         plci->tone_last_indication_code = dtmf_digit_map[j].character;
10040
10041                         msg[++n] = dtmf_digit_map[j].character;
10042                 }
10043         }
10044         if (n != 0)
10045         {
10046                 msg[0] = (byte) n;
10047                 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10048         }
10049 }
10050
10051
10052 /*------------------------------------------------------------------*/
10053 /* DTMF parameters                                                  */
10054 /*------------------------------------------------------------------*/
10055
10056 static void dtmf_parameter_write(PLCI *plci)
10057 {
10058         word i;
10059         byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10060
10061         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10062                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10063                         (char *)(FILE_), __LINE__));
10064
10065         parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10066         parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10067         for (i = 0; i < plci->dtmf_parameter_length; i++)
10068                 parameter_buffer[2 + i] = plci->dtmf_parameter_buffer[i];
10069         add_p(plci, FTY, parameter_buffer);
10070         sig_req(plci, TEL_CTRL, 0);
10071         send_req(plci);
10072 }
10073
10074
10075 static void dtmf_parameter_clear_config(PLCI *plci)
10076 {
10077
10078         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10079                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10080                         (char *)(FILE_), __LINE__));
10081
10082         plci->dtmf_parameter_length = 0;
10083 }
10084
10085
10086 static void dtmf_parameter_prepare_switch(dword Id, PLCI *plci)
10087 {
10088
10089         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10090                         UnMapId(Id), (char *)(FILE_), __LINE__));
10091
10092 }
10093
10094
10095 static word dtmf_parameter_save_config(dword Id, PLCI *plci, byte Rc)
10096 {
10097
10098         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10099                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10100
10101         return (GOOD);
10102 }
10103
10104
10105 static word dtmf_parameter_restore_config(dword Id, PLCI *plci, byte Rc)
10106 {
10107         word Info;
10108
10109         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10110                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10111
10112         Info = GOOD;
10113         if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10114             && (plci->dtmf_parameter_length != 0))
10115         {
10116                 switch (plci->adjust_b_state)
10117                 {
10118                 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10119                         plci->internal_command = plci->adjust_b_command;
10120                         if (plci->sig_req)
10121                         {
10122                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10123                                 break;
10124                         }
10125                         dtmf_parameter_write(plci);
10126                         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10127                         break;
10128                 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10129                         if ((Rc != OK) && (Rc != OK_FC))
10130                         {
10131                                 dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10132                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10133                                 Info = _WRONG_STATE;
10134                                 break;
10135                         }
10136                         break;
10137                 }
10138         }
10139         return (Info);
10140 }
10141
10142
10143 /*------------------------------------------------------------------*/
10144 /* Line interconnect facilities                                     */
10145 /*------------------------------------------------------------------*/
10146
10147
10148 LI_CONFIG   *li_config_table;
10149 word li_total_channels;
10150
10151
10152 /*------------------------------------------------------------------*/
10153 /* translate a CHI information element to a channel number          */
10154 /* returns 0xff - any channel                                       */
10155 /*         0xfe - chi wrong coding                                  */
10156 /*         0xfd - D-channel                                         */
10157 /*         0x00 - no channel                                        */
10158 /*         else channel number / PRI: timeslot                      */
10159 /* if channels is provided we accept more than one channel.         */
10160 /*------------------------------------------------------------------*/
10161
10162 static byte chi_to_channel(byte *chi, dword *pchannelmap)
10163 {
10164         int p;
10165         int i;
10166         dword map;
10167         byte excl;
10168         byte ofs;
10169         byte ch;
10170
10171         if (pchannelmap) *pchannelmap = 0;
10172         if (!chi[0]) return 0xff;
10173         excl = 0;
10174
10175         if (chi[1] & 0x20) {
10176                 if (chi[0] == 1 && chi[1] == 0xac) return 0xfd; /* exclusive d-channel */
10177                 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10178                 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10179                 if ((chi[1] | 0xc8) != 0xe9) return 0xfe;
10180                 if (chi[1] & 0x08) excl = 0x40;
10181
10182                 /* int. id present */
10183                 if (chi[1] & 0x40) {
10184                         p = i + 1;
10185                         for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10186                         if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10187                 }
10188
10189                 /* coding standard, Number/Map, Channel Type */
10190                 p = i + 1;
10191                 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10192                 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10193                 if ((chi[p] | 0xd0) != 0xd3) return 0xfe;
10194
10195                 /* Number/Map */
10196                 if (chi[p] & 0x10) {
10197
10198                         /* map */
10199                         if ((chi[0] - p) == 4) ofs = 0;
10200                         else if ((chi[0] - p) == 3) ofs = 1;
10201                         else return 0xfe;
10202                         ch = 0;
10203                         map = 0;
10204                         for (i = 0; i < 4 && p < chi[0]; i++) {
10205                                 p++;
10206                                 ch += 8;
10207                                 map <<= 8;
10208                                 if (chi[p]) {
10209                                         for (ch = 0; !(chi[p] & (1 << ch)); ch++);
10210                                         map |= chi[p];
10211                                 }
10212                         }
10213                         ch += ofs;
10214                         map <<= ofs;
10215                 }
10216                 else {
10217
10218                         /* number */
10219                         p = i + 1;
10220                         ch = chi[p] & 0x3f;
10221                         if (pchannelmap) {
10222                                 if ((byte)(chi[0] - p) > 30) return 0xfe;
10223                                 map = 0;
10224                                 for (i = p; i <= chi[0]; i++) {
10225                                         if ((chi[i] & 0x7f) > 31) return 0xfe;
10226                                         map |= (1L << (chi[i] & 0x7f));
10227                                 }
10228                         }
10229                         else {
10230                                 if (p != chi[0]) return 0xfe;
10231                                 if (ch > 31) return 0xfe;
10232                                 map = (1L << ch);
10233                         }
10234                         if (chi[p] & 0x40) return 0xfe;
10235                 }
10236                 if (pchannelmap) *pchannelmap = map;
10237                 else if (map != ((dword)(1L << ch))) return 0xfe;
10238                 return (byte)(excl | ch);
10239         }
10240         else {  /* not PRI */
10241                 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10242                 if (i != chi[0] || !(chi[i] & 0x80)) return 0xfe;
10243                 if (chi[1] & 0x08) excl = 0x40;
10244
10245                 switch (chi[1] | 0x98) {
10246                 case 0x98: return 0;
10247                 case 0x99:
10248                         if (pchannelmap) *pchannelmap = 2;
10249                         return excl | 1;
10250                 case 0x9a:
10251                         if (pchannelmap) *pchannelmap = 4;
10252                         return excl | 2;
10253                 case 0x9b: return 0xff;
10254                 case 0x9c: return 0xfd; /* d-ch */
10255                 default: return 0xfe;
10256                 }
10257         }
10258 }
10259
10260
10261 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id)
10262 {
10263         DIVA_CAPI_ADAPTER *a;
10264         PLCI *splci;
10265         byte old_id;
10266
10267         a = plci->adapter;
10268         old_id = plci->li_bchannel_id;
10269         if (a->li_pri)
10270         {
10271                 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10272                         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10273                 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10274                 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10275                         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10276         }
10277         else
10278         {
10279                 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10280                 {
10281                         if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10282                                 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10283                         plci->li_bchannel_id = bchannel_id & 0x03;
10284                         if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10285                         {
10286                                 splci = a->AdvSignalPLCI;
10287                                 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10288                                 {
10289                                         if ((splci->li_bchannel_id != 0)
10290                                             && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10291                                         {
10292                                                 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10293                                         }
10294                                         splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10295                                         li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10296                                         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10297                                                         (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10298                                                         (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10299                                 }
10300                         }
10301                         if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10302                                 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10303                 }
10304         }
10305         if ((old_id == 0) && (plci->li_bchannel_id != 0)
10306             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10307         {
10308                 mixer_clear_config(plci);
10309         }
10310         dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10311                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10312                         (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10313 }
10314
10315
10316 static void mixer_set_bchannel_id(PLCI *plci, byte *chi)
10317 {
10318         DIVA_CAPI_ADAPTER *a;
10319         PLCI *splci;
10320         byte ch, old_id;
10321
10322         a = plci->adapter;
10323         old_id = plci->li_bchannel_id;
10324         ch = chi_to_channel(chi, NULL);
10325         if (!(ch & 0x80))
10326         {
10327                 if (a->li_pri)
10328                 {
10329                         if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10330                                 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10331                         plci->li_bchannel_id = (ch & 0x1f) + 1;
10332                         if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10333                                 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10334                 }
10335                 else
10336                 {
10337                         if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10338                         {
10339                                 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10340                                         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10341                                 plci->li_bchannel_id = ch & 0x1f;
10342                                 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10343                                 {
10344                                         splci = a->AdvSignalPLCI;
10345                                         if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10346                                         {
10347                                                 if ((splci->li_bchannel_id != 0)
10348                                                     && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10349                                                 {
10350                                                         li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10351                                                 }
10352                                                 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10353                                                 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10354                                                 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10355                                                                 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10356                                                                 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10357                                         }
10358                                 }
10359                                 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10360                                         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10361                         }
10362                 }
10363         }
10364         if ((old_id == 0) && (plci->li_bchannel_id != 0)
10365             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10366         {
10367                 mixer_clear_config(plci);
10368         }
10369         dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10370                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10371                         (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10372 }
10373
10374
10375 #define MIXER_MAX_DUMP_CHANNELS 34
10376
10377 static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER *a)
10378 {
10379         word n, i, j;
10380         char *p;
10381         char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10382
10383         dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10384                         (dword)(UnMapController(a->Id)), (char *)(FILE_), __LINE__));
10385
10386         for (i = 0; i < li_total_channels; i++)
10387         {
10388                 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10389                 if (li_config_table[i].chflags != 0)
10390                         li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10391                 else
10392                 {
10393                         for (j = 0; j < li_total_channels; j++)
10394                         {
10395                                 if (((li_config_table[i].flag_table[j]) != 0)
10396                                     || ((li_config_table[j].flag_table[i]) != 0))
10397                                 {
10398                                         li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10399                                 }
10400                                 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10401                                     || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10402                                 {
10403                                         li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10404                                 }
10405                         }
10406                 }
10407         }
10408         for (i = 0; i < li_total_channels; i++)
10409         {
10410                 for (j = 0; j < li_total_channels; j++)
10411                 {
10412                         li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10413                         if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10414                                 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10415                 }
10416         }
10417         for (n = 0; n < li_total_channels; n++)
10418         {
10419                 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10420                 {
10421                         for (i = 0; i < li_total_channels; i++)
10422                         {
10423                                 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10424                                 {
10425                                         for (j = 0; j < li_total_channels; j++)
10426                                         {
10427                                                 li_config_table[i].coef_table[j] |=
10428                                                         li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10429                                         }
10430                                 }
10431                         }
10432                 }
10433         }
10434         for (i = 0; i < li_total_channels; i++)
10435         {
10436                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10437                 {
10438                         li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10439                         for (j = 0; j < li_total_channels; j++)
10440                         {
10441                                 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10442                                         li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10443                         }
10444                         if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10445                                 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10446                 }
10447         }
10448         for (i = 0; i < li_total_channels; i++)
10449         {
10450                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10451                 {
10452                         for (j = 0; j < li_total_channels; j++)
10453                         {
10454                                 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10455                                         li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10456                                 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10457                                         li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10458                                 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10459                                         li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10460                                 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10461                                         li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10462                         }
10463                         if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10464                         {
10465                                 for (j = 0; j < li_total_channels; j++)
10466                                 {
10467                                         if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10468                                         {
10469                                                 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10470                                                 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10471                                                         li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10472                                         }
10473                                 }
10474                         }
10475                         if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10476                         {
10477                                 for (j = 0; j < li_total_channels; j++)
10478                                 {
10479                                         if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10480                                                 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10481                                 }
10482                         }
10483                         if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10484                         {
10485                                 for (j = 0; j < li_total_channels; j++)
10486                                 {
10487                                         if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10488                                         {
10489                                                 for (n = 0; n < li_total_channels; n++)
10490                                                 {
10491                                                         if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10492                                                         {
10493                                                                 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10494                                                                 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10495                                                                 {
10496                                                                         li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10497                                                                         if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10498                                                                                 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10499                                                                 }
10500                                                                 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10501                                                                         li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10502                                                         }
10503                                                 }
10504                                         }
10505                                 }
10506                         }
10507                 }
10508         }
10509         for (i = 0; i < li_total_channels; i++)
10510         {
10511                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10512                 {
10513                         if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10514                                 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10515                         if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10516                                 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10517                         if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10518                                 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10519                         for (j = 0; j < li_total_channels; j++)
10520                         {
10521                                 if ((li_config_table[i].flag_table[j] &
10522                                      (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10523                                     || (li_config_table[j].flag_table[i] &
10524                                         (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10525                                 {
10526                                         li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10527                                 }
10528                                 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10529                                         li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10530                                 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10531                                         li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10532                         }
10533                         if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10534                         {
10535                                 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10536                                 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10537                         }
10538                 }
10539         }
10540         for (i = 0; i < li_total_channels; i++)
10541         {
10542                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10543                 {
10544                         j = 0;
10545                         while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10546                                 j++;
10547                         if (j < li_total_channels)
10548                         {
10549                                 for (j = 0; j < li_total_channels; j++)
10550                                 {
10551                                         li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10552                                         if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10553                                                 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10554                                 }
10555                         }
10556                 }
10557         }
10558         n = li_total_channels;
10559         if (n > MIXER_MAX_DUMP_CHANNELS)
10560                 n = MIXER_MAX_DUMP_CHANNELS;
10561
10562         p = hex_line;
10563         for (j = 0; j < n; j++)
10564         {
10565                 if ((j & 0x7) == 0)
10566                         *(p++) = ' ';
10567                 p = hex_byte_pack(p, li_config_table[j].curchnl);
10568         }
10569         *p = '\0';
10570         dbug(1, dprintf("[%06lx] CURRENT %s",
10571                         (dword)(UnMapController(a->Id)), (char *)hex_line));
10572         p = hex_line;
10573         for (j = 0; j < n; j++)
10574         {
10575                 if ((j & 0x7) == 0)
10576                         *(p++) = ' ';
10577                 p = hex_byte_pack(p, li_config_table[j].channel);
10578         }
10579         *p = '\0';
10580         dbug(1, dprintf("[%06lx] CHANNEL %s",
10581                         (dword)(UnMapController(a->Id)), (char *)hex_line));
10582         p = hex_line;
10583         for (j = 0; j < n; j++)
10584         {
10585                 if ((j & 0x7) == 0)
10586                         *(p++) = ' ';
10587                 p = hex_byte_pack(p, li_config_table[j].chflags);
10588         }
10589         *p = '\0';
10590         dbug(1, dprintf("[%06lx] CHFLAG  %s",
10591                         (dword)(UnMapController(a->Id)), (char *)hex_line));
10592         for (i = 0; i < n; i++)
10593         {
10594                 p = hex_line;
10595                 for (j = 0; j < n; j++)
10596                 {
10597                         if ((j & 0x7) == 0)
10598                                 *(p++) = ' ';
10599                         p = hex_byte_pack(p, li_config_table[i].flag_table[j]);
10600                 }
10601                 *p = '\0';
10602                 dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10603                                 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10604         }
10605         for (i = 0; i < n; i++)
10606         {
10607                 p = hex_line;
10608                 for (j = 0; j < n; j++)
10609                 {
10610                         if ((j & 0x7) == 0)
10611                                 *(p++) = ' ';
10612                         p = hex_byte_pack(p, li_config_table[i].coef_table[j]);
10613                 }
10614                 *p = '\0';
10615                 dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10616                                 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10617         }
10618 }
10619
10620
10621 static struct
10622 {
10623         byte mask;
10624         byte line_flags;
10625 } mixer_write_prog_pri[] =
10626 {
10627         { LI_COEF_CH_CH, 0 },
10628         { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10629         { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10630         { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10631 };
10632
10633 static struct
10634 {
10635         byte from_ch;
10636         byte to_ch;
10637         byte mask;
10638         byte xconnect_override;
10639 } mixer_write_prog_bri[] =
10640 {
10641         { 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10642         { 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10643         { 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10644         { 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10645         { 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10646         { 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10647         { 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10648         { 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10649         { 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10650         { 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10651         { 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10652         { 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10653         { 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10654         { 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10655         { 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10656         { 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10657         { 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10658         { 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10659         { 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10660         { 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10661         { 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10662         { 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10663         { 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10664         { 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10665         { 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10666         { 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10667         { 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10668         { 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10669         { 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10670         { 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10671         { 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10672         { 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10673         { 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10674         { 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10675         { 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10676         { 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10677 };
10678
10679 static byte mixer_swapped_index_bri[] =
10680 {
10681         18,  /* B      to B      */
10682         19,  /* Alt B  to B      */
10683         20,  /* PC     to B      */
10684         21,  /* Alt PC to B      */
10685         22,  /* IC     to B      */
10686         23,  /* Alt IC to B      */
10687         24,  /* B      to PC     */
10688         25,  /* Alt B  to PC     */
10689         26,  /* PC     to PC     */
10690         27,  /* Alt PC to PC     */
10691         28,  /* IC     to PC     */
10692         29,  /* Alt IC to PC     */
10693         30,  /* B      to IC     */
10694         31,  /* Alt B  to IC     */
10695         32,  /* PC     to IC     */
10696         33,  /* Alt PC to IC     */
10697         34,  /* IC     to IC     */
10698         35,  /* Alt IC to IC     */
10699         0,   /* Alt B  to Alt B  */
10700         1,   /* B      to Alt B  */
10701         2,   /* Alt PC to Alt B  */
10702         3,   /* PC     to Alt B  */
10703         4,   /* Alt IC to Alt B  */
10704         5,   /* IC     to Alt B  */
10705         6,   /* Alt B  to Alt PC */
10706         7,   /* B      to Alt PC */
10707         8,   /* Alt PC to Alt PC */
10708         9,   /* PC     to Alt PC */
10709         10,  /* Alt IC to Alt PC */
10710         11,  /* IC     to Alt PC */
10711         12,  /* Alt B  to Alt IC */
10712         13,  /* B      to Alt IC */
10713         14,  /* Alt PC to Alt IC */
10714         15,  /* PC     to Alt IC */
10715         16,  /* Alt IC to Alt IC */
10716         17   /* IC     to Alt IC */
10717 };
10718
10719 static struct
10720 {
10721         byte mask;
10722         byte from_pc;
10723         byte to_pc;
10724 } xconnect_write_prog[] =
10725 {
10726         { LI_COEF_CH_CH, false, false },
10727         { LI_COEF_CH_PC, false, true },
10728         { LI_COEF_PC_CH, true, false },
10729         { LI_COEF_PC_PC, true, true }
10730 };
10731
10732
10733 static void xconnect_query_addresses(PLCI *plci)
10734 {
10735         DIVA_CAPI_ADAPTER *a;
10736         word w, ch;
10737         byte *p;
10738
10739         dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10740                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10741                         (char *)(FILE_), __LINE__));
10742
10743         a = plci->adapter;
10744         if (a->li_pri && ((plci->li_bchannel_id == 0)
10745                           || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10746         {
10747                 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10748                                 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10749                                 (char *)(FILE_), __LINE__));
10750                 return;
10751         }
10752         p = plci->internal_req_buffer;
10753         ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10754         *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10755         w = ch;
10756         *(p++) = (byte) w;
10757         *(p++) = (byte)(w >> 8);
10758         w = ch | XCONNECT_CHANNEL_PORT_PC;
10759         *(p++) = (byte) w;
10760         *(p++) = (byte)(w >> 8);
10761         plci->NData[0].P = plci->internal_req_buffer;
10762         plci->NData[0].PLength = p - plci->internal_req_buffer;
10763         plci->NL.X = plci->NData;
10764         plci->NL.ReqCh = 0;
10765         plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10766         plci->adapter->request(&plci->NL);
10767 }
10768
10769
10770 static void xconnect_write_coefs(PLCI *plci, word internal_command)
10771 {
10772
10773         dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10774                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10775                         (char *)(FILE_), __LINE__, internal_command));
10776
10777         plci->li_write_command = internal_command;
10778         plci->li_write_channel = 0;
10779 }
10780
10781
10782 static byte xconnect_write_coefs_process(dword Id, PLCI *plci, byte Rc)
10783 {
10784         DIVA_CAPI_ADAPTER *a;
10785         word w, n, i, j, r, s, to_ch;
10786         dword d;
10787         byte *p;
10788         struct xconnect_transfer_address_s   *transfer_address;
10789         byte ch_map[MIXER_CHANNELS_BRI];
10790
10791         dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10792                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10793
10794         a = plci->adapter;
10795         if ((plci->li_bchannel_id == 0)
10796             || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10797         {
10798                 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10799                                 UnMapId(Id), (char *)(FILE_), __LINE__));
10800                 return (true);
10801         }
10802         i = a->li_base + (plci->li_bchannel_id - 1);
10803         j = plci->li_write_channel;
10804         p = plci->internal_req_buffer;
10805         if (j != 0)
10806         {
10807                 if ((Rc != OK) && (Rc != OK_FC))
10808                 {
10809                         dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10810                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10811                         return (false);
10812                 }
10813         }
10814         if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10815         {
10816                 r = 0;
10817                 s = 0;
10818                 if (j < li_total_channels)
10819                 {
10820                         if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10821                         {
10822                                 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10823                                      (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10824                                         ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10825                                          (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10826                         }
10827                         r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10828                         while ((j < li_total_channels)
10829                                && ((r == 0)
10830                                    || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10831                                    || (!li_config_table[j].adapter->li_pri
10832                                        && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10833                                    || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10834                                         || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10835                                        && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10836                                            || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10837                                    || ((li_config_table[j].adapter->li_base != a->li_base)
10838                                        && !(r & s &
10839                                             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10840                                              (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10841                                             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10842                                              (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10843                         {
10844                                 j++;
10845                                 if (j < li_total_channels)
10846                                         r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10847                         }
10848                 }
10849                 if (j < li_total_channels)
10850                 {
10851                         plci->internal_command = plci->li_write_command;
10852                         if (plci_nl_busy(plci))
10853                                 return (true);
10854                         to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10855                         *(p++) = UDATA_REQUEST_XCONNECT_TO;
10856                         do
10857                         {
10858                                 if (li_config_table[j].adapter->li_base != a->li_base)
10859                                 {
10860                                         r &= s &
10861                                                 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10862                                                  (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10863                                                 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10864                                                  (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10865                                 }
10866                                 n = 0;
10867                                 do
10868                                 {
10869                                         if (r & xconnect_write_prog[n].mask)
10870                                         {
10871                                                 if (xconnect_write_prog[n].from_pc)
10872                                                         transfer_address = &(li_config_table[j].send_pc);
10873                                                 else
10874                                                         transfer_address = &(li_config_table[j].send_b);
10875                                                 d = transfer_address->card_address.low;
10876                                                 *(p++) = (byte) d;
10877                                                 *(p++) = (byte)(d >> 8);
10878                                                 *(p++) = (byte)(d >> 16);
10879                                                 *(p++) = (byte)(d >> 24);
10880                                                 d = transfer_address->card_address.high;
10881                                                 *(p++) = (byte) d;
10882                                                 *(p++) = (byte)(d >> 8);
10883                                                 *(p++) = (byte)(d >> 16);
10884                                                 *(p++) = (byte)(d >> 24);
10885                                                 d = transfer_address->offset;
10886                                                 *(p++) = (byte) d;
10887                                                 *(p++) = (byte)(d >> 8);
10888                                                 *(p++) = (byte)(d >> 16);
10889                                                 *(p++) = (byte)(d >> 24);
10890                                                 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
10891                                                 *(p++) = (byte) w;
10892                                                 *(p++) = (byte)(w >> 8);
10893                                                 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
10894                                                         (li_config_table[i].adapter->u_law ?
10895                                                          (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
10896                                                          (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
10897                                                 *(p++) = (byte) w;
10898                                                 *(p++) = (byte) 0;
10899                                                 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
10900                                         }
10901                                         n++;
10902                                 } while ((n < ARRAY_SIZE(xconnect_write_prog))
10903                                          && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
10904                                 if (n == ARRAY_SIZE(xconnect_write_prog))
10905                                 {
10906                                         do
10907                                         {
10908                                                 j++;
10909                                                 if (j < li_total_channels)
10910                                                         r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10911                                         } while ((j < li_total_channels)
10912                                                  && ((r == 0)
10913                                                      || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10914                                                      || (!li_config_table[j].adapter->li_pri
10915                                                          && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10916                                                      || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10917                                                           || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10918                                                          && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10919                                                              || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10920                                                      || ((li_config_table[j].adapter->li_base != a->li_base)
10921                                                          && !(r & s &
10922                                                               ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10923                                                                (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10924                                                               ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10925                                                                (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
10926                                 }
10927                         } while ((j < li_total_channels)
10928                                  && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
10929                 }
10930                 else if (j == li_total_channels)
10931                 {
10932                         plci->internal_command = plci->li_write_command;
10933                         if (plci_nl_busy(plci))
10934                                 return (true);
10935                         if (a->li_pri)
10936                         {
10937                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
10938                                 w = 0;
10939                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
10940                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
10941                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
10942                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
10943                                 *(p++) = (byte) w;
10944                                 *(p++) = (byte)(w >> 8);
10945                         }
10946                         else
10947                         {
10948                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
10949                                 w = 0;
10950                                 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
10951                                     && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
10952                                 {
10953                                         w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
10954                                 }
10955                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
10956                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
10957                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
10958                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
10959                                 *(p++) = (byte) w;
10960                                 *(p++) = (byte)(w >> 8);
10961                                 for (j = 0; j < sizeof(ch_map); j += 2)
10962                                 {
10963                                         if (plci->li_bchannel_id == 2)
10964                                         {
10965                                                 ch_map[j] = (byte)(j + 1);
10966                                                 ch_map[j + 1] = (byte) j;
10967                                         }
10968                                         else
10969                                         {
10970                                                 ch_map[j] = (byte) j;
10971                                                 ch_map[j + 1] = (byte)(j + 1);
10972                                         }
10973                                 }
10974                                 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
10975                                 {
10976                                         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
10977                                         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
10978                                         if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
10979                                         {
10980                                                 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
10981                                                         mixer_write_prog_bri[n].xconnect_override :
10982                                                         ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
10983                                                 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
10984                                                 {
10985                                                         w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10986                                                         li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
10987                                                 }
10988                                         }
10989                                         else
10990                                         {
10991                                                 *p = 0x00;
10992                                                 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10993                                                 {
10994                                                         w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
10995                                                         if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
10996                                                                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
10997                                                 }
10998                                         }
10999                                         p++;
11000                                 }
11001                         }
11002                         j = li_total_channels + 1;
11003                 }
11004         }
11005         else
11006         {
11007                 if (j <= li_total_channels)
11008                 {
11009                         plci->internal_command = plci->li_write_command;
11010                         if (plci_nl_busy(plci))
11011                                 return (true);
11012                         if (j < a->li_base)
11013                                 j = a->li_base;
11014                         if (a->li_pri)
11015                         {
11016                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11017                                 w = 0;
11018                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11019                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
11020                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11021                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
11022                                 *(p++) = (byte) w;
11023                                 *(p++) = (byte)(w >> 8);
11024                                 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11025                                 {
11026                                         *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11027                                         for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11028                                         {
11029                                                 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11030                                                 if (w & mixer_write_prog_pri[n].mask)
11031                                                 {
11032                                                         *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11033                                                         li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11034                                                 }
11035                                                 else
11036                                                         *(p++) = 0x00;
11037                                         }
11038                                         *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11039                                         for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11040                                         {
11041                                                 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11042                                                 if (w & mixer_write_prog_pri[n].mask)
11043                                                 {
11044                                                         *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11045                                                         li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11046                                                 }
11047                                                 else
11048                                                         *(p++) = 0x00;
11049                                         }
11050                                 }
11051                         }
11052                         else
11053                         {
11054                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11055                                 w = 0;
11056                                 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11057                                     && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11058                                 {
11059                                         w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11060                                 }
11061                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11062                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
11063                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11064                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
11065                                 *(p++) = (byte) w;
11066                                 *(p++) = (byte)(w >> 8);
11067                                 for (j = 0; j < sizeof(ch_map); j += 2)
11068                                 {
11069                                         if (plci->li_bchannel_id == 2)
11070                                         {
11071                                                 ch_map[j] = (byte)(j + 1);
11072                                                 ch_map[j + 1] = (byte) j;
11073                                         }
11074                                         else
11075                                         {
11076                                                 ch_map[j] = (byte) j;
11077                                                 ch_map[j + 1] = (byte)(j + 1);
11078                                         }
11079                                 }
11080                                 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11081                                 {
11082                                         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11083                                         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11084                                         if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11085                                         {
11086                                                 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11087                                                 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11088                                                 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11089                                         }
11090                                         else
11091                                         {
11092                                                 *p = 0x00;
11093                                                 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11094                                                 {
11095                                                         w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11096                                                         if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11097                                                                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11098                                                 }
11099                                         }
11100                                         p++;
11101                                 }
11102                         }
11103                         j = li_total_channels + 1;
11104                 }
11105         }
11106         plci->li_write_channel = j;
11107         if (p != plci->internal_req_buffer)
11108         {
11109                 plci->NData[0].P = plci->internal_req_buffer;
11110                 plci->NData[0].PLength = p - plci->internal_req_buffer;
11111                 plci->NL.X = plci->NData;
11112                 plci->NL.ReqCh = 0;
11113                 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11114                 plci->adapter->request(&plci->NL);
11115         }
11116         return (true);
11117 }
11118
11119
11120 static void mixer_notify_update(PLCI *plci, byte others)
11121 {
11122         DIVA_CAPI_ADAPTER *a;
11123         word i, w;
11124         PLCI *notify_plci;
11125         byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11126
11127         dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11128                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11129                         (char *)(FILE_), __LINE__, others));
11130
11131         a = plci->adapter;
11132         if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11133         {
11134                 if (others)
11135                         plci->li_notify_update = true;
11136                 i = 0;
11137                 do
11138                 {
11139                         notify_plci = NULL;
11140                         if (others)
11141                         {
11142                                 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11143                                         i++;
11144                                 if (i < li_total_channels)
11145                                         notify_plci = li_config_table[i++].plci;
11146                         }
11147                         else
11148                         {
11149                                 if ((plci->li_bchannel_id != 0)
11150                                     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11151                                 {
11152                                         notify_plci = plci;
11153                                 }
11154                         }
11155                         if ((notify_plci != NULL)
11156                             && !notify_plci->li_notify_update
11157                             && (notify_plci->appl != NULL)
11158                             && (notify_plci->State)
11159                             && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11160                         {
11161                                 notify_plci->li_notify_update = true;
11162                                 ((CAPI_MSG *) msg)->header.length = 18;
11163                                 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11164                                 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11165                                 ((CAPI_MSG *) msg)->header.number = 0;
11166                                 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11167                                 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11168                                 ((CAPI_MSG *) msg)->header.ncci = 0;
11169                                 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11170                                 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11171                                 ((CAPI_MSG *) msg)->info.facility_req.structs[1] = LI_REQ_SILENT_UPDATE & 0xff;
11172                                 ((CAPI_MSG *) msg)->info.facility_req.structs[2] = LI_REQ_SILENT_UPDATE >> 8;
11173                                 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11174                                 w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11175                                 if (w != _QUEUE_FULL)
11176                                 {
11177                                         if (w != 0)
11178                                         {
11179                                                 dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11180                                                                 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11181                                                                 (char *)(FILE_), __LINE__,
11182                                                                 (dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11183                                         }
11184                                         notify_plci->li_notify_update = false;
11185                                 }
11186                         }
11187                 } while (others && (notify_plci != NULL));
11188                 if (others)
11189                         plci->li_notify_update = false;
11190         }
11191 }
11192
11193
11194 static void mixer_clear_config(PLCI *plci)
11195 {
11196         DIVA_CAPI_ADAPTER *a;
11197         word i, j;
11198
11199         dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11200                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11201                         (char *)(FILE_), __LINE__));
11202
11203         plci->li_notify_update = false;
11204         plci->li_plci_b_write_pos = 0;
11205         plci->li_plci_b_read_pos = 0;
11206         plci->li_plci_b_req_pos = 0;
11207         a = plci->adapter;
11208         if ((plci->li_bchannel_id != 0)
11209             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11210         {
11211                 i = a->li_base + (plci->li_bchannel_id - 1);
11212                 li_config_table[i].curchnl = 0;
11213                 li_config_table[i].channel = 0;
11214                 li_config_table[i].chflags = 0;
11215                 for (j = 0; j < li_total_channels; j++)
11216                 {
11217                         li_config_table[j].flag_table[i] = 0;
11218                         li_config_table[i].flag_table[j] = 0;
11219                         li_config_table[i].coef_table[j] = 0;
11220                         li_config_table[j].coef_table[i] = 0;
11221                 }
11222                 if (!a->li_pri)
11223                 {
11224                         li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11225                         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11226                         {
11227                                 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11228                                 li_config_table[i].curchnl = 0;
11229                                 li_config_table[i].channel = 0;
11230                                 li_config_table[i].chflags = 0;
11231                                 for (j = 0; j < li_total_channels; j++)
11232                                 {
11233                                         li_config_table[i].flag_table[j] = 0;
11234                                         li_config_table[j].flag_table[i] = 0;
11235                                         li_config_table[i].coef_table[j] = 0;
11236                                         li_config_table[j].coef_table[i] = 0;
11237                                 }
11238                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11239                                 {
11240                                         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11241                                         li_config_table[i].curchnl = 0;
11242                                         li_config_table[i].channel = 0;
11243                                         li_config_table[i].chflags = 0;
11244                                         for (j = 0; j < li_total_channels; j++)
11245                                         {
11246                                                 li_config_table[i].flag_table[j] = 0;
11247                                                 li_config_table[j].flag_table[i] = 0;
11248                                                 li_config_table[i].coef_table[j] = 0;
11249                                                 li_config_table[j].coef_table[i] = 0;
11250                                         }
11251                                 }
11252                         }
11253                 }
11254         }
11255 }
11256
11257
11258 static void mixer_prepare_switch(dword Id, PLCI *plci)
11259 {
11260
11261         dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11262                         UnMapId(Id), (char *)(FILE_), __LINE__));
11263
11264         do
11265         {
11266                 mixer_indication_coefs_set(Id, plci);
11267         } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11268 }
11269
11270
11271 static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11272 {
11273         DIVA_CAPI_ADAPTER *a;
11274         word i, j;
11275
11276         dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11277                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11278
11279         a = plci->adapter;
11280         if ((plci->li_bchannel_id != 0)
11281             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11282         {
11283                 i = a->li_base + (plci->li_bchannel_id - 1);
11284                 for (j = 0; j < li_total_channels; j++)
11285                 {
11286                         li_config_table[i].coef_table[j] &= 0xf;
11287                         li_config_table[j].coef_table[i] &= 0xf;
11288                 }
11289                 if (!a->li_pri)
11290                         li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11291         }
11292         return (GOOD);
11293 }
11294
11295
11296 static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11297 {
11298         DIVA_CAPI_ADAPTER *a;
11299         word Info;
11300
11301         dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11302                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11303
11304         Info = GOOD;
11305         a = plci->adapter;
11306         if ((plci->B1_facilities & B1_FACILITY_MIXER)
11307             && (plci->li_bchannel_id != 0)
11308             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11309         {
11310                 switch (plci->adjust_b_state)
11311                 {
11312                 case ADJUST_B_RESTORE_MIXER_1:
11313                         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11314                         {
11315                                 plci->internal_command = plci->adjust_b_command;
11316                                 if (plci_nl_busy(plci))
11317                                 {
11318                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11319                                         break;
11320                                 }
11321                                 xconnect_query_addresses(plci);
11322                                 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11323                                 break;
11324                         }
11325                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11326                         Rc = OK;
11327                         /* fall through */
11328                 case ADJUST_B_RESTORE_MIXER_2:
11329                 case ADJUST_B_RESTORE_MIXER_3:
11330                 case ADJUST_B_RESTORE_MIXER_4:
11331                         if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11332                         {
11333                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11334                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11335                                 Info = _WRONG_STATE;
11336                                 break;
11337                         }
11338                         if (Rc == OK)
11339                         {
11340                                 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11341                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11342                                 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11343                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11344                         }
11345                         else if (Rc == 0)
11346                         {
11347                                 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11348                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11349                                 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11350                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11351                         }
11352                         if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11353                         {
11354                                 plci->internal_command = plci->adjust_b_command;
11355                                 break;
11356                         }
11357                         /* fall through */
11358                 case ADJUST_B_RESTORE_MIXER_5:
11359                         xconnect_write_coefs(plci, plci->adjust_b_command);
11360                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11361                         Rc = OK;
11362                         /* fall through */
11363                 case ADJUST_B_RESTORE_MIXER_6:
11364                         if (!xconnect_write_coefs_process(Id, plci, Rc))
11365                         {
11366                                 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11367                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11368                                 Info = _FACILITY_NOT_SUPPORTED;
11369                                 break;
11370                         }
11371                         if (plci->internal_command)
11372                                 break;
11373                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11374                 case ADJUST_B_RESTORE_MIXER_7:
11375                         break;
11376                 }
11377         }
11378         return (Info);
11379 }
11380
11381
11382 static void mixer_command(dword Id, PLCI *plci, byte Rc)
11383 {
11384         DIVA_CAPI_ADAPTER *a;
11385         word i, internal_command;
11386
11387         dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11388                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11389                         plci->li_cmd));
11390
11391         a = plci->adapter;
11392         internal_command = plci->internal_command;
11393         plci->internal_command = 0;
11394         switch (plci->li_cmd)
11395         {
11396         case LI_REQ_CONNECT:
11397         case LI_REQ_DISCONNECT:
11398         case LI_REQ_SILENT_UPDATE:
11399                 switch (internal_command)
11400                 {
11401                 default:
11402                         if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11403                         {
11404                                 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11405                                                                           B1_FACILITY_MIXER), MIXER_COMMAND_1);
11406                         }
11407                         /* fall through */
11408                 case MIXER_COMMAND_1:
11409                         if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11410                         {
11411                                 if (adjust_b_process(Id, plci, Rc) != GOOD)
11412                                 {
11413                                         dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11414                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
11415                                         break;
11416                                 }
11417                                 if (plci->internal_command)
11418                                         return;
11419                         }
11420                         plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11421                         if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11422                             || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11423                                 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11424                                                                                       ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11425                         {
11426                                 xconnect_write_coefs(plci, MIXER_COMMAND_2);
11427                         }
11428                         else
11429                         {
11430                                 do
11431                                 {
11432                                         mixer_indication_coefs_set(Id, plci);
11433                                 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11434                         }
11435                         /* fall through */
11436                 case MIXER_COMMAND_2:
11437                         if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11438                             || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11439                                 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11440                                                                                       ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11441                         {
11442                                 if (!xconnect_write_coefs_process(Id, plci, Rc))
11443                                 {
11444                                         dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11445                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
11446                                         if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11447                                         {
11448                                                 do
11449                                                 {
11450                                                         plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11451                                                                 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11452                                                         i = (plci->li_plci_b_write_pos == 0) ?
11453                                                                 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11454                                                 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11455                                                          && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11456                                         }
11457                                         break;
11458                                 }
11459                                 if (plci->internal_command)
11460                                         return;
11461                         }
11462                         if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11463                         {
11464                                 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11465                                                                           ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11466                         }
11467                         /* fall through */
11468                 case MIXER_COMMAND_3:
11469                         if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11470                         {
11471                                 if (adjust_b_process(Id, plci, Rc) != GOOD)
11472                                 {
11473                                         dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11474                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
11475                                         break;
11476                                 }
11477                                 if (plci->internal_command)
11478                                         return;
11479                         }
11480                         break;
11481                 }
11482                 break;
11483         }
11484         if ((plci->li_bchannel_id == 0)
11485             || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11486         {
11487                 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11488                                 UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11489         }
11490         else
11491         {
11492                 i = a->li_base + (plci->li_bchannel_id - 1);
11493                 li_config_table[i].curchnl = plci->li_channel_bits;
11494                 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11495                 {
11496                         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11497                         li_config_table[i].curchnl = plci->li_channel_bits;
11498                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11499                         {
11500                                 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11501                                 li_config_table[i].curchnl = plci->li_channel_bits;
11502                         }
11503                 }
11504         }
11505 }
11506
11507
11508 static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11509                               dword plci_b_id, byte connect, dword li_flags)
11510 {
11511         word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11512         PLCI *plci_b;
11513         DIVA_CAPI_ADAPTER *a_b;
11514
11515         a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11516         plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11517         ch_a = a->li_base + (plci->li_bchannel_id - 1);
11518         if (!a->li_pri && (plci->tel == ADV_VOICE)
11519             && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11520         {
11521                 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11522                 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11523                         a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11524         }
11525         else
11526         {
11527                 ch_a_v = ch_a;
11528                 ch_a_s = ch_a;
11529         }
11530         ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11531         if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11532             && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11533         {
11534                 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11535                 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11536                         a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11537         }
11538         else
11539         {
11540                 ch_b_v = ch_b;
11541                 ch_b_s = ch_b;
11542         }
11543         if (connect)
11544         {
11545                 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11546                 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11547                 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11548                 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11549         }
11550         li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11551         li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11552         li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11553         li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11554         if (ch_a_v == ch_b_v)
11555         {
11556                 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11557                 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11558         }
11559         else
11560         {
11561                 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11562                 {
11563                         for (i = 0; i < li_total_channels; i++)
11564                         {
11565                                 if (i != ch_a_v)
11566                                         li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11567                         }
11568                 }
11569                 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11570                 {
11571                         for (i = 0; i < li_total_channels; i++)
11572                         {
11573                                 if (i != ch_a_s)
11574                                         li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11575                         }
11576                 }
11577                 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11578                 {
11579                         for (i = 0; i < li_total_channels; i++)
11580                         {
11581                                 if (i != ch_a_v)
11582                                         li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11583                         }
11584                 }
11585                 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11586                 {
11587                         for (i = 0; i < li_total_channels; i++)
11588                         {
11589                                 if (i != ch_a_s)
11590                                         li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11591                         }
11592                 }
11593         }
11594         if (li_flags & LI_FLAG_CONFERENCE_A_B)
11595         {
11596                 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11597                 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11598                 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11599                 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11600         }
11601         if (li_flags & LI_FLAG_CONFERENCE_B_A)
11602         {
11603                 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11604                 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11605                 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11606                 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11607         }
11608         if (li_flags & LI_FLAG_MONITOR_A)
11609         {
11610                 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11611                 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11612         }
11613         if (li_flags & LI_FLAG_MONITOR_B)
11614         {
11615                 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11616                 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11617         }
11618         if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11619         {
11620                 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11621                 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11622         }
11623         if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11624         {
11625                 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11626                 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11627         }
11628         if (li_flags & LI_FLAG_MIX_A)
11629         {
11630                 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11631                 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11632         }
11633         if (li_flags & LI_FLAG_MIX_B)
11634         {
11635                 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11636                 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11637         }
11638         if (ch_a_v != ch_a_s)
11639         {
11640                 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11641                 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11642         }
11643         if (ch_b_v != ch_b_s)
11644         {
11645                 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11646                 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11647         }
11648 }
11649
11650
11651 static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11652                                dword plci_b_id, byte connect, dword li_flags)
11653 {
11654         word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11655         PLCI *plci_b;
11656         DIVA_CAPI_ADAPTER *a_b;
11657
11658         a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11659         plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11660         ch_a = a->li_base + (plci->li_bchannel_id - 1);
11661         if (!a->li_pri && (plci->tel == ADV_VOICE)
11662             && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11663         {
11664                 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11665                 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11666                         a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11667         }
11668         else
11669         {
11670                 ch_a_v = ch_a;
11671                 ch_a_s = ch_a;
11672         }
11673         ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11674         if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11675             && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11676         {
11677                 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11678                 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11679                         a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11680         }
11681         else
11682         {
11683                 ch_b_v = ch_b;
11684                 ch_b_s = ch_b;
11685         }
11686         if (connect)
11687         {
11688                 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11689                 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11690                 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11691                 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11692                 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11693                 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11694         }
11695         li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11696         li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11697         li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11698         li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11699         li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11700         li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11701         li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11702         li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11703         if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11704         {
11705                 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11706                 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11707                 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11708                 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11709         }
11710         if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11711         {
11712                 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11713                 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11714                 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11715                 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11716         }
11717         if (li_flags & LI2_FLAG_MONITOR_B)
11718         {
11719                 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11720                 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11721         }
11722         if (li_flags & LI2_FLAG_MIX_B)
11723         {
11724                 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11725                 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11726         }
11727         if (li_flags & LI2_FLAG_MONITOR_X)
11728                 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11729         if (li_flags & LI2_FLAG_MIX_X)
11730                 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11731         if (li_flags & LI2_FLAG_LOOP_B)
11732         {
11733                 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11734                 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11735                 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11736                 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11737         }
11738         if (li_flags & LI2_FLAG_LOOP_PC)
11739                 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11740         if (li_flags & LI2_FLAG_LOOP_X)
11741                 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11742         if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11743                 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11744         if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11745                 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11746         if (ch_a_v != ch_a_s)
11747         {
11748                 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11749                 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11750         }
11751         if (ch_b_v != ch_b_s)
11752         {
11753                 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11754                 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11755         }
11756 }
11757
11758
11759 static word li_check_main_plci(dword Id, PLCI *plci)
11760 {
11761         if (plci == NULL)
11762         {
11763                 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11764                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11765                 return (_WRONG_IDENTIFIER);
11766         }
11767         if (!plci->State
11768             || !plci->NL.Id || plci->nl_remove_id
11769             || (plci->li_bchannel_id == 0))
11770         {
11771                 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11772                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11773                 return (_WRONG_STATE);
11774         }
11775         li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11776         return (GOOD);
11777 }
11778
11779
11780 static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11781                              dword plci_b_id, word plci_b_write_pos, byte *p_result)
11782 {
11783         byte ctlr_b;
11784         PLCI *plci_b;
11785
11786         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11787              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11788         {
11789                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11790                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11791                 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11792                 return (NULL);
11793         }
11794         ctlr_b = 0;
11795         if ((plci_b_id & 0x7f) != 0)
11796         {
11797                 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11798                 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11799                         ctlr_b = 0;
11800         }
11801         if ((ctlr_b == 0)
11802             || (((plci_b_id >> 8) & 0xff) == 0)
11803             || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11804         {
11805                 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11806                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11807                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11808                 return (NULL);
11809         }
11810         plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11811         if (!plci_b->State
11812             || !plci_b->NL.Id || plci_b->nl_remove_id
11813             || (plci_b->li_bchannel_id == 0))
11814         {
11815                 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11816                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11817                 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11818                 return (NULL);
11819         }
11820         li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11821         if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11822             ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11823             && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11824                 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11825         {
11826                 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11827                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11828                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11829                 return (NULL);
11830         }
11831         if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11832                                                           (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11833         {
11834                 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11835                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11836                 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11837                 return (NULL);
11838         }
11839         return (plci_b);
11840 }
11841
11842
11843 static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11844                               dword plci_b_id, word plci_b_write_pos, byte *p_result)
11845 {
11846         byte ctlr_b;
11847         PLCI *plci_b;
11848
11849         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11850              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11851         {
11852                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11853                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11854                 PUT_WORD(p_result, _WRONG_STATE);
11855                 return (NULL);
11856         }
11857         ctlr_b = 0;
11858         if ((plci_b_id & 0x7f) != 0)
11859         {
11860                 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11861                 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11862                         ctlr_b = 0;
11863         }
11864         if ((ctlr_b == 0)
11865             || (((plci_b_id >> 8) & 0xff) == 0)
11866             || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11867         {
11868                 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11869                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11870                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11871                 return (NULL);
11872         }
11873         plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11874         if (!plci_b->State
11875             || !plci_b->NL.Id || plci_b->nl_remove_id
11876             || (plci_b->li_bchannel_id == 0)
11877             || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11878         {
11879                 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11880                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11881                 PUT_WORD(p_result, _WRONG_STATE);
11882                 return (NULL);
11883         }
11884         if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11885             ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11886             && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11887                 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11888         {
11889                 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11890                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11891                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11892                 return (NULL);
11893         }
11894         if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11895                                                           (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11896         {
11897                 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11898                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11899                 PUT_WORD(p_result, _WRONG_STATE);
11900                 return (NULL);
11901         }
11902         return (plci_b);
11903 }
11904
11905
11906 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
11907 {
11908         word Info;
11909         word i;
11910         dword d, li_flags, plci_b_id;
11911         PLCI *plci_b;
11912         API_PARSE li_parms[3];
11913         API_PARSE li_req_parms[3];
11914         API_PARSE li_participant_struct[2];
11915         API_PARSE li_participant_parms[3];
11916         word participant_parms_pos;
11917         byte result_buffer[32];
11918         byte *result;
11919         word result_pos;
11920         word plci_b_write_pos;
11921
11922         dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
11923                         UnMapId(Id), (char *)(FILE_), __LINE__));
11924
11925         Info = GOOD;
11926         result = result_buffer;
11927         result_buffer[0] = 0;
11928         if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
11929         {
11930                 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
11931                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11932                 Info = _FACILITY_NOT_SUPPORTED;
11933         }
11934         else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
11935         {
11936                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
11937                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11938                 Info = _WRONG_MESSAGE_FORMAT;
11939         }
11940         else
11941         {
11942                 result_buffer[0] = 3;
11943                 PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
11944                 result_buffer[3] = 0;
11945                 switch (GET_WORD(li_parms[0].info))
11946                 {
11947                 case LI_GET_SUPPORTED_SERVICES:
11948                         if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
11949                         {
11950                                 result_buffer[0] = 17;
11951                                 result_buffer[3] = 14;
11952                                 PUT_WORD(&result_buffer[4], GOOD);
11953                                 d = 0;
11954                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
11955                                         d |= LI_CONFERENCING_SUPPORTED;
11956                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
11957                                         d |= LI_MONITORING_SUPPORTED;
11958                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
11959                                         d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
11960                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11961                                         d |= LI_CROSS_CONTROLLER_SUPPORTED;
11962                                 PUT_DWORD(&result_buffer[6], d);
11963                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11964                                 {
11965                                         d = 0;
11966                                         for (i = 0; i < li_total_channels; i++)
11967                                         {
11968                                                 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11969                                                     && (li_config_table[i].adapter->li_pri
11970                                                         || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
11971                                                 {
11972                                                         d++;
11973                                                 }
11974                                         }
11975                                 }
11976                                 else
11977                                 {
11978                                         d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
11979                                 }
11980                                 PUT_DWORD(&result_buffer[10], d / 2);
11981                                 PUT_DWORD(&result_buffer[14], d);
11982                         }
11983                         else
11984                         {
11985                                 result_buffer[0] = 25;
11986                                 result_buffer[3] = 22;
11987                                 PUT_WORD(&result_buffer[4], GOOD);
11988                                 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
11989                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
11990                                         d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
11991                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
11992                                         d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
11993                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
11994                                         d |= LI2_PC_LOOPING_SUPPORTED;
11995                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11996                                         d |= LI2_CROSS_CONTROLLER_SUPPORTED;
11997                                 PUT_DWORD(&result_buffer[6], d);
11998                                 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
11999                                 PUT_DWORD(&result_buffer[10], d / 2);
12000                                 PUT_DWORD(&result_buffer[14], d - 1);
12001                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12002                                 {
12003                                         d = 0;
12004                                         for (i = 0; i < li_total_channels; i++)
12005                                         {
12006                                                 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12007                                                     && (li_config_table[i].adapter->li_pri
12008                                                         || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12009                                                 {
12010                                                         d++;
12011                                                 }
12012                                         }
12013                                 }
12014                                 PUT_DWORD(&result_buffer[18], d / 2);
12015                                 PUT_DWORD(&result_buffer[22], d - 1);
12016                         }
12017                         break;
12018
12019                 case LI_REQ_CONNECT:
12020                         if (li_parms[1].length == 8)
12021                         {
12022                                 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12023                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12024                                 {
12025                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12026                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12027                                         Info = _WRONG_MESSAGE_FORMAT;
12028                                         break;
12029                                 }
12030                                 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12031                                 li_flags = GET_DWORD(li_req_parms[1].info);
12032                                 Info = li_check_main_plci(Id, plci);
12033                                 result_buffer[0] = 9;
12034                                 result_buffer[3] = 6;
12035                                 PUT_DWORD(&result_buffer[4], plci_b_id);
12036                                 PUT_WORD(&result_buffer[8], GOOD);
12037                                 if (Info != GOOD)
12038                                         break;
12039                                 result = plci->saved_msg.info;
12040                                 for (i = 0; i <= result_buffer[0]; i++)
12041                                         result[i] = result_buffer[i];
12042                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12043                                 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12044                                 if (plci_b == NULL)
12045                                         break;
12046                                 li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12047                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12048                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12049                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12050                         }
12051                         else
12052                         {
12053                                 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12054                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12055                                 {
12056                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12057                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12058                                         Info = _WRONG_MESSAGE_FORMAT;
12059                                         break;
12060                                 }
12061                                 li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12062                                 Info = li_check_main_plci(Id, plci);
12063                                 result_buffer[0] = 7;
12064                                 result_buffer[3] = 4;
12065                                 PUT_WORD(&result_buffer[4], Info);
12066                                 result_buffer[6] = 0;
12067                                 if (Info != GOOD)
12068                                         break;
12069                                 result = plci->saved_msg.info;
12070                                 for (i = 0; i <= result_buffer[0]; i++)
12071                                         result[i] = result_buffer[i];
12072                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12073                                 participant_parms_pos = 0;
12074                                 result_pos = 7;
12075                                 li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12076                                 while (participant_parms_pos < li_req_parms[1].length)
12077                                 {
12078                                         result[result_pos] = 6;
12079                                         result_pos += 7;
12080                                         PUT_DWORD(&result[result_pos - 6], 0);
12081                                         PUT_WORD(&result[result_pos - 2], GOOD);
12082                                         if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12083                                                       (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12084                                         {
12085                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12086                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12087                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12088                                                 break;
12089                                         }
12090                                         if (api_parse(&li_participant_struct[0].info[1],
12091                                                       li_participant_struct[0].length, "dd", li_participant_parms))
12092                                         {
12093                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12094                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12095                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12096                                                 break;
12097                                         }
12098                                         plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12099                                         li_flags = GET_DWORD(li_participant_parms[1].info);
12100                                         PUT_DWORD(&result[result_pos - 6], plci_b_id);
12101                                         if (sizeof(result) - result_pos < 7)
12102                                         {
12103                                                 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12104                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12105                                                 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12106                                                 break;
12107                                         }
12108                                         plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12109                                         if (plci_b != NULL)
12110                                         {
12111                                                 li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12112                                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12113                                                         ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12114                                                                       LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12115                                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12116                                         }
12117                                         participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12118                                                                        (&li_req_parms[1].info[1]));
12119                                 }
12120                                 result[0] = (byte)(result_pos - 1);
12121                                 result[3] = (byte)(result_pos - 4);
12122                                 result[6] = (byte)(result_pos - 7);
12123                                 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12124                                 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12125                                     || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12126                                 {
12127                                         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12128                                         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12129                                 }
12130                                 else
12131                                         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12132                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12133                         }
12134                         mixer_calculate_coefs(a);
12135                         plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12136                         mixer_notify_update(plci, true);
12137                         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12138                               "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12139                         plci->command = 0;
12140                         plci->li_cmd = GET_WORD(li_parms[0].info);
12141                         start_internal_command(Id, plci, mixer_command);
12142                         return (false);
12143
12144                 case LI_REQ_DISCONNECT:
12145                         if (li_parms[1].length == 4)
12146                         {
12147                                 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12148                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12149                                 {
12150                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12151                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12152                                         Info = _WRONG_MESSAGE_FORMAT;
12153                                         break;
12154                                 }
12155                                 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12156                                 Info = li_check_main_plci(Id, plci);
12157                                 result_buffer[0] = 9;
12158                                 result_buffer[3] = 6;
12159                                 PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12160                                 PUT_WORD(&result_buffer[8], GOOD);
12161                                 if (Info != GOOD)
12162                                         break;
12163                                 result = plci->saved_msg.info;
12164                                 for (i = 0; i <= result_buffer[0]; i++)
12165                                         result[i] = result_buffer[i];
12166                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12167                                 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12168                                 if (plci_b == NULL)
12169                                         break;
12170                                 li_update_connect(Id, a, plci, plci_b_id, false, 0);
12171                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12172                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12173                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12174                         }
12175                         else
12176                         {
12177                                 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12178                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12179                                 {
12180                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12181                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12182                                         Info = _WRONG_MESSAGE_FORMAT;
12183                                         break;
12184                                 }
12185                                 Info = li_check_main_plci(Id, plci);
12186                                 result_buffer[0] = 7;
12187                                 result_buffer[3] = 4;
12188                                 PUT_WORD(&result_buffer[4], Info);
12189                                 result_buffer[6] = 0;
12190                                 if (Info != GOOD)
12191                                         break;
12192                                 result = plci->saved_msg.info;
12193                                 for (i = 0; i <= result_buffer[0]; i++)
12194                                         result[i] = result_buffer[i];
12195                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12196                                 participant_parms_pos = 0;
12197                                 result_pos = 7;
12198                                 while (participant_parms_pos < li_req_parms[0].length)
12199                                 {
12200                                         result[result_pos] = 6;
12201                                         result_pos += 7;
12202                                         PUT_DWORD(&result[result_pos - 6], 0);
12203                                         PUT_WORD(&result[result_pos - 2], GOOD);
12204                                         if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12205                                                       (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12206                                         {
12207                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12208                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12209                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12210                                                 break;
12211                                         }
12212                                         if (api_parse(&li_participant_struct[0].info[1],
12213                                                       li_participant_struct[0].length, "d", li_participant_parms))
12214                                         {
12215                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12216                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12217                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12218                                                 break;
12219                                         }
12220                                         plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12221                                         PUT_DWORD(&result[result_pos - 6], plci_b_id);
12222                                         if (sizeof(result) - result_pos < 7)
12223                                         {
12224                                                 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12225                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12226                                                 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12227                                                 break;
12228                                         }
12229                                         plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12230                                         if (plci_b != NULL)
12231                                         {
12232                                                 li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12233                                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12234                                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12235                                         }
12236                                         participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12237                                                                        (&li_req_parms[0].info[1]));
12238                                 }
12239                                 result[0] = (byte)(result_pos - 1);
12240                                 result[3] = (byte)(result_pos - 4);
12241                                 result[6] = (byte)(result_pos - 7);
12242                                 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12243                                 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12244                                     || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12245                                 {
12246                                         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12247                                         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12248                                 }
12249                                 else
12250                                         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12251                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12252                         }
12253                         mixer_calculate_coefs(a);
12254                         plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12255                         mixer_notify_update(plci, true);
12256                         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12257                               "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12258                         plci->command = 0;
12259                         plci->li_cmd = GET_WORD(li_parms[0].info);
12260                         start_internal_command(Id, plci, mixer_command);
12261                         return (false);
12262
12263                 case LI_REQ_SILENT_UPDATE:
12264                         if (!plci || !plci->State
12265                             || !plci->NL.Id || plci->nl_remove_id
12266                             || (plci->li_bchannel_id == 0)
12267                             || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12268                         {
12269                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12270                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12271                                 return (false);
12272                         }
12273                         plci_b_write_pos = plci->li_plci_b_write_pos;
12274                         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12275                              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12276                         {
12277                                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12278                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12279                                 return (false);
12280                         }
12281                         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12282                         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12283                             || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12284                         {
12285                                 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12286                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12287                         }
12288                         else
12289                                 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12290                         plci->li_plci_b_write_pos = plci_b_write_pos;
12291                         plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12292                         plci->command = 0;
12293                         plci->li_cmd = GET_WORD(li_parms[0].info);
12294                         start_internal_command(Id, plci, mixer_command);
12295                         return (false);
12296
12297                 default:
12298                         dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12299                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12300                         Info = _FACILITY_NOT_SUPPORTED;
12301                 }
12302         }
12303         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12304               "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12305         return (false);
12306 }
12307
12308
12309 static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12310 {
12311         dword d;
12312         byte result[12];
12313
12314         dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12315                         UnMapId(Id), (char *)(FILE_), __LINE__));
12316
12317         if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12318         {
12319                 do
12320                 {
12321                         d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12322                         if (!(d & LI_PLCI_B_SKIP_FLAG))
12323                         {
12324                                 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12325                                 {
12326                                         if (d & LI_PLCI_B_DISC_FLAG)
12327                                         {
12328                                                 result[0] = 5;
12329                                                 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12330                                                 result[3] = 2;
12331                                                 PUT_WORD(&result[4], _LI_USER_INITIATED);
12332                                         }
12333                                         else
12334                                         {
12335                                                 result[0] = 7;
12336                                                 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12337                                                 result[3] = 4;
12338                                                 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12339                                         }
12340                                 }
12341                                 else
12342                                 {
12343                                         if (d & LI_PLCI_B_DISC_FLAG)
12344                                         {
12345                                                 result[0] = 9;
12346                                                 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12347                                                 result[3] = 6;
12348                                                 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12349                                                 PUT_WORD(&result[8], _LI_USER_INITIATED);
12350                                         }
12351                                         else
12352                                         {
12353                                                 result[0] = 7;
12354                                                 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12355                                                 result[3] = 4;
12356                                                 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12357                                         }
12358                                 }
12359                                 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12360                                       "ws", SELECTOR_LINE_INTERCONNECT, result);
12361                         }
12362                         plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12363                                 0 : plci->li_plci_b_read_pos + 1;
12364                 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12365         }
12366 }
12367
12368
12369 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12370 {
12371         word i, j, ch;
12372         struct xconnect_transfer_address_s s,   *p;
12373         DIVA_CAPI_ADAPTER *a;
12374
12375         dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12376                         UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12377
12378         a = plci->adapter;
12379         i = 1;
12380         for (i = 1; i < length; i += 16)
12381         {
12382                 s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12383                 s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12384                 s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12385                 ch = msg[i + 12] | (msg[i + 13] << 8);
12386                 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12387                 if (!a->li_pri && (plci->li_bchannel_id == 2))
12388                         j = 1 - j;
12389                 j += a->li_base;
12390                 if (ch & XCONNECT_CHANNEL_PORT_PC)
12391                         p = &(li_config_table[j].send_pc);
12392                 else
12393                         p = &(li_config_table[j].send_b);
12394                 p->card_address.low = s.card_address.low;
12395                 p->card_address.high = s.card_address.high;
12396                 p->offset = s.offset;
12397                 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12398         }
12399         if (plci->internal_command_queue[0]
12400             && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12401                 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12402                 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12403         {
12404                 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12405                 if (!plci->internal_command)
12406                         next_internal_command(Id, plci);
12407         }
12408         mixer_notify_update(plci, true);
12409 }
12410
12411
12412 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12413 {
12414
12415         dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12416                         UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12417
12418 }
12419
12420
12421 static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12422 {
12423         word plci_b_write_pos;
12424
12425         plci_b_write_pos = plci->li_plci_b_write_pos;
12426         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12427              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12428         {
12429                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12430                                 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12431                                 (char *)(FILE_), __LINE__));
12432                 return (false);
12433         }
12434         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12435         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12436         plci->li_plci_b_write_pos = plci_b_write_pos;
12437         return (true);
12438 }
12439
12440
12441 static void mixer_remove(PLCI *plci)
12442 {
12443         DIVA_CAPI_ADAPTER *a;
12444         PLCI *notify_plci;
12445         dword plci_b_id;
12446         word i, j;
12447
12448         dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12449                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12450                         (char *)(FILE_), __LINE__));
12451
12452         a = plci->adapter;
12453         plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12454         if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12455         {
12456                 if ((plci->li_bchannel_id != 0)
12457                     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12458                 {
12459                         i = a->li_base + (plci->li_bchannel_id - 1);
12460                         if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12461                         {
12462                                 for (j = 0; j < li_total_channels; j++)
12463                                 {
12464                                         if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12465                                             || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12466                                         {
12467                                                 notify_plci = li_config_table[j].plci;
12468                                                 if ((notify_plci != NULL)
12469                                                     && (notify_plci != plci)
12470                                                     && (notify_plci->appl != NULL)
12471                                                     && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12472                                                     && (notify_plci->State)
12473                                                     && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12474                                                 {
12475                                                         mixer_notify_source_removed(notify_plci, plci_b_id);
12476                                                 }
12477                                         }
12478                                 }
12479                                 mixer_clear_config(plci);
12480                                 mixer_calculate_coefs(a);
12481                                 mixer_notify_update(plci, true);
12482                         }
12483                         li_config_table[i].plci = NULL;
12484                         plci->li_bchannel_id = 0;
12485                 }
12486         }
12487 }
12488
12489
12490 /*------------------------------------------------------------------*/
12491 /* Echo canceller facilities                                        */
12492 /*------------------------------------------------------------------*/
12493
12494
12495 static void ec_write_parameters(PLCI *plci)
12496 {
12497         word w;
12498         byte parameter_buffer[6];
12499
12500         dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12501                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12502                         (char *)(FILE_), __LINE__));
12503
12504         parameter_buffer[0] = 5;
12505         parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12506         PUT_WORD(&parameter_buffer[2], plci->ec_idi_options);
12507         plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12508         w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12509         PUT_WORD(&parameter_buffer[4], w);
12510         add_p(plci, FTY, parameter_buffer);
12511         sig_req(plci, TEL_CTRL, 0);
12512         send_req(plci);
12513 }
12514
12515
12516 static void ec_clear_config(PLCI *plci)
12517 {
12518
12519         dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12520                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12521                         (char *)(FILE_), __LINE__));
12522
12523         plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12524                 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12525         plci->ec_tail_length = 0;
12526 }
12527
12528
12529 static void ec_prepare_switch(dword Id, PLCI *plci)
12530 {
12531
12532         dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12533                         UnMapId(Id), (char *)(FILE_), __LINE__));
12534
12535 }
12536
12537
12538 static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12539 {
12540
12541         dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12542                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12543
12544         return (GOOD);
12545 }
12546
12547
12548 static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12549 {
12550         word Info;
12551
12552         dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12553                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12554
12555         Info = GOOD;
12556         if (plci->B1_facilities & B1_FACILITY_EC)
12557         {
12558                 switch (plci->adjust_b_state)
12559                 {
12560                 case ADJUST_B_RESTORE_EC_1:
12561                         plci->internal_command = plci->adjust_b_command;
12562                         if (plci->sig_req)
12563                         {
12564                                 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12565                                 break;
12566                         }
12567                         ec_write_parameters(plci);
12568                         plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12569                         break;
12570                 case ADJUST_B_RESTORE_EC_2:
12571                         if ((Rc != OK) && (Rc != OK_FC))
12572                         {
12573                                 dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12574                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12575                                 Info = _WRONG_STATE;
12576                                 break;
12577                         }
12578                         break;
12579                 }
12580         }
12581         return (Info);
12582 }
12583
12584
12585 static void ec_command(dword Id, PLCI *plci, byte Rc)
12586 {
12587         word internal_command, Info;
12588         byte result[8];
12589
12590         dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12591                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12592                         plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12593
12594         Info = GOOD;
12595         if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12596         {
12597                 result[0] = 2;
12598                 PUT_WORD(&result[1], EC_SUCCESS);
12599         }
12600         else
12601         {
12602                 result[0] = 5;
12603                 PUT_WORD(&result[1], plci->ec_cmd);
12604                 result[3] = 2;
12605                 PUT_WORD(&result[4], GOOD);
12606         }
12607         internal_command = plci->internal_command;
12608         plci->internal_command = 0;
12609         switch (plci->ec_cmd)
12610         {
12611         case EC_ENABLE_OPERATION:
12612         case EC_FREEZE_COEFFICIENTS:
12613         case EC_RESUME_COEFFICIENT_UPDATE:
12614         case EC_RESET_COEFFICIENTS:
12615                 switch (internal_command)
12616                 {
12617                 default:
12618                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12619                                                                   B1_FACILITY_EC), EC_COMMAND_1);
12620                         /* fall through */
12621                 case EC_COMMAND_1:
12622                         if (adjust_b_process(Id, plci, Rc) != GOOD)
12623                         {
12624                                 dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12625                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12626                                 Info = _FACILITY_NOT_SUPPORTED;
12627                                 break;
12628                         }
12629                         if (plci->internal_command)
12630                                 return;
12631                         /* fall through */
12632                 case EC_COMMAND_2:
12633                         if (plci->sig_req)
12634                         {
12635                                 plci->internal_command = EC_COMMAND_2;
12636                                 return;
12637                         }
12638                         plci->internal_command = EC_COMMAND_3;
12639                         ec_write_parameters(plci);
12640                         return;
12641                 case EC_COMMAND_3:
12642                         if ((Rc != OK) && (Rc != OK_FC))
12643                         {
12644                                 dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12645                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12646                                 Info = _FACILITY_NOT_SUPPORTED;
12647                                 break;
12648                         }
12649                         break;
12650                 }
12651                 break;
12652
12653         case EC_DISABLE_OPERATION:
12654                 switch (internal_command)
12655                 {
12656                 default:
12657                 case EC_COMMAND_1:
12658                         if (plci->B1_facilities & B1_FACILITY_EC)
12659                         {
12660                                 if (plci->sig_req)
12661                                 {
12662                                         plci->internal_command = EC_COMMAND_1;
12663                                         return;
12664                                 }
12665                                 plci->internal_command = EC_COMMAND_2;
12666                                 ec_write_parameters(plci);
12667                                 return;
12668                         }
12669                         Rc = OK;
12670                         /* fall through */
12671                 case EC_COMMAND_2:
12672                         if ((Rc != OK) && (Rc != OK_FC))
12673                         {
12674                                 dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12675                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12676                                 Info = _FACILITY_NOT_SUPPORTED;
12677                                 break;
12678                         }
12679                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12680                                                                   ~B1_FACILITY_EC), EC_COMMAND_3);
12681                         /* fall through */
12682                 case EC_COMMAND_3:
12683                         if (adjust_b_process(Id, plci, Rc) != GOOD)
12684                         {
12685                                 dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12686                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12687                                 Info = _FACILITY_NOT_SUPPORTED;
12688                                 break;
12689                         }
12690                         if (plci->internal_command)
12691                                 return;
12692                         break;
12693                 }
12694                 break;
12695         }
12696         sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12697               "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12698               PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12699 }
12700
12701
12702 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
12703 {
12704         word Info;
12705         word opt;
12706         API_PARSE ec_parms[3];
12707         byte result[16];
12708
12709         dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12710                         UnMapId(Id), (char *)(FILE_), __LINE__));
12711
12712         Info = GOOD;
12713         result[0] = 0;
12714         if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12715         {
12716                 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12717                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12718                 Info = _FACILITY_NOT_SUPPORTED;
12719         }
12720         else
12721         {
12722                 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12723                 {
12724                         if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12725                         {
12726                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12727                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12728                                 Info = _WRONG_MESSAGE_FORMAT;
12729                         }
12730                         else
12731                         {
12732                                 if (plci == NULL)
12733                                 {
12734                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12735                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12736                                         Info = _WRONG_IDENTIFIER;
12737                                 }
12738                                 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12739                                 {
12740                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12741                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12742                                         Info = _WRONG_STATE;
12743                                 }
12744                                 else
12745                                 {
12746                                         plci->command = 0;
12747                                         plci->ec_cmd = GET_WORD(ec_parms[0].info);
12748                                         plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12749                                         result[0] = 2;
12750                                         PUT_WORD(&result[1], EC_SUCCESS);
12751                                         if (msg[1].length >= 4)
12752                                         {
12753                                                 opt = GET_WORD(&ec_parms[0].info[2]);
12754                                                 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12755                                                                           LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12756                                                 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12757                                                         plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12758                                                 if (opt & EC_DETECT_DISABLE_TONE)
12759                                                         plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12760                                                 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12761                                                         plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12762                                                 if (msg[1].length >= 6)
12763                                                 {
12764                                                         plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12765                                                 }
12766                                         }
12767                                         switch (plci->ec_cmd)
12768                                         {
12769                                         case EC_ENABLE_OPERATION:
12770                                                 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12771                                                 start_internal_command(Id, plci, ec_command);
12772                                                 return (false);
12773
12774                                         case EC_DISABLE_OPERATION:
12775                                                 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12776                                                         LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12777                                                         LEC_RESET_COEFFICIENTS;
12778                                                 start_internal_command(Id, plci, ec_command);
12779                                                 return (false);
12780
12781                                         case EC_FREEZE_COEFFICIENTS:
12782                                                 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12783                                                 start_internal_command(Id, plci, ec_command);
12784                                                 return (false);
12785
12786                                         case EC_RESUME_COEFFICIENT_UPDATE:
12787                                                 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12788                                                 start_internal_command(Id, plci, ec_command);
12789                                                 return (false);
12790
12791                                         case EC_RESET_COEFFICIENTS:
12792                                                 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12793                                                 start_internal_command(Id, plci, ec_command);
12794                                                 return (false);
12795
12796                                         default:
12797                                                 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12798                                                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12799                                                 PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12800                                         }
12801                                 }
12802                         }
12803                 }
12804                 else
12805                 {
12806                         if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12807                         {
12808                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12809                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12810                                 Info = _WRONG_MESSAGE_FORMAT;
12811                         }
12812                         else
12813                         {
12814                                 if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12815                                 {
12816                                         result[0] = 11;
12817                                         PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12818                                         result[3] = 8;
12819                                         PUT_WORD(&result[4], GOOD);
12820                                         PUT_WORD(&result[6], 0x0007);
12821                                         PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12822                                         PUT_WORD(&result[10], 0);
12823                                 }
12824                                 else if (plci == NULL)
12825                                 {
12826                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12827                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12828                                         Info = _WRONG_IDENTIFIER;
12829                                 }
12830                                 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12831                                 {
12832                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12833                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12834                                         Info = _WRONG_STATE;
12835                                 }
12836                                 else
12837                                 {
12838                                         plci->command = 0;
12839                                         plci->ec_cmd = GET_WORD(ec_parms[0].info);
12840                                         plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12841                                         result[0] = 5;
12842                                         PUT_WORD(&result[1], plci->ec_cmd);
12843                                         result[3] = 2;
12844                                         PUT_WORD(&result[4], GOOD);
12845                                         plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12846                                                                   LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12847                                         plci->ec_tail_length = 0;
12848                                         if (ec_parms[1].length >= 2)
12849                                         {
12850                                                 opt = GET_WORD(&ec_parms[1].info[1]);
12851                                                 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12852                                                         plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12853                                                 if (opt & EC_DETECT_DISABLE_TONE)
12854                                                         plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12855                                                 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12856                                                         plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12857                                                 if (ec_parms[1].length >= 4)
12858                                                 {
12859                                                         plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12860                                                 }
12861                                         }
12862                                         switch (plci->ec_cmd)
12863                                         {
12864                                         case EC_ENABLE_OPERATION:
12865                                                 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12866                                                 start_internal_command(Id, plci, ec_command);
12867                                                 return (false);
12868
12869                                         case EC_DISABLE_OPERATION:
12870                                                 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12871                                                         LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12872                                                         LEC_RESET_COEFFICIENTS;
12873                                                 start_internal_command(Id, plci, ec_command);
12874                                                 return (false);
12875
12876                                         default:
12877                                                 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12878                                                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12879                                                 PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12880                                         }
12881                                 }
12882                         }
12883                 }
12884         }
12885         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12886               "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12887               PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12888         return (false);
12889 }
12890
12891
12892 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
12893 {
12894         byte result[8];
12895
12896         dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
12897                         UnMapId(Id), (char *)(FILE_), __LINE__));
12898
12899         if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
12900         {
12901                 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12902                 {
12903                         result[0] = 2;
12904                         PUT_WORD(&result[1], 0);
12905                         switch (msg[1])
12906                         {
12907                         case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
12908                                 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
12909                                 break;
12910                         case LEC_DISABLE_TYPE_REVERSED_2100HZ:
12911                                 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
12912                                 break;
12913                         case LEC_DISABLE_RELEASED:
12914                                 PUT_WORD(&result[1], EC_BYPASS_RELEASED);
12915                                 break;
12916                         }
12917                 }
12918                 else
12919                 {
12920                         result[0] = 5;
12921                         PUT_WORD(&result[1], EC_BYPASS_INDICATION);
12922                         result[3] = 2;
12923                         PUT_WORD(&result[4], 0);
12924                         switch (msg[1])
12925                         {
12926                         case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
12927                                 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
12928                                 break;
12929                         case LEC_DISABLE_TYPE_REVERSED_2100HZ:
12930                                 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
12931                                 break;
12932                         case LEC_DISABLE_RELEASED:
12933                                 PUT_WORD(&result[4], EC_BYPASS_RELEASED);
12934                                 break;
12935                         }
12936                 }
12937                 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12938                       PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12939         }
12940 }
12941
12942
12943
12944 /*------------------------------------------------------------------*/
12945 /* Advanced voice                                                   */
12946 /*------------------------------------------------------------------*/
12947
12948 static void adv_voice_write_coefs(PLCI *plci, word write_command)
12949 {
12950         DIVA_CAPI_ADAPTER *a;
12951         word i;
12952         byte *p;
12953
12954         word w, n, j, k;
12955         byte ch_map[MIXER_CHANNELS_BRI];
12956
12957         byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
12958
12959         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
12960                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12961                         (char *)(FILE_), __LINE__, write_command));
12962
12963         a = plci->adapter;
12964         p = coef_buffer + 1;
12965         *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
12966         i = 0;
12967         while (i + sizeof(word) <= a->adv_voice_coef_length)
12968         {
12969                 PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
12970                 p += 2;
12971                 i += 2;
12972         }
12973         while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
12974         {
12975                 PUT_WORD(p, 0x8000);
12976                 p += 2;
12977                 i += 2;
12978         }
12979
12980         if (!a->li_pri && (plci->li_bchannel_id == 0))
12981         {
12982                 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
12983                 {
12984                         plci->li_bchannel_id = 1;
12985                         li_config_table[a->li_base].plci = plci;
12986                         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
12987                                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12988                                         (char *)(FILE_), __LINE__, plci->li_bchannel_id));
12989                 }
12990                 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
12991                 {
12992                         plci->li_bchannel_id = 2;
12993                         li_config_table[a->li_base + 1].plci = plci;
12994                         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
12995                                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12996                                         (char *)(FILE_), __LINE__, plci->li_bchannel_id));
12997                 }
12998         }
12999         if (!a->li_pri && (plci->li_bchannel_id != 0)
13000             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13001         {
13002                 i = a->li_base + (plci->li_bchannel_id - 1);
13003                 switch (write_command)
13004                 {
13005                 case ADV_VOICE_WRITE_ACTIVATION:
13006                         j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13007                         k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13008                         if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13009                         {
13010                                 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13011                                 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13012                         }
13013                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13014                         {
13015                                 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13016                                 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13017                                 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13018                                 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13019                         }
13020                         mixer_calculate_coefs(a);
13021                         li_config_table[i].curchnl = li_config_table[i].channel;
13022                         li_config_table[j].curchnl = li_config_table[j].channel;
13023                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13024                                 li_config_table[k].curchnl = li_config_table[k].channel;
13025                         break;
13026
13027                 case ADV_VOICE_WRITE_DEACTIVATION:
13028                         for (j = 0; j < li_total_channels; j++)
13029                         {
13030                                 li_config_table[i].flag_table[j] = 0;
13031                                 li_config_table[j].flag_table[i] = 0;
13032                         }
13033                         k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13034                         for (j = 0; j < li_total_channels; j++)
13035                         {
13036                                 li_config_table[k].flag_table[j] = 0;
13037                                 li_config_table[j].flag_table[k] = 0;
13038                         }
13039                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13040                         {
13041                                 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13042                                 for (j = 0; j < li_total_channels; j++)
13043                                 {
13044                                         li_config_table[k].flag_table[j] = 0;
13045                                         li_config_table[j].flag_table[k] = 0;
13046                                 }
13047                         }
13048                         mixer_calculate_coefs(a);
13049                         break;
13050                 }
13051                 if (plci->B1_facilities & B1_FACILITY_MIXER)
13052                 {
13053                         w = 0;
13054                         if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13055                                 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13056                         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13057                                 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13058                         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13059                                 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13060                         *(p++) = (byte) w;
13061                         *(p++) = (byte)(w >> 8);
13062                         for (j = 0; j < sizeof(ch_map); j += 2)
13063                         {
13064                                 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13065                                 ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13066                         }
13067                         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13068                         {
13069                                 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13070                                 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13071                                 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13072                                 {
13073                                         *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13074                                         w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13075                                         li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13076                                 }
13077                                 else
13078                                 {
13079                                         *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13080                                                 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13081                                 }
13082                         }
13083                 }
13084                 else
13085                 {
13086                         for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13087                                 *(p++) = a->adv_voice_coef_buffer[i];
13088                 }
13089         }
13090         else
13091
13092         {
13093                 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13094                         *(p++) = a->adv_voice_coef_buffer[i];
13095         }
13096         coef_buffer[0] = (p - coef_buffer) - 1;
13097         add_p(plci, FTY, coef_buffer);
13098         sig_req(plci, TEL_CTRL, 0);
13099         send_req(plci);
13100 }
13101
13102
13103 static void adv_voice_clear_config(PLCI *plci)
13104 {
13105         DIVA_CAPI_ADAPTER *a;
13106
13107         word i, j;
13108
13109
13110         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13111                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13112                         (char *)(FILE_), __LINE__));
13113
13114         a = plci->adapter;
13115         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13116         {
13117                 a->adv_voice_coef_length = 0;
13118
13119                 if (!a->li_pri && (plci->li_bchannel_id != 0)
13120                     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13121                 {
13122                         i = a->li_base + (plci->li_bchannel_id - 1);
13123                         li_config_table[i].curchnl = 0;
13124                         li_config_table[i].channel = 0;
13125                         li_config_table[i].chflags = 0;
13126                         for (j = 0; j < li_total_channels; j++)
13127                         {
13128                                 li_config_table[i].flag_table[j] = 0;
13129                                 li_config_table[j].flag_table[i] = 0;
13130                                 li_config_table[i].coef_table[j] = 0;
13131                                 li_config_table[j].coef_table[i] = 0;
13132                         }
13133                         li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13134                         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13135                         li_config_table[i].curchnl = 0;
13136                         li_config_table[i].channel = 0;
13137                         li_config_table[i].chflags = 0;
13138                         for (j = 0; j < li_total_channels; j++)
13139                         {
13140                                 li_config_table[i].flag_table[j] = 0;
13141                                 li_config_table[j].flag_table[i] = 0;
13142                                 li_config_table[i].coef_table[j] = 0;
13143                                 li_config_table[j].coef_table[i] = 0;
13144                         }
13145                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13146                         {
13147                                 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13148                                 li_config_table[i].curchnl = 0;
13149                                 li_config_table[i].channel = 0;
13150                                 li_config_table[i].chflags = 0;
13151                                 for (j = 0; j < li_total_channels; j++)
13152                                 {
13153                                         li_config_table[i].flag_table[j] = 0;
13154                                         li_config_table[j].flag_table[i] = 0;
13155                                         li_config_table[i].coef_table[j] = 0;
13156                                         li_config_table[j].coef_table[i] = 0;
13157                                 }
13158                         }
13159                 }
13160
13161         }
13162 }
13163
13164
13165 static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13166 {
13167
13168         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13169                         UnMapId(Id), (char *)(FILE_), __LINE__));
13170
13171 }
13172
13173
13174 static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13175 {
13176
13177         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13178                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13179
13180         return (GOOD);
13181 }
13182
13183
13184 static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13185 {
13186         DIVA_CAPI_ADAPTER *a;
13187         word Info;
13188
13189         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13190                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13191
13192         Info = GOOD;
13193         a = plci->adapter;
13194         if ((plci->B1_facilities & B1_FACILITY_VOICE)
13195             && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13196         {
13197                 switch (plci->adjust_b_state)
13198                 {
13199                 case ADJUST_B_RESTORE_VOICE_1:
13200                         plci->internal_command = plci->adjust_b_command;
13201                         if (plci->sig_req)
13202                         {
13203                                 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13204                                 break;
13205                         }
13206                         adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13207                         plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13208                         break;
13209                 case ADJUST_B_RESTORE_VOICE_2:
13210                         if ((Rc != OK) && (Rc != OK_FC))
13211                         {
13212                                 dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13213                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13214                                 Info = _WRONG_STATE;
13215                                 break;
13216                         }
13217                         break;
13218                 }
13219         }
13220         return (Info);
13221 }
13222
13223
13224
13225
13226 /*------------------------------------------------------------------*/
13227 /* B1 resource switching                                            */
13228 /*------------------------------------------------------------------*/
13229
13230 static byte b1_facilities_table[] =
13231 {
13232         0x00,  /* 0  No bchannel resources      */
13233         0x00,  /* 1  Codec (automatic law)      */
13234         0x00,  /* 2  Codec (A-law)              */
13235         0x00,  /* 3  Codec (y-law)              */
13236         0x00,  /* 4  HDLC for X.21              */
13237         0x00,  /* 5  HDLC                       */
13238         0x00,  /* 6  External Device 0          */
13239         0x00,  /* 7  External Device 1          */
13240         0x00,  /* 8  HDLC 56k                   */
13241         0x00,  /* 9  Transparent                */
13242         0x00,  /* 10 Loopback to network        */
13243         0x00,  /* 11 Test pattern to net        */
13244         0x00,  /* 12 Rate adaptation sync       */
13245         0x00,  /* 13 Rate adaptation async      */
13246         0x00,  /* 14 R-Interface                */
13247         0x00,  /* 15 HDLC 128k leased line      */
13248         0x00,  /* 16 FAX                        */
13249         0x00,  /* 17 Modem async                */
13250         0x00,  /* 18 Modem sync HDLC            */
13251         0x00,  /* 19 V.110 async HDLC           */
13252         0x12,  /* 20 Adv voice (Trans,mixer)    */
13253         0x00,  /* 21 Codec connected to IC      */
13254         0x0c,  /* 22 Trans,DTMF                 */
13255         0x1e,  /* 23 Trans,DTMF+mixer           */
13256         0x1f,  /* 24 Trans,DTMF+mixer+local     */
13257         0x13,  /* 25 Trans,mixer+local          */
13258         0x12,  /* 26 HDLC,mixer                 */
13259         0x12,  /* 27 HDLC 56k,mixer             */
13260         0x2c,  /* 28 Trans,LEC+DTMF             */
13261         0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13262         0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13263         0x2c,  /* 31 RTP,LEC+DTMF               */
13264         0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13265         0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13266         0x00,  /* 34 Signaling task             */
13267         0x00,  /* 35 PIAFS                      */
13268         0x0c,  /* 36 Trans,DTMF+TONE            */
13269         0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13270         0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13271 };
13272
13273
13274 static word get_b1_facilities(PLCI *plci, byte b1_resource)
13275 {
13276         word b1_facilities;
13277
13278         b1_facilities = b1_facilities_table[b1_resource];
13279         if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13280         {
13281
13282                 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13283                       || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13284
13285                 {
13286                         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13287                                 b1_facilities |= B1_FACILITY_DTMFX;
13288                         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13289                                 b1_facilities |= B1_FACILITY_DTMFR;
13290                 }
13291         }
13292         if ((b1_resource == 17) || (b1_resource == 18))
13293         {
13294                 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13295                         b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13296         }
13297 /*
13298   dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13299   (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13300   (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13301 */
13302         return (b1_facilities);
13303 }
13304
13305
13306 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13307 {
13308         byte b;
13309
13310         switch (b1_resource)
13311         {
13312         case 5:
13313         case 26:
13314                 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13315                         b = 26;
13316                 else
13317                         b = 5;
13318                 break;
13319
13320         case 8:
13321         case 27:
13322                 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13323                         b = 27;
13324                 else
13325                         b = 8;
13326                 break;
13327
13328         case 9:
13329         case 20:
13330         case 22:
13331         case 23:
13332         case 24:
13333         case 25:
13334         case 28:
13335         case 29:
13336         case 30:
13337         case 36:
13338         case 37:
13339         case 38:
13340                 if (b1_facilities & B1_FACILITY_EC)
13341                 {
13342                         if (b1_facilities & B1_FACILITY_LOCAL)
13343                                 b = 30;
13344                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13345                                 b = 29;
13346                         else
13347                                 b = 28;
13348                 }
13349
13350                 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13351                          && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13352                              || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13353                 {
13354                         if (b1_facilities & B1_FACILITY_LOCAL)
13355                                 b = 38;
13356                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13357                                 b = 37;
13358                         else
13359                                 b = 36;
13360                 }
13361
13362                 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13363                           && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13364                          || ((b1_facilities & B1_FACILITY_DTMFR)
13365                              && ((b1_facilities & B1_FACILITY_MIXER)
13366                                  || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13367                          || ((b1_facilities & B1_FACILITY_DTMFX)
13368                              && ((b1_facilities & B1_FACILITY_MIXER)
13369                                  || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13370                 {
13371                         if (b1_facilities & B1_FACILITY_LOCAL)
13372                                 b = 24;
13373                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13374                                 b = 23;
13375                         else
13376                                 b = 22;
13377                 }
13378                 else
13379                 {
13380                         if (b1_facilities & B1_FACILITY_LOCAL)
13381                                 b = 25;
13382                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13383                                 b = 20;
13384                         else
13385                                 b = 9;
13386                 }
13387                 break;
13388
13389         case 31:
13390         case 32:
13391         case 33:
13392                 if (b1_facilities & B1_FACILITY_LOCAL)
13393                         b = 33;
13394                 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13395                         b = 32;
13396                 else
13397                         b = 31;
13398                 break;
13399
13400         default:
13401                 b = b1_resource;
13402         }
13403         dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13404                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13405                         (char *)(FILE_), __LINE__,
13406                         b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13407         return (b);
13408 }
13409
13410
13411 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13412 {
13413         word removed_facilities;
13414
13415         dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13416                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13417                         (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13418                         new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13419
13420         new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13421         removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13422
13423         if (removed_facilities & B1_FACILITY_EC)
13424                 ec_clear_config(plci);
13425
13426
13427         if (removed_facilities & B1_FACILITY_DTMFR)
13428         {
13429                 dtmf_rec_clear_config(plci);
13430                 dtmf_parameter_clear_config(plci);
13431         }
13432         if (removed_facilities & B1_FACILITY_DTMFX)
13433                 dtmf_send_clear_config(plci);
13434
13435
13436         if (removed_facilities & B1_FACILITY_MIXER)
13437                 mixer_clear_config(plci);
13438
13439         if (removed_facilities & B1_FACILITY_VOICE)
13440                 adv_voice_clear_config(plci);
13441         plci->B1_facilities = new_b1_facilities;
13442 }
13443
13444
13445 static void adjust_b_clear(PLCI *plci)
13446 {
13447
13448         dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13449                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13450                         (char *)(FILE_), __LINE__));
13451
13452         plci->adjust_b_restore = false;
13453 }
13454
13455
13456 static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13457 {
13458         word Info;
13459         byte b1_resource;
13460         NCCI *ncci_ptr;
13461         API_PARSE bp[2];
13462
13463         dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13464                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13465
13466         Info = GOOD;
13467         switch (plci->adjust_b_state)
13468         {
13469         case ADJUST_B_START:
13470                 if ((plci->adjust_b_parms_msg == NULL)
13471                     && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13472                     && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13473                                                  ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13474                 {
13475                         b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13476                                 0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13477                         if (b1_resource == plci->B1_resource)
13478                         {
13479                                 adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13480                                 break;
13481                         }
13482                         if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13483                         {
13484                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13485                                                 UnMapId(Id), (char *)(FILE_), __LINE__,
13486                                                 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13487                                 Info = _WRONG_STATE;
13488                                 break;
13489                         }
13490                 }
13491                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13492                 {
13493
13494                         mixer_prepare_switch(Id, plci);
13495
13496
13497                         dtmf_prepare_switch(Id, plci);
13498                         dtmf_parameter_prepare_switch(Id, plci);
13499
13500
13501                         ec_prepare_switch(Id, plci);
13502
13503                         adv_voice_prepare_switch(Id, plci);
13504                 }
13505                 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13506                 Rc = OK;
13507                 /* fall through */
13508         case ADJUST_B_SAVE_MIXER_1:
13509                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13510                 {
13511
13512                         Info = mixer_save_config(Id, plci, Rc);
13513                         if ((Info != GOOD) || plci->internal_command)
13514                                 break;
13515
13516                 }
13517                 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13518                 Rc = OK;
13519                 /* fall through */
13520         case ADJUST_B_SAVE_DTMF_1:
13521                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13522                 {
13523
13524                         Info = dtmf_save_config(Id, plci, Rc);
13525                         if ((Info != GOOD) || plci->internal_command)
13526                                 break;
13527
13528                 }
13529                 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13530                 /* fall through */
13531         case ADJUST_B_REMOVE_L23_1:
13532                 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13533                     && plci->NL.Id && !plci->nl_remove_id)
13534                 {
13535                         plci->internal_command = plci->adjust_b_command;
13536                         if (plci->adjust_b_ncci != 0)
13537                         {
13538                                 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13539                                 while (ncci_ptr->data_pending)
13540                                 {
13541                                         plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13542                                         data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13543                                 }
13544                                 while (ncci_ptr->data_ack_pending)
13545                                         data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13546                         }
13547                         nl_req_ncci(plci, REMOVE,
13548                                     (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13549                         send_req(plci);
13550                         plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13551                         break;
13552                 }
13553                 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13554                 Rc = OK;
13555                 /* fall through */
13556         case ADJUST_B_REMOVE_L23_2:
13557                 if ((Rc != OK) && (Rc != OK_FC))
13558                 {
13559                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13560                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13561                         Info = _WRONG_STATE;
13562                         break;
13563                 }
13564                 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13565                 {
13566                         if (plci_nl_busy(plci))
13567                         {
13568                                 plci->internal_command = plci->adjust_b_command;
13569                                 break;
13570                         }
13571                 }
13572                 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13573                 Rc = OK;
13574                 /* fall through */
13575         case ADJUST_B_SAVE_EC_1:
13576                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13577                 {
13578
13579                         Info = ec_save_config(Id, plci, Rc);
13580                         if ((Info != GOOD) || plci->internal_command)
13581                                 break;
13582
13583                 }
13584                 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13585                 Rc = OK;
13586                 /* fall through */
13587         case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13588                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13589                 {
13590
13591                         Info = dtmf_parameter_save_config(Id, plci, Rc);
13592                         if ((Info != GOOD) || plci->internal_command)
13593                                 break;
13594
13595                 }
13596                 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13597                 Rc = OK;
13598                 /* fall through */
13599         case ADJUST_B_SAVE_VOICE_1:
13600                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13601                 {
13602                         Info = adv_voice_save_config(Id, plci, Rc);
13603                         if ((Info != GOOD) || plci->internal_command)
13604                                 break;
13605                 }
13606                 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13607                 /* fall through */
13608         case ADJUST_B_SWITCH_L1_1:
13609                 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13610                 {
13611                         if (plci->sig_req)
13612                         {
13613                                 plci->internal_command = plci->adjust_b_command;
13614                                 break;
13615                         }
13616                         if (plci->adjust_b_parms_msg != NULL)
13617                                 api_load_msg(plci->adjust_b_parms_msg, bp);
13618                         else
13619                                 api_load_msg(&plci->B_protocol, bp);
13620                         Info = add_b1(plci, bp,
13621                                       (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13622                                       plci->adjust_b_facilities);
13623                         if (Info != GOOD)
13624                         {
13625                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13626                                                 UnMapId(Id), (char *)(FILE_), __LINE__,
13627                                                 plci->B1_resource, plci->adjust_b_facilities));
13628                                 break;
13629                         }
13630                         plci->internal_command = plci->adjust_b_command;
13631                         sig_req(plci, RESOURCES, 0);
13632                         send_req(plci);
13633                         plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13634                         break;
13635                 }
13636                 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13637                 Rc = OK;
13638                 /* fall through */
13639         case ADJUST_B_SWITCH_L1_2:
13640                 if ((Rc != OK) && (Rc != OK_FC))
13641                 {
13642                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13643                                         UnMapId(Id), (char *)(FILE_), __LINE__,
13644                                         Rc, plci->B1_resource, plci->adjust_b_facilities));
13645                         Info = _WRONG_STATE;
13646                         break;
13647                 }
13648                 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13649                 Rc = OK;
13650                 /* fall through */
13651         case ADJUST_B_RESTORE_VOICE_1:
13652         case ADJUST_B_RESTORE_VOICE_2:
13653                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13654                 {
13655                         Info = adv_voice_restore_config(Id, plci, Rc);
13656                         if ((Info != GOOD) || plci->internal_command)
13657                                 break;
13658                 }
13659                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13660                 Rc = OK;
13661                 /* fall through */
13662         case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13663         case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13664                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13665                 {
13666
13667                         Info = dtmf_parameter_restore_config(Id, plci, Rc);
13668                         if ((Info != GOOD) || plci->internal_command)
13669                                 break;
13670
13671                 }
13672                 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13673                 Rc = OK;
13674                 /* fall through */
13675         case ADJUST_B_RESTORE_EC_1:
13676         case ADJUST_B_RESTORE_EC_2:
13677                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13678                 {
13679
13680                         Info = ec_restore_config(Id, plci, Rc);
13681                         if ((Info != GOOD) || plci->internal_command)
13682                                 break;
13683
13684                 }
13685                 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13686                 /* fall through */
13687         case ADJUST_B_ASSIGN_L23_1:
13688                 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13689                 {
13690                         if (plci_nl_busy(plci))
13691                         {
13692                                 plci->internal_command = plci->adjust_b_command;
13693                                 break;
13694                         }
13695                         if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13696                                 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13697                         if (plci->adjust_b_parms_msg != NULL)
13698                                 api_load_msg(plci->adjust_b_parms_msg, bp);
13699                         else
13700                                 api_load_msg(&plci->B_protocol, bp);
13701                         Info = add_b23(plci, bp);
13702                         if (Info != GOOD)
13703                         {
13704                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13705                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13706                                 break;
13707                         }
13708                         plci->internal_command = plci->adjust_b_command;
13709                         nl_req_ncci(plci, ASSIGN, 0);
13710                         send_req(plci);
13711                         plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13712                         break;
13713                 }
13714                 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13715                 Rc = ASSIGN_OK;
13716                 /* fall through */
13717         case ADJUST_B_ASSIGN_L23_2:
13718                 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13719                 {
13720                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13721                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13722                         Info = _WRONG_STATE;
13723                         break;
13724                 }
13725                 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13726                 {
13727                         if (Rc != ASSIGN_OK)
13728                         {
13729                                 plci->internal_command = plci->adjust_b_command;
13730                                 break;
13731                         }
13732                 }
13733                 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13734                 {
13735                         plci->adjust_b_restore = true;
13736                         break;
13737                 }
13738                 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13739                 /* fall through */
13740         case ADJUST_B_CONNECT_1:
13741                 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13742                 {
13743                         plci->internal_command = plci->adjust_b_command;
13744                         if (plci_nl_busy(plci))
13745                                 break;
13746                         nl_req_ncci(plci, N_CONNECT, 0);
13747                         send_req(plci);
13748                         plci->adjust_b_state = ADJUST_B_CONNECT_2;
13749                         break;
13750                 }
13751                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13752                 Rc = OK;
13753                 /* fall through */
13754         case ADJUST_B_CONNECT_2:
13755         case ADJUST_B_CONNECT_3:
13756         case ADJUST_B_CONNECT_4:
13757                 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13758                 {
13759                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13760                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13761                         Info = _WRONG_STATE;
13762                         break;
13763                 }
13764                 if (Rc == OK)
13765                 {
13766                         if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13767                         {
13768                                 get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13769                                 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13770                         }
13771                         if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13772                                 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13773                         else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13774                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13775                 }
13776                 else if (Rc == 0)
13777                 {
13778                         if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13779                                 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13780                         else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13781                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13782                 }
13783                 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13784                 {
13785                         plci->internal_command = plci->adjust_b_command;
13786                         break;
13787                 }
13788                 Rc = OK;
13789                 /* fall through */
13790         case ADJUST_B_RESTORE_DTMF_1:
13791         case ADJUST_B_RESTORE_DTMF_2:
13792                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13793                 {
13794
13795                         Info = dtmf_restore_config(Id, plci, Rc);
13796                         if ((Info != GOOD) || plci->internal_command)
13797                                 break;
13798
13799                 }
13800                 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13801                 Rc = OK;
13802                 /* fall through */
13803         case ADJUST_B_RESTORE_MIXER_1:
13804         case ADJUST_B_RESTORE_MIXER_2:
13805         case ADJUST_B_RESTORE_MIXER_3:
13806         case ADJUST_B_RESTORE_MIXER_4:
13807         case ADJUST_B_RESTORE_MIXER_5:
13808         case ADJUST_B_RESTORE_MIXER_6:
13809         case ADJUST_B_RESTORE_MIXER_7:
13810                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13811                 {
13812
13813                         Info = mixer_restore_config(Id, plci, Rc);
13814                         if ((Info != GOOD) || plci->internal_command)
13815                                 break;
13816
13817                 }
13818                 plci->adjust_b_state = ADJUST_B_END;
13819         case ADJUST_B_END:
13820                 break;
13821         }
13822         return (Info);
13823 }
13824
13825
13826 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13827 {
13828
13829         dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13830                         UnMapId(Id), (char *)(FILE_), __LINE__,
13831                         plci->B1_resource, b1_facilities));
13832
13833         plci->adjust_b_parms_msg = bp_msg;
13834         plci->adjust_b_facilities = b1_facilities;
13835         plci->adjust_b_command = internal_command;
13836         plci->adjust_b_ncci = (word)(Id >> 16);
13837         if ((bp_msg == NULL) && (plci->B1_resource == 0))
13838                 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13839         else
13840                 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13841         plci->adjust_b_state = ADJUST_B_START;
13842         dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13843                         UnMapId(Id), (char *)(FILE_), __LINE__,
13844                         plci->B1_resource, b1_facilities));
13845 }
13846
13847
13848 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13849 {
13850         word internal_command;
13851
13852         dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13853                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13854
13855         internal_command = plci->internal_command;
13856         plci->internal_command = 0;
13857         switch (internal_command)
13858         {
13859         default:
13860                 plci->command = 0;
13861                 if (plci->req_in != 0)
13862                 {
13863                         plci->internal_command = ADJUST_B_RESTORE_1;
13864                         break;
13865                 }
13866                 Rc = OK;
13867                 /* fall through */
13868         case ADJUST_B_RESTORE_1:
13869                 if ((Rc != OK) && (Rc != OK_FC))
13870                 {
13871                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13872                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13873                 }
13874                 plci->adjust_b_parms_msg = NULL;
13875                 plci->adjust_b_facilities = plci->B1_facilities;
13876                 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13877                 plci->adjust_b_ncci = (word)(Id >> 16);
13878                 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13879                 plci->adjust_b_state = ADJUST_B_START;
13880                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13881                                 UnMapId(Id), (char *)(FILE_), __LINE__));
13882                 /* fall through */
13883         case ADJUST_B_RESTORE_2:
13884                 if (adjust_b_process(Id, plci, Rc) != GOOD)
13885                 {
13886                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13887                                         UnMapId(Id), (char *)(FILE_), __LINE__));
13888                 }
13889                 if (plci->internal_command)
13890                         break;
13891                 break;
13892         }
13893 }
13894
13895
13896 static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
13897 {
13898         word Info;
13899         word internal_command;
13900
13901         dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
13902                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13903
13904         Info = GOOD;
13905         internal_command = plci->internal_command;
13906         plci->internal_command = 0;
13907         switch (internal_command)
13908         {
13909         default:
13910                 plci->command = 0;
13911                 plci->adjust_b_parms_msg = NULL;
13912                 plci->adjust_b_facilities = plci->B1_facilities;
13913                 plci->adjust_b_command = RESET_B3_COMMAND_1;
13914                 plci->adjust_b_ncci = (word)(Id >> 16);
13915                 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
13916                 plci->adjust_b_state = ADJUST_B_START;
13917                 dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
13918                                 UnMapId(Id), (char *)(FILE_), __LINE__));
13919                 /* fall through */
13920         case RESET_B3_COMMAND_1:
13921                 Info = adjust_b_process(Id, plci, Rc);
13922                 if (Info != GOOD)
13923                 {
13924                         dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
13925                                         UnMapId(Id), (char *)(FILE_), __LINE__));
13926                         break;
13927                 }
13928                 if (plci->internal_command)
13929                         return;
13930                 break;
13931         }
13932 /*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
13933         sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
13934 }
13935
13936
13937 static void select_b_command(dword Id, PLCI *plci, byte Rc)
13938 {
13939         word Info;
13940         word internal_command;
13941         byte esc_chi[3];
13942
13943         dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
13944                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13945
13946         Info = GOOD;
13947         internal_command = plci->internal_command;
13948         plci->internal_command = 0;
13949         switch (internal_command)
13950         {
13951         default:
13952                 plci->command = 0;
13953                 plci->adjust_b_parms_msg = &plci->saved_msg;
13954                 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
13955                         plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
13956                 else
13957                         plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
13958                 plci->adjust_b_command = SELECT_B_COMMAND_1;
13959                 plci->adjust_b_ncci = (word)(Id >> 16);
13960                 if (plci->saved_msg.parms[0].length == 0)
13961                 {
13962                         plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
13963                                 ADJUST_B_MODE_NO_RESOURCE;
13964                 }
13965                 else
13966                 {
13967                         plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
13968                                 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
13969                 }
13970                 plci->adjust_b_state = ADJUST_B_START;
13971                 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
13972                                 UnMapId(Id), (char *)(FILE_), __LINE__));
13973                 /* fall through */
13974         case SELECT_B_COMMAND_1:
13975                 Info = adjust_b_process(Id, plci, Rc);
13976                 if (Info != GOOD)
13977                 {
13978                         dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
13979                                         UnMapId(Id), (char *)(FILE_), __LINE__));
13980                         break;
13981                 }
13982                 if (plci->internal_command)
13983                         return;
13984                 if (plci->tel == ADV_VOICE)
13985                 {
13986                         esc_chi[0] = 0x02;
13987                         esc_chi[1] = 0x18;
13988                         esc_chi[2] = plci->b_channel;
13989                         SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
13990                 }
13991                 break;
13992         }
13993         sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
13994 }
13995
13996
13997 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
13998 {
13999         word internal_command;
14000
14001         dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14002                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14003
14004         internal_command = plci->internal_command;
14005         plci->internal_command = 0;
14006         switch (internal_command)
14007         {
14008         default:
14009                 plci->command = 0; /* fall through */
14010         case FAX_CONNECT_ACK_COMMAND_1:
14011                 if (plci_nl_busy(plci))
14012                 {
14013                         plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14014                         return;
14015                 }
14016                 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14017                 plci->NData[0].P = plci->fax_connect_info_buffer;
14018                 plci->NData[0].PLength = plci->fax_connect_info_length;
14019                 plci->NL.X = plci->NData;
14020                 plci->NL.ReqCh = 0;
14021                 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14022                 plci->adapter->request(&plci->NL);
14023                 return;
14024         case FAX_CONNECT_ACK_COMMAND_2:
14025                 if ((Rc != OK) && (Rc != OK_FC))
14026                 {
14027                         dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14028                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14029                         break;
14030                 }
14031         }
14032         if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14033             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14034         {
14035                 if (plci->B3_prot == 4)
14036                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14037                 else
14038                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
14039                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14040         }
14041 }
14042
14043
14044 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14045 {
14046         word internal_command;
14047
14048         dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14049                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14050
14051         internal_command = plci->internal_command;
14052         plci->internal_command = 0;
14053         switch (internal_command)
14054         {
14055         default:
14056                 plci->command = 0;
14057                 /* fall through */
14058         case FAX_EDATA_ACK_COMMAND_1:
14059                 if (plci_nl_busy(plci))
14060                 {
14061                         plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14062                         return;
14063                 }
14064                 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14065                 plci->NData[0].P = plci->fax_connect_info_buffer;
14066                 plci->NData[0].PLength = plci->fax_edata_ack_length;
14067                 plci->NL.X = plci->NData;
14068                 plci->NL.ReqCh = 0;
14069                 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14070                 plci->adapter->request(&plci->NL);
14071                 return;
14072         case FAX_EDATA_ACK_COMMAND_2:
14073                 if ((Rc != OK) && (Rc != OK_FC))
14074                 {
14075                         dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14076                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14077                         break;
14078                 }
14079         }
14080 }
14081
14082
14083 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14084 {
14085         word Info;
14086         word internal_command;
14087
14088         dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14089                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14090
14091         Info = GOOD;
14092         internal_command = plci->internal_command;
14093         plci->internal_command = 0;
14094         switch (internal_command)
14095         {
14096         default:
14097                 plci->command = 0; /* fall through */
14098         case FAX_CONNECT_INFO_COMMAND_1:
14099                 if (plci_nl_busy(plci))
14100                 {
14101                         plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14102                         return;
14103                 }
14104                 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14105                 plci->NData[0].P = plci->fax_connect_info_buffer;
14106                 plci->NData[0].PLength = plci->fax_connect_info_length;
14107                 plci->NL.X = plci->NData;
14108                 plci->NL.ReqCh = 0;
14109                 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14110                 plci->adapter->request(&plci->NL);
14111                 return;
14112         case FAX_CONNECT_INFO_COMMAND_2:
14113                 if ((Rc != OK) && (Rc != OK_FC))
14114                 {
14115                         dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14116                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14117                         Info = _WRONG_STATE;
14118                         break;
14119                 }
14120                 if (plci_nl_busy(plci))
14121                 {
14122                         plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14123                         return;
14124                 }
14125                 plci->command = _CONNECT_B3_R;
14126                 nl_req_ncci(plci, N_CONNECT, 0);
14127                 send_req(plci);
14128                 return;
14129         }
14130         sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14131 }
14132
14133
14134 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14135 {
14136         word Info;
14137         word internal_command;
14138
14139         dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14140                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14141
14142         Info = GOOD;
14143         internal_command = plci->internal_command;
14144         plci->internal_command = 0;
14145         switch (internal_command)
14146         {
14147         default:
14148                 plci->command = 0;
14149                 plci->adjust_b_parms_msg = NULL;
14150                 plci->adjust_b_facilities = plci->B1_facilities;
14151                 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14152                 plci->adjust_b_ncci = (word)(Id >> 16);
14153                 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14154                 plci->adjust_b_state = ADJUST_B_START;
14155                 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14156                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14157                 /* fall through */
14158         case FAX_ADJUST_B23_COMMAND_1:
14159                 Info = adjust_b_process(Id, plci, Rc);
14160                 if (Info != GOOD)
14161                 {
14162                         dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14163                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14164                         break;
14165                 }
14166                 if (plci->internal_command)
14167                         return;
14168                 /* fall through */
14169         case FAX_ADJUST_B23_COMMAND_2:
14170                 if (plci_nl_busy(plci))
14171                 {
14172                         plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14173                         return;
14174                 }
14175                 plci->command = _CONNECT_B3_R;
14176                 nl_req_ncci(plci, N_CONNECT, 0);
14177                 send_req(plci);
14178                 return;
14179         }
14180         sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14181 }
14182
14183
14184 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14185 {
14186         word internal_command;
14187
14188         dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14189                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14190
14191         internal_command = plci->internal_command;
14192         plci->internal_command = 0;
14193         switch (internal_command)
14194         {
14195         default:
14196                 plci->command = 0;
14197                 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14198                 return;
14199         case FAX_DISCONNECT_COMMAND_1:
14200         case FAX_DISCONNECT_COMMAND_2:
14201         case FAX_DISCONNECT_COMMAND_3:
14202                 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14203                 {
14204                         dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14205                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14206                         break;
14207                 }
14208                 if (Rc == OK)
14209                 {
14210                         if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14211                             || (internal_command == FAX_DISCONNECT_COMMAND_2))
14212                         {
14213                                 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14214                         }
14215                 }
14216                 else if (Rc == 0)
14217                 {
14218                         if (internal_command == FAX_DISCONNECT_COMMAND_1)
14219                                 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14220                 }
14221                 return;
14222         }
14223 }
14224
14225
14226
14227 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14228 {
14229         word Info;
14230         word internal_command;
14231
14232         dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14233                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14234
14235         Info = GOOD;
14236         internal_command = plci->internal_command;
14237         plci->internal_command = 0;
14238         switch (internal_command)
14239         {
14240         default:
14241                 plci->command = 0; /* fall through */
14242         case RTP_CONNECT_B3_REQ_COMMAND_1:
14243                 if (plci_nl_busy(plci))
14244                 {
14245                         plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14246                         return;
14247                 }
14248                 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14249                 nl_req_ncci(plci, N_CONNECT, 0);
14250                 send_req(plci);
14251                 return;
14252         case RTP_CONNECT_B3_REQ_COMMAND_2:
14253                 if ((Rc != OK) && (Rc != OK_FC))
14254                 {
14255                         dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14256                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14257                         Info = _WRONG_STATE;
14258                         break;
14259                 }
14260                 if (plci_nl_busy(plci))
14261                 {
14262                         plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14263                         return;
14264                 }
14265                 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14266                 plci->NData[0].PLength = plci->internal_req_buffer[0];
14267                 plci->NData[0].P = plci->internal_req_buffer + 1;
14268                 plci->NL.X = plci->NData;
14269                 plci->NL.ReqCh = 0;
14270                 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14271                 plci->adapter->request(&plci->NL);
14272                 break;
14273         case RTP_CONNECT_B3_REQ_COMMAND_3:
14274                 return;
14275         }
14276         sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14277 }
14278
14279
14280 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14281 {
14282         word internal_command;
14283
14284         dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14285                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14286
14287         internal_command = plci->internal_command;
14288         plci->internal_command = 0;
14289         switch (internal_command)
14290         {
14291         default:
14292                 plci->command = 0; /* fall through */
14293         case RTP_CONNECT_B3_RES_COMMAND_1:
14294                 if (plci_nl_busy(plci))
14295                 {
14296                         plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14297                         return;
14298                 }
14299                 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14300                 nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14301                 send_req(plci);
14302                 return;
14303         case RTP_CONNECT_B3_RES_COMMAND_2:
14304                 if ((Rc != OK) && (Rc != OK_FC))
14305                 {
14306                         dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14307                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14308                         break;
14309                 }
14310                 if (plci_nl_busy(plci))
14311                 {
14312                         plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14313                         return;
14314                 }
14315                 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14316                 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14317                 plci->NData[0].PLength = plci->internal_req_buffer[0];
14318                 plci->NData[0].P = plci->internal_req_buffer + 1;
14319                 plci->NL.X = plci->NData;
14320                 plci->NL.ReqCh = 0;
14321                 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14322                 plci->adapter->request(&plci->NL);
14323                 return;
14324         case RTP_CONNECT_B3_RES_COMMAND_3:
14325                 return;
14326         }
14327 }
14328
14329
14330
14331 static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14332 {
14333         byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14334         word Info;
14335         word internal_command;
14336
14337         dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14338                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14339
14340         Info = GOOD;
14341         internal_command = plci->internal_command;
14342         plci->internal_command = 0;
14343         switch (internal_command)
14344         {
14345         default:
14346                 if (!plci->NL.Id)
14347                         break;
14348                 plci->command = 0;
14349                 plci->adjust_b_parms_msg = NULL;
14350                 plci->adjust_b_facilities = plci->B1_facilities;
14351                 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14352                 plci->adjust_b_ncci = (word)(Id >> 16);
14353                 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14354                 plci->adjust_b_state = ADJUST_B_START;
14355                 dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14356                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14357                 /* fall through */
14358         case HOLD_SAVE_COMMAND_1:
14359                 Info = adjust_b_process(Id, plci, Rc);
14360                 if (Info != GOOD)
14361                 {
14362                         dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14363                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14364                         break;
14365                 }
14366                 if (plci->internal_command)
14367                         return;
14368         }
14369         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14370 }
14371
14372
14373 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14374 {
14375         byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14376         word Info;
14377         word internal_command;
14378
14379         dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14380                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14381
14382         Info = GOOD;
14383         internal_command = plci->internal_command;
14384         plci->internal_command = 0;
14385         switch (internal_command)
14386         {
14387         default:
14388                 plci->command = 0;
14389                 plci->adjust_b_parms_msg = NULL;
14390                 plci->adjust_b_facilities = plci->B1_facilities;
14391                 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14392                 plci->adjust_b_ncci = (word)(Id >> 16);
14393                 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14394                 plci->adjust_b_state = ADJUST_B_START;
14395                 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14396                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14397                 /* fall through */
14398         case RETRIEVE_RESTORE_COMMAND_1:
14399                 Info = adjust_b_process(Id, plci, Rc);
14400                 if (Info != GOOD)
14401                 {
14402                         dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14403                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14404                         break;
14405                 }
14406                 if (plci->internal_command)
14407                         return;
14408         }
14409         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14410 }
14411
14412
14413 static void init_b1_config(PLCI *plci)
14414 {
14415
14416         dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14417                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14418                         (char *)(FILE_), __LINE__));
14419
14420         plci->B1_resource = 0;
14421         plci->B1_facilities = 0;
14422
14423         plci->li_bchannel_id = 0;
14424         mixer_clear_config(plci);
14425
14426
14427         ec_clear_config(plci);
14428
14429
14430         dtmf_rec_clear_config(plci);
14431         dtmf_send_clear_config(plci);
14432         dtmf_parameter_clear_config(plci);
14433
14434         adv_voice_clear_config(plci);
14435         adjust_b_clear(plci);
14436 }
14437
14438
14439 static void clear_b1_config(PLCI *plci)
14440 {
14441
14442         dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14443                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14444                         (char *)(FILE_), __LINE__));
14445
14446         adv_voice_clear_config(plci);
14447         adjust_b_clear(plci);
14448
14449         ec_clear_config(plci);
14450
14451
14452         dtmf_rec_clear_config(plci);
14453         dtmf_send_clear_config(plci);
14454         dtmf_parameter_clear_config(plci);
14455
14456
14457         if ((plci->li_bchannel_id != 0)
14458             && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14459         {
14460                 mixer_clear_config(plci);
14461                 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14462                 plci->li_bchannel_id = 0;
14463         }
14464
14465         plci->B1_resource = 0;
14466         plci->B1_facilities = 0;
14467 }
14468
14469
14470 /* -----------------------------------------------------------------
14471    XON protocol local helpers
14472    ----------------------------------------------------------------- */
14473 static void channel_flow_control_remove(PLCI *plci) {
14474         DIVA_CAPI_ADAPTER *a = plci->adapter;
14475         word i;
14476         for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14477                 if (a->ch_flow_plci[i] == plci->Id) {
14478                         a->ch_flow_plci[i] = 0;
14479                         a->ch_flow_control[i] = 0;
14480                 }
14481         }
14482 }
14483
14484 static void channel_x_on(PLCI *plci, byte ch) {
14485         DIVA_CAPI_ADAPTER *a = plci->adapter;
14486         if (a->ch_flow_control[ch] & N_XON_SENT) {
14487                 a->ch_flow_control[ch] &= ~N_XON_SENT;
14488         }
14489 }
14490
14491 static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14492         DIVA_CAPI_ADAPTER *a = plci->adapter;
14493         if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14494                 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14495                 a->ch_flow_plci[ch] = plci->Id;
14496                 a->ch_flow_control_pending++;
14497         }
14498 }
14499
14500 static void channel_request_xon(PLCI *plci, byte ch) {
14501         DIVA_CAPI_ADAPTER *a = plci->adapter;
14502
14503         if (a->ch_flow_control[ch] & N_CH_XOFF) {
14504                 a->ch_flow_control[ch] |= N_XON_REQ;
14505                 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14506                 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14507         }
14508 }
14509
14510 static void channel_xmit_extended_xon(PLCI *plci) {
14511         DIVA_CAPI_ADAPTER *a;
14512         int max_ch = ARRAY_SIZE(a->ch_flow_control);
14513         int i, one_requested = 0;
14514
14515         if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14516                 return;
14517         }
14518
14519         for (i = 0; i < max_ch; i++) {
14520                 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14521                     (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14522                     (plci->Id == a->ch_flow_plci[i])) {
14523                         channel_request_xon(plci, (byte)i);
14524                         one_requested = 1;
14525                 }
14526         }
14527
14528         if (one_requested) {
14529                 channel_xmit_xon(plci);
14530         }
14531 }
14532
14533 /*
14534   Try to xmit next X_ON
14535 */
14536 static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14537         int max_ch = ARRAY_SIZE(a->ch_flow_control);
14538         int i;
14539
14540         if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14541                 return (0);
14542         }
14543
14544         if (a->last_flow_control_ch >= max_ch) {
14545                 a->last_flow_control_ch = 1;
14546         }
14547         for (i = a->last_flow_control_ch; i < max_ch; i++) {
14548                 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14549                     (plci->Id == a->ch_flow_plci[i])) {
14550                         a->last_flow_control_ch = i + 1;
14551                         return (i);
14552                 }
14553         }
14554
14555         for (i = 1; i < a->last_flow_control_ch; i++) {
14556                 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14557                     (plci->Id == a->ch_flow_plci[i])) {
14558                         a->last_flow_control_ch = i + 1;
14559                         return (i);
14560                 }
14561         }
14562
14563         return (0);
14564 }
14565
14566 static void channel_xmit_xon(PLCI *plci) {
14567         DIVA_CAPI_ADAPTER *a = plci->adapter;
14568         byte ch;
14569
14570         if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14571                 return;
14572         }
14573         if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14574                 return;
14575         }
14576         a->ch_flow_control[ch] &= ~N_XON_REQ;
14577         a->ch_flow_control[ch] |= N_XON_SENT;
14578
14579         plci->NL.Req = plci->nl_req = (byte)N_XON;
14580         plci->NL.ReqCh         = ch;
14581         plci->NL.X             = plci->NData;
14582         plci->NL.XNum          = 1;
14583         plci->NData[0].P       = &plci->RBuffer[0];
14584         plci->NData[0].PLength = 0;
14585
14586         plci->adapter->request(&plci->NL);
14587 }
14588
14589 static int channel_can_xon(PLCI *plci, byte ch) {
14590         APPL *APPLptr;
14591         DIVA_CAPI_ADAPTER *a;
14592         word NCCIcode;
14593         dword count;
14594         word Num;
14595         word i;
14596
14597         APPLptr = plci->appl;
14598         a = plci->adapter;
14599
14600         if (!APPLptr)
14601                 return (0);
14602
14603         NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14604
14605         /* count all buffers within the Application pool    */
14606         /* belonging to the same NCCI. XON if a first is    */
14607         /* used.                                            */
14608         count = 0;
14609         Num = 0xffff;
14610         for (i = 0; i < APPLptr->MaxBuffer; i++) {
14611                 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14612                 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14613         }
14614         if ((count > 2) || (Num == 0xffff)) {
14615                 return (0);
14616         }
14617         return (1);
14618 }
14619
14620
14621 /*------------------------------------------------------------------*/
14622
14623 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14624 {
14625         return 1;
14626 }
14627
14628
14629
14630 /**********************************************************************************/
14631 /* function groups the listening applications according to the CIP mask and the   */
14632 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14633 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14634 /* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14635 /* function must be enabled by setting "a->group_optimization_enabled" from the   */
14636 /* OS specific part (per adapter).                                                */
14637 /**********************************************************************************/
14638 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14639 {
14640         word i, j, k, busy, group_found;
14641         dword info_mask_group[MAX_CIP_TYPES];
14642         dword cip_mask_group[MAX_CIP_TYPES];
14643         word appl_number_group_type[MAX_APPL];
14644         PLCI *auxplci;
14645
14646         /* all APPLs within this inc. call are allowed to dial in */
14647         bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
14648
14649         if (!a->group_optimization_enabled)
14650         {
14651                 dbug(1, dprintf("No group optimization"));
14652                 return;
14653         }
14654
14655         dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14656
14657         for (i = 0; i < MAX_CIP_TYPES; i++)
14658         {
14659                 info_mask_group[i] = 0;
14660                 cip_mask_group[i] = 0;
14661         }
14662         for (i = 0; i < MAX_APPL; i++)
14663         {
14664                 appl_number_group_type[i] = 0;
14665         }
14666         for (i = 0; i < max_appl; i++) /* check if any multi instance capable application is present */
14667         {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14668                 if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14669                 {
14670                         dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14671                         return; /* allow good application unfiltered access */
14672                 }
14673         }
14674         for (i = 0; i < max_appl; i++) /* Build CIP Groups */
14675         {
14676                 if (application[i].Id && a->CIP_Mask[i])
14677                 {
14678                         for (k = 0, busy = false; k < a->max_plci; k++)
14679                         {
14680                                 if (a->plci[k].Id)
14681                                 {
14682                                         auxplci = &a->plci[k];
14683                                         if (auxplci->appl == &application[i]) {
14684                                                 /* application has a busy PLCI */
14685                                                 busy = true;
14686                                                 dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14687                                         } else if (test_bit(i, plci->c_ind_mask_table)) {
14688                                                 /* application has an incoming call pending */
14689                                                 busy = true;
14690                                                 dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14691                                         }
14692                                 }
14693                         }
14694
14695                         for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++)     /* build groups with free applications only */
14696                         {
14697                                 if (j == MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14698                                 {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14699                                         appl_number_group_type[i] = MAX_CIP_TYPES;
14700                                         group_found = true;
14701                                         dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14702                                 }
14703                                 else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14704                                 {                                      /* is group already present ?                  */
14705                                         appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14706                                         group_found = true;
14707                                         dbug(1, dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx", appl_number_group_type[i], i + 1, info_mask_group[j]));
14708                                 }
14709                                 else if (!info_mask_group[j])
14710                                 {                                      /* establish a new group                       */
14711                                         appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14712                                         info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14713                                         cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14714                                         group_found = true;
14715                                         dbug(1, dprintf("New Group 0x%x established with appl 0x%x, CIP=0x%lx", appl_number_group_type[i], i + 1, info_mask_group[j]));
14716                                 }
14717                         }
14718                 }
14719         }
14720
14721         for (i = 0; i < max_appl; i++) /* Build group_optimization_mask_table */
14722         {
14723                 if (appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14724                 {
14725                         if (appl_number_group_type[i] == MAX_CIP_TYPES)
14726                         {
14727                                 dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14728                         }
14729                         else
14730                         {
14731                                 dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14732                                 for (j = i + 1; j < max_appl; j++)   /* search other group members and mark them as busy        */
14733                                 {
14734                                         if (appl_number_group_type[i] == appl_number_group_type[j])
14735                                         {
14736                                                 dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14737                                                 /* disable call on other group members */
14738                                                 __clear_bit(j, plci->group_optimization_mask_table);
14739                                                 appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14740                                         }
14741                                 }
14742                         }
14743                 }
14744                 else                                                 /* application should not get a call */
14745                 {
14746                         __clear_bit(i, plci->group_optimization_mask_table);
14747                 }
14748         }
14749
14750 }
14751
14752
14753
14754 /* OS notifies the driver about a application Capi_Register */
14755 word CapiRegister(word id)
14756 {
14757         word i, j, appls_found;
14758
14759         PLCI *plci;
14760         DIVA_CAPI_ADAPTER *a;
14761
14762         for (i = 0, appls_found = 0; i < max_appl; i++)
14763         {
14764                 if (application[i].Id && (application[i].Id != id))
14765                 {
14766                         appls_found++;                       /* an application has been found */
14767                 }
14768         }
14769
14770         if (appls_found) return true;
14771         for (i = 0; i < max_adapter; i++)                   /* scan all adapters...    */
14772         {
14773                 a = &adapter[i];
14774                 if (a->request)
14775                 {
14776                         if (a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14777                         {
14778                                 if (!appls_found)           /* first application does a capi register   */
14779                                 {
14780                                         if ((j = get_plci(a)))                    /* activate L1 of all adapters */
14781                                         {
14782                                                 plci = &a->plci[j - 1];
14783                                                 plci->command = 0;
14784                                                 add_p(plci, OAD, "\x01\xfd");
14785                                                 add_p(plci, CAI, "\x01\x80");
14786                                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14787                                                 add_p(plci, SHIFT | 6, NULL);
14788                                                 add_p(plci, SIN, "\x02\x00\x00");
14789                                                 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14790                                                 sig_req(plci, ASSIGN, DSIG_ID);
14791                                                 add_p(plci, FTY, "\x02\xff\x07"); /* l1 start */
14792                                                 sig_req(plci, SIG_CTRL, 0);
14793                                                 send_req(plci);
14794                                         }
14795                                 }
14796                         }
14797                 }
14798         }
14799         return false;
14800 }
14801
14802 /*------------------------------------------------------------------*/
14803
14804 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14805
14806 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14807 {
14808         word i;
14809         /* Format of vswitch_t:
14810            0 byte length
14811            1 byte VSWITCHIE
14812            2 byte VSWITCH_REQ/VSWITCH_IND
14813            3 byte reserved
14814            4 word VSwitchcommand
14815            6 word returnerror
14816            8... Params
14817         */
14818         if (!plci ||
14819             !plci->appl ||
14820             !plci->State ||
14821             plci->Sig.Ind == NCR_FACILITY
14822                 )
14823                 return;
14824
14825         for (i = 0; i < MAX_MULTI_IE; i++)
14826         {
14827                 if (!parms[i][0]) continue;
14828                 if (parms[i][0] < 7)
14829                 {
14830                         parms[i][0] = 0; /* kill it */
14831                         continue;
14832                 }
14833                 dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14834                 switch (parms[i][4])
14835                 {
14836                 case VSJOIN:
14837                         if (!plci->relatedPTYPLCI ||
14838                             (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14839                         { /* Error */
14840                                 break;
14841                         }
14842                         /* remember all necessary informations */
14843                         if (parms[i][0] != 11 || parms[i][8] != 3) /* Length Test */
14844                         {
14845                                 break;
14846                         }
14847                         if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14848                         {   /* first indication after ECT-Request on Consultation Call */
14849                                 plci->vswitchstate = parms[i][9];
14850                                 parms[i][9] = 2; /* State */
14851                                 /* now ask first Call to join */
14852                         }
14853                         else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14854                         { /* Answer of VSWITCH_REQ from first Call */
14855                                 plci->vswitchstate = parms[i][9];
14856                                 /* tell consultation call to join
14857                                    and the protocol capabilities of the first call */
14858                         }
14859                         else
14860                         { /* Error */
14861                                 break;
14862                         }
14863                         plci->vsprot = parms[i][10]; /* protocol */
14864                         plci->vsprotdialect = parms[i][11]; /* protocoldialect */
14865                         /* send join request to related PLCI */
14866                         parms[i][1] = VSWITCHIE;
14867                         parms[i][2] = VSWITCH_REQ;
14868
14869                         plci->relatedPTYPLCI->command = 0;
14870                         plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14871                         add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14872                         sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14873                         send_req(plci->relatedPTYPLCI);
14874                         break;
14875                 case VSTRANSPORT:
14876                 default:
14877                         if (plci->relatedPTYPLCI &&
14878                             plci->vswitchstate == 3 &&
14879                             plci->relatedPTYPLCI->vswitchstate == 3)
14880                         {
14881                                 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14882                                 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14883                                 send_req(plci->relatedPTYPLCI);
14884                         }
14885                         break;
14886                 }
14887                 parms[i][0] = 0; /* kill it */
14888         }
14889 }
14890
14891
14892 /*------------------------------------------------------------------*/
14893
14894 static int diva_get_dma_descriptor(PLCI *plci, dword   *dma_magic) {
14895         ENTITY e;
14896         IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14897
14898         if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14899                 return (-1);
14900         }
14901
14902         pReq->xdi_dma_descriptor_operation.Req = 0;
14903         pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14904
14905         pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14906         pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
14907         pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14908         pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
14909
14910         e.user[0] = plci->adapter->Id - 1;
14911         plci->adapter->request((ENTITY *)pReq);
14912
14913         if (!pReq->xdi_dma_descriptor_operation.info.operation &&
14914             (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
14915             pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
14916                 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
14917                 dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
14918                                 plci->adapter->Id,
14919                                 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
14920                                 *dma_magic));
14921                 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
14922         } else {
14923                 dbug(1, dprintf("dma_alloc failed"));
14924                 return (-1);
14925         }
14926 }
14927
14928 static void diva_free_dma_descriptor(PLCI *plci, int nr) {
14929         ENTITY e;
14930         IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14931
14932         if (nr < 0) {
14933                 return;
14934         }
14935
14936         pReq->xdi_dma_descriptor_operation.Req = 0;
14937         pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14938
14939         pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
14940         pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
14941         pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14942         pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
14943
14944         e.user[0] = plci->adapter->Id - 1;
14945         plci->adapter->request((ENTITY *)pReq);
14946
14947         if (!pReq->xdi_dma_descriptor_operation.info.operation) {
14948                 dbug(1, dprintf("dma_free(%d)", nr));
14949         } else {
14950                 dbug(1, dprintf("dma_free failed (%d)", nr));
14951         }
14952 }
14953
14954 /*------------------------------------------------------------------*/