GNU Linux-libre 4.9.309-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
27
28
29
30 #include "platform.h"
31 #include "di_defs.h"
32 #include "pc.h"
33 #include "capi20.h"
34 #include "divacapi.h"
35 #include "mdm_msg.h"
36 #include "divasync.h"
37
38
39
40 #define FILE_ "MESSAGE.C"
41 #define dprintf
42
43
44
45
46
47
48
49
50
51 /*------------------------------------------------------------------*/
52 /* This is options supported for all adapters that are server by    */
53 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
54 /* and it is not necessary to save it separate for every adapter    */
55 /* Macrose defined here have only local meaning                     */
56 /*------------------------------------------------------------------*/
57 static dword diva_xdi_extended_features = 0;
58
59 #define DIVA_CAPI_USE_CMA                 0x00000001
60 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR  0x00000002
61 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL  0x00000004
62 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA     0x00000008
63
64 /*
65   CAPI can request to process all return codes self only if:
66   protocol code supports this && xdi supports this
67 */
68 #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__)   (((__a__)->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL) && ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) && (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
69
70 /*------------------------------------------------------------------*/
71 /* local function prototypes                                        */
72 /*------------------------------------------------------------------*/
73
74 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci);
75 static void set_group_ind_mask(PLCI *plci);
76 static void clear_group_ind_mask_bit(PLCI *plci, word b);
77 static byte test_group_ind_mask_bit(PLCI *plci, word b);
78 void AutomaticLaw(DIVA_CAPI_ADAPTER *);
79 word CapiRelease(word);
80 word CapiRegister(word);
81 word api_put(APPL *, CAPI_MSG *);
82 static word api_parse(byte *, word, byte *, API_PARSE *);
83 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out);
84 static void api_load_msg(API_SAVE *in, API_PARSE *out);
85
86 word api_remove_start(void);
87 void api_remove_complete(void);
88
89 static void plci_remove(PLCI *);
90 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a);
91 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *);
92
93 void callback(ENTITY *);
94
95 static void control_rc(PLCI *, byte, byte, byte, byte, byte);
96 static void data_rc(PLCI *, byte);
97 static void data_ack(PLCI *, byte);
98 static void sig_ind(PLCI *);
99 static void SendInfo(PLCI *, dword, byte **, byte);
100 static void SendSetupInfo(APPL *, PLCI *, dword, byte **, byte);
101 static void SendSSExtInd(APPL *, PLCI *plci, dword Id, byte **parms);
102
103 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
104
105 static void nl_ind(PLCI *);
106
107 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
108 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
109 static byte connect_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
110 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
111 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
112 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
113 static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
114 static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
115 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
116 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
117 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
118 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
119 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
120 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
121 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
122 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
123 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
124 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
125 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
126 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
127 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
128 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
129 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
130 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
131
132 static word get_plci(DIVA_CAPI_ADAPTER *);
133 static void add_p(PLCI *, byte, byte *);
134 static void add_s(PLCI *plci, byte code, API_PARSE *p);
135 static void add_ss(PLCI *plci, byte code, API_PARSE *p);
136 static void add_ie(PLCI *plci, byte code, byte *p, word p_length);
137 static void add_d(PLCI *, word, byte *);
138 static void add_ai(PLCI *, API_PARSE *);
139 static word add_b1(PLCI *, API_PARSE *, word, word);
140 static word add_b23(PLCI *, API_PARSE *);
141 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms);
142 static void sig_req(PLCI *, byte, byte);
143 static void nl_req_ncci(PLCI *, byte, byte);
144 static void send_req(PLCI *);
145 static void send_data(PLCI *);
146 static word plci_remove_check(PLCI *);
147 static void listen_check(DIVA_CAPI_ADAPTER *);
148 static byte AddInfo(byte **, byte **, byte *, byte *);
149 static byte getChannel(API_PARSE *);
150 static void IndParse(PLCI *, const word *, byte **, byte);
151 static byte ie_compare(byte *, byte *);
152 static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *);
153 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *, word);
154
155 /*
156   XON protocol helpers
157 */
158 static void channel_flow_control_remove(PLCI *plci);
159 static void channel_x_off(PLCI *plci, byte ch, byte flag);
160 static void channel_x_on(PLCI *plci, byte ch);
161 static void channel_request_xon(PLCI *plci, byte ch);
162 static void channel_xmit_xon(PLCI *plci);
163 static int channel_can_xon(PLCI *plci, byte ch);
164 static void channel_xmit_extended_xon(PLCI *plci);
165
166 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type, dword info_mask, byte setupParse);
167 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte);
168 static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *);
169 static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER *);
170 static void VoiceChannelOff(PLCI *plci);
171 static void adv_voice_write_coefs(PLCI *plci, word write_command);
172 static void adv_voice_clear_config(PLCI *plci);
173
174 static word get_b1_facilities(PLCI *plci, byte b1_resource);
175 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities);
176 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities);
177 static word adjust_b_process(dword Id, PLCI *plci, byte Rc);
178 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command);
179 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc);
180 static void reset_b3_command(dword Id, PLCI *plci, byte Rc);
181 static void select_b_command(dword Id, PLCI *plci, byte Rc);
182 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc);
183 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc);
184 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc);
185 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc);
186 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc);
187 static void hold_save_command(dword Id, PLCI *plci, byte Rc);
188 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc);
189 static void init_b1_config(PLCI *plci);
190 static void clear_b1_config(PLCI *plci);
191
192 static void dtmf_command(dword Id, PLCI *plci, byte Rc);
193 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
194 static void dtmf_confirmation(dword Id, PLCI *plci);
195 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length);
196 static void dtmf_parameter_write(PLCI *plci);
197
198
199 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id);
200 static void mixer_set_bchannel_id(PLCI *plci, byte *chi);
201 static void mixer_clear_config(PLCI *plci);
202 static void mixer_notify_update(PLCI *plci, byte others);
203 static void mixer_command(dword Id, PLCI *plci, byte Rc);
204 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
205 static void mixer_indication_coefs_set(dword Id, PLCI *plci);
206 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length);
207 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length);
208 static void mixer_remove(PLCI *plci);
209
210
211 static void ec_command(dword Id, PLCI *plci, byte Rc);
212 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
213 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length);
214
215
216 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc);
217 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc);
218
219
220 static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic);
221 static void diva_free_dma_descriptor(PLCI *plci, int nr);
222
223 /*------------------------------------------------------------------*/
224 /* external function prototypes                                     */
225 /*------------------------------------------------------------------*/
226
227 extern byte MapController(byte);
228 extern byte UnMapController(byte);
229 #define MapId(Id)(((Id) & 0xffffff00L) | MapController((byte)(Id)))
230 #define UnMapId(Id)(((Id) & 0xffffff00L) | UnMapController((byte)(Id)))
231
232 void sendf(APPL *, word, dword, word, byte *, ...);
233 void *TransmitBufferSet(APPL *appl, dword ref);
234 void *TransmitBufferGet(APPL *appl, void *p);
235 void TransmitBufferFree(APPL *appl, void *p);
236 void *ReceiveBufferGet(APPL *appl, int Num);
237
238 int fax_head_line_time(char *buffer);
239
240
241 /*------------------------------------------------------------------*/
242 /* Global data definitions                                          */
243 /*------------------------------------------------------------------*/
244 extern byte max_adapter;
245 extern byte max_appl;
246 extern DIVA_CAPI_ADAPTER *adapter;
247 extern APPL *application;
248
249
250
251
252
253
254
255 static byte remove_started = false;
256 static PLCI dummy_plci;
257
258
259 static struct _ftable {
260         word command;
261         byte *format;
262         byte (*function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
263 } ftable[] = {
264         {_DATA_B3_R,                          "dwww",         data_b3_req},
265         {_DATA_B3_I | RESPONSE,               "w",            data_b3_res},
266         {_INFO_R,                             "ss",           info_req},
267         {_INFO_I | RESPONSE,                  "",             info_res},
268         {_CONNECT_R,                          "wsssssssss",   connect_req},
269         {_CONNECT_I | RESPONSE,               "wsssss",       connect_res},
270         {_CONNECT_ACTIVE_I | RESPONSE,        "",             connect_a_res},
271         {_DISCONNECT_R,                       "s",            disconnect_req},
272         {_DISCONNECT_I | RESPONSE,            "",             disconnect_res},
273         {_LISTEN_R,                           "dddss",        listen_req},
274         {_ALERT_R,                            "s",            alert_req},
275         {_FACILITY_R,                         "ws",           facility_req},
276         {_FACILITY_I | RESPONSE,              "ws",           facility_res},
277         {_CONNECT_B3_R,                       "s",            connect_b3_req},
278         {_CONNECT_B3_I | RESPONSE,            "ws",           connect_b3_res},
279         {_CONNECT_B3_ACTIVE_I | RESPONSE,     "",             connect_b3_a_res},
280         {_DISCONNECT_B3_R,                    "s",            disconnect_b3_req},
281         {_DISCONNECT_B3_I | RESPONSE,         "",             disconnect_b3_res},
282         {_RESET_B3_R,                         "s",            reset_b3_req},
283         {_RESET_B3_I | RESPONSE,              "",             reset_b3_res},
284         {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "ws",           connect_b3_t90_a_res},
285         {_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "",             connect_b3_t90_a_res},
286         {_SELECT_B_REQ,                       "s",            select_b_req},
287         {_MANUFACTURER_R,                     "dws",          manufacturer_req},
288         {_MANUFACTURER_I | RESPONSE,          "dws",          manufacturer_res},
289         {_MANUFACTURER_I | RESPONSE,          "",             manufacturer_res}
290 };
291
292 static byte *cip_bc[29][2] = {
293         { "",                     ""                     }, /* 0 */
294         { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 1 */
295         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 2 */
296         { "\x02\x89\x90",         "\x02\x89\x90"         }, /* 3 */
297         { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 4 */
298         { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 5 */
299         { "\x02\x98\x90",         "\x02\x98\x90"         }, /* 6 */
300         { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
301         { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
302         { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 9 */
303         { "",                     ""                     }, /* 10 */
304         { "",                     ""                     }, /* 11 */
305         { "",                     ""                     }, /* 12 */
306         { "",                     ""                     }, /* 13 */
307         { "",                     ""                     }, /* 14 */
308         { "",                     ""                     }, /* 15 */
309
310         { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 16 */
311         { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 17 */
312         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 18 */
313         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 19 */
314         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 20 */
315         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 21 */
316         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 22 */
317         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 23 */
318         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 24 */
319         { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 25 */
320         { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 26 */
321         { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 27 */
322         { "\x02\x88\x90",         "\x02\x88\x90"         }  /* 28 */
323 };
324
325 static byte *cip_hlc[29] = {
326         "",                           /* 0 */
327         "",                           /* 1 */
328         "",                           /* 2 */
329         "",                           /* 3 */
330         "",                           /* 4 */
331         "",                           /* 5 */
332         "",                           /* 6 */
333         "",                           /* 7 */
334         "",                           /* 8 */
335         "",                           /* 9 */
336         "",                           /* 10 */
337         "",                           /* 11 */
338         "",                           /* 12 */
339         "",                           /* 13 */
340         "",                           /* 14 */
341         "",                           /* 15 */
342
343         "\x02\x91\x81",               /* 16 */
344         "\x02\x91\x84",               /* 17 */
345         "\x02\x91\xa1",               /* 18 */
346         "\x02\x91\xa4",               /* 19 */
347         "\x02\x91\xa8",               /* 20 */
348         "\x02\x91\xb1",               /* 21 */
349         "\x02\x91\xb2",               /* 22 */
350         "\x02\x91\xb5",               /* 23 */
351         "\x02\x91\xb8",               /* 24 */
352         "\x02\x91\xc1",               /* 25 */
353         "\x02\x91\x81",               /* 26 */
354         "\x03\x91\xe0\x01",           /* 27 */
355         "\x03\x91\xe0\x02"            /* 28 */
356 };
357
358 /*------------------------------------------------------------------*/
359
360 #define V120_HEADER_LENGTH 1
361 #define V120_HEADER_EXTEND_BIT  0x80
362 #define V120_HEADER_BREAK_BIT   0x40
363 #define V120_HEADER_C1_BIT      0x04
364 #define V120_HEADER_C2_BIT      0x08
365 #define V120_HEADER_FLUSH_COND  (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
366
367 static byte v120_default_header[] =
368 {
369
370         0x83                          /*  Ext, BR , res, res, C2 , C1 , B  , F   */
371
372 };
373
374 static byte v120_break_header[] =
375 {
376
377         0xc3 | V120_HEADER_BREAK_BIT  /*  Ext, BR , res, res, C2 , C1 , B  , F   */
378
379 };
380
381
382 /*------------------------------------------------------------------*/
383 /* API_PUT function                                                 */
384 /*------------------------------------------------------------------*/
385
386 word api_put(APPL *appl, CAPI_MSG *msg)
387 {
388         word i, j, k, l, n;
389         word ret;
390         byte c;
391         byte controller;
392         DIVA_CAPI_ADAPTER *a;
393         PLCI *plci;
394         NCCI *ncci_ptr;
395         word ncci;
396         CAPI_MSG *m;
397         API_PARSE msg_parms[MAX_MSG_PARMS + 1];
398
399         if (msg->header.length < sizeof(msg->header) ||
400             msg->header.length > MAX_MSG_SIZE) {
401                 dbug(1, dprintf("bad len"));
402                 return _BAD_MSG;
403         }
404
405         controller = (byte)((msg->header.controller & 0x7f) - 1);
406
407         /* controller starts with 0 up to (max_adapter - 1) */
408         if (controller >= max_adapter)
409         {
410                 dbug(1, dprintf("invalid ctrl"));
411                 return _BAD_MSG;
412         }
413
414         a = &adapter[controller];
415         plci = NULL;
416         if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
417         {
418                 dbug(1, dprintf("plci=%x", msg->header.plci));
419                 plci = &a->plci[msg->header.plci - 1];
420                 ncci = GET_WORD(&msg->header.ncci);
421                 if (plci->Id
422                     && (plci->appl
423                         || (plci->State == INC_CON_PENDING)
424                         || (plci->State == INC_CON_ALERT)
425                         || (msg->header.command == (_DISCONNECT_I | RESPONSE)))
426                     && ((ncci == 0)
427                         || (msg->header.command == (_DISCONNECT_B3_I | RESPONSE))
428                         || ((ncci < MAX_NCCI + 1) && (a->ncci_plci[ncci] == plci->Id))))
429                 {
430                         i = plci->msg_in_read_pos;
431                         j = plci->msg_in_write_pos;
432                         if (j >= i)
433                         {
434                                 if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
435                                         i += MSG_IN_QUEUE_SIZE - j;
436                                 else
437                                         j = 0;
438                         }
439                         else
440                         {
441
442                                 n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
443
444                                 if (i > MSG_IN_QUEUE_SIZE - n)
445                                         i = MSG_IN_QUEUE_SIZE - n + 1;
446                                 i -= j;
447                         }
448
449                         if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
450
451                         {
452                                 dbug(0, dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
453                                                 msg->header.length, plci->msg_in_write_pos,
454                                                 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
455
456                                 return _QUEUE_FULL;
457                         }
458                         c = false;
459                         if ((((byte *) msg) < ((byte *)(plci->msg_in_queue)))
460                             || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
461                         {
462                                 if (plci->msg_in_write_pos != plci->msg_in_read_pos)
463                                         c = true;
464                         }
465                         if (msg->header.command == _DATA_B3_R)
466                         {
467                                 if (msg->header.length < 20)
468                                 {
469                                         dbug(1, dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
470                                         return _BAD_MSG;
471                                 }
472                                 ncci_ptr = &(a->ncci[ncci]);
473                                 n = ncci_ptr->data_pending;
474                                 l = ncci_ptr->data_ack_pending;
475                                 k = plci->msg_in_read_pos;
476                                 while (k != plci->msg_in_write_pos)
477                                 {
478                                         if (k == plci->msg_in_wrap_pos)
479                                                 k = 0;
480                                         if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
481                                             && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
482                                         {
483                                                 n++;
484                                                 if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
485                                                         l++;
486                                         }
487
488                                         k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
489                                               MSG_IN_OVERHEAD + 3) & 0xfffc;
490
491                                 }
492                                 if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
493                                 {
494                                         dbug(0, dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
495                                                         ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
496
497                                         return _QUEUE_FULL;
498                                 }
499                                 if (plci->req_in || plci->internal_command)
500                                 {
501                                         if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
502                                             && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
503                                         {
504                                                 dbug(0, dprintf("Q-FULL3(requeue)"));
505
506                                                 return _QUEUE_FULL;
507                                         }
508                                         c = true;
509                                 }
510                         }
511                         else
512                         {
513                                 if (plci->req_in || plci->internal_command)
514                                         c = true;
515                                 else
516                                 {
517                                         plci->command = msg->header.command;
518                                         plci->number = msg->header.number;
519                                 }
520                         }
521                         if (c)
522                         {
523                                 dbug(1, dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
524                                                 msg->header.command, plci->req_in, plci->internal_command,
525                                                 msg->header.length, plci->msg_in_write_pos,
526                                                 plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
527                                 if (j == 0)
528                                         plci->msg_in_wrap_pos = plci->msg_in_write_pos;
529                                 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
530                                 for (i = 0; i < msg->header.length; i++)
531                                         ((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i];
532                                 if (m->header.command == _DATA_B3_R)
533                                 {
534
535                                         m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet(appl, m->info.data_b3_req.Data));
536
537                                 }
538
539                                 j = (j + 3) & 0xfffc;
540
541                                 *((APPL **)(&((byte *)(plci->msg_in_queue))[j])) = appl;
542                                 plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
543                                 return 0;
544                         }
545                 }
546                 else
547                 {
548                         plci = NULL;
549                 }
550         }
551         dbug(1, dprintf("com=%x", msg->header.command));
552
553         for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
554         for (i = 0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
555
556                 if (ftable[i].command == msg->header.command) {
557                         /* break loop if the message is correct, otherwise continue scan  */
558                         /* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */
559                         if (!api_parse(msg->info.b, (word)(msg->header.length - 12), ftable[i].format, msg_parms)) {
560                                 ret = 0;
561                                 break;
562                         }
563                         for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
564                 }
565         }
566         if (ret) {
567                 dbug(1, dprintf("BAD_MSG"));
568                 if (plci) plci->command = 0;
569                 return ret;
570         }
571
572
573         c = ftable[i].function(GET_DWORD(&msg->header.controller),
574                                msg->header.number,
575                                a,
576                                plci,
577                                appl,
578                                msg_parms);
579
580         channel_xmit_extended_xon(plci);
581
582         if (c == 1) send_req(plci);
583         if (c == 2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
584         if (plci && !plci->req_in) plci->command = 0;
585         return 0;
586 }
587
588
589 /*------------------------------------------------------------------*/
590 /* api_parse function, check the format of api messages             */
591 /*------------------------------------------------------------------*/
592
593 static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
594 {
595         word i;
596         word p;
597
598         for (i = 0, p = 0; format[i]; i++) {
599                 if (parms)
600                 {
601                         parms[i].info = &msg[p];
602                 }
603                 switch (format[i]) {
604                 case 'b':
605                         p += 1;
606                         break;
607                 case 'w':
608                         p += 2;
609                         break;
610                 case 'd':
611                         p += 4;
612                         break;
613                 case 's':
614                         if (msg[p] == 0xff) {
615                                 parms[i].info += 2;
616                                 parms[i].length = msg[p + 1] + (msg[p + 2] << 8);
617                                 p += (parms[i].length + 3);
618                         }
619                         else {
620                                 parms[i].length = msg[p];
621                                 p += (parms[i].length + 1);
622                         }
623                         break;
624                 }
625
626                 if (p > length) return true;
627         }
628         if (parms) parms[i].info = NULL;
629         return false;
630 }
631
632 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
633 {
634         word i, j, n = 0;
635         byte *p;
636
637         p = out->info;
638         for (i = 0; format[i] != '\0'; i++)
639         {
640                 out->parms[i].info = p;
641                 out->parms[i].length = in[i].length;
642                 switch (format[i])
643                 {
644                 case 'b':
645                         n = 1;
646                         break;
647                 case 'w':
648                         n = 2;
649                         break;
650                 case 'd':
651                         n = 4;
652                         break;
653                 case 's':
654                         n = in[i].length + 1;
655                         break;
656                 }
657                 for (j = 0; j < n; j++)
658                         *(p++) = in[i].info[j];
659         }
660         out->parms[i].info = NULL;
661         out->parms[i].length = 0;
662 }
663
664 static void api_load_msg(API_SAVE *in, API_PARSE *out)
665 {
666         word i;
667
668         i = 0;
669         do
670         {
671                 out[i].info = in->parms[i].info;
672                 out[i].length = in->parms[i].length;
673         } while (in->parms[i++].info);
674 }
675
676
677 /*------------------------------------------------------------------*/
678 /* CAPI remove function                                             */
679 /*------------------------------------------------------------------*/
680
681 word api_remove_start(void)
682 {
683         word i;
684         word j;
685
686         if (!remove_started) {
687                 remove_started = true;
688                 for (i = 0; i < max_adapter; i++) {
689                         if (adapter[i].request) {
690                                 for (j = 0; j < adapter[i].max_plci; j++) {
691                                         if (adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
692                                 }
693                         }
694                 }
695                 return 1;
696         }
697         else {
698                 for (i = 0; i < max_adapter; i++) {
699                         if (adapter[i].request) {
700                                 for (j = 0; j < adapter[i].max_plci; j++) {
701                                         if (adapter[i].plci[j].Sig.Id) return 1;
702                                 }
703                         }
704                 }
705         }
706         api_remove_complete();
707         return 0;
708 }
709
710
711 /*------------------------------------------------------------------*/
712 /* internal command queue                                           */
713 /*------------------------------------------------------------------*/
714
715 static void init_internal_command_queue(PLCI *plci)
716 {
717         word i;
718
719         dbug(1, dprintf("%s,%d: init_internal_command_queue",
720                         (char *)(FILE_), __LINE__));
721
722         plci->internal_command = 0;
723         for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
724                 plci->internal_command_queue[i] = NULL;
725 }
726
727
728 static void start_internal_command(dword Id, PLCI *plci, t_std_internal_command command_function)
729 {
730         word i;
731
732         dbug(1, dprintf("[%06lx] %s,%d: start_internal_command",
733                         UnMapId(Id), (char *)(FILE_), __LINE__));
734
735         if (plci->internal_command == 0)
736         {
737                 plci->internal_command_queue[0] = command_function;
738                 (*command_function)(Id, plci, OK);
739         }
740         else
741         {
742                 i = 1;
743                 while (plci->internal_command_queue[i] != NULL)
744                         i++;
745                 plci->internal_command_queue[i] = command_function;
746         }
747 }
748
749
750 static void next_internal_command(dword Id, PLCI *plci)
751 {
752         word i;
753
754         dbug(1, dprintf("[%06lx] %s,%d: next_internal_command",
755                         UnMapId(Id), (char *)(FILE_), __LINE__));
756
757         plci->internal_command = 0;
758         plci->internal_command_queue[0] = NULL;
759         while (plci->internal_command_queue[1] != NULL)
760         {
761                 for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
762                         plci->internal_command_queue[i] = plci->internal_command_queue[i + 1];
763                 plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
764                 (*(plci->internal_command_queue[0]))(Id, plci, OK);
765                 if (plci->internal_command != 0)
766                         return;
767                 plci->internal_command_queue[0] = NULL;
768         }
769 }
770
771
772 /*------------------------------------------------------------------*/
773 /* NCCI allocate/remove function                                    */
774 /*------------------------------------------------------------------*/
775
776 static dword ncci_mapping_bug = 0;
777
778 static word get_ncci(PLCI *plci, byte ch, word force_ncci)
779 {
780         DIVA_CAPI_ADAPTER *a;
781         word ncci, i, j, k;
782
783         a = plci->adapter;
784         if (!ch || a->ch_ncci[ch])
785         {
786                 ncci_mapping_bug++;
787                 dbug(1, dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
788                                 ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
789                 ncci = ch;
790         }
791         else
792         {
793                 if (force_ncci)
794                         ncci = force_ncci;
795                 else
796                 {
797                         if ((ch < MAX_NCCI + 1) && !a->ncci_ch[ch])
798                                 ncci = ch;
799                         else
800                         {
801                                 ncci = 1;
802                                 while ((ncci < MAX_NCCI + 1) && a->ncci_ch[ncci])
803                                         ncci++;
804                                 if (ncci == MAX_NCCI + 1)
805                                 {
806                                         ncci_mapping_bug++;
807                                         i = 1;
808                                         do
809                                         {
810                                                 j = 1;
811                                                 while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i))
812                                                         j++;
813                                                 k = j;
814                                                 if (j < MAX_NCCI + 1)
815                                                 {
816                                                         do
817                                                         {
818                                                                 j++;
819                                                         } while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i));
820                                                 }
821                                         } while ((i < MAX_NL_CHANNEL + 1) && (j < MAX_NCCI + 1));
822                                         if (i < MAX_NL_CHANNEL + 1)
823                                         {
824                                                 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
825                                                                 ncci_mapping_bug, ch, force_ncci, i, k, j));
826                                         }
827                                         else
828                                         {
829                                                 dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x",
830                                                                 ncci_mapping_bug, ch, force_ncci));
831                                         }
832                                         ncci = ch;
833                                 }
834                         }
835                         a->ncci_plci[ncci] = plci->Id;
836                         a->ncci_state[ncci] = IDLE;
837                         if (!plci->ncci_ring_list)
838                                 plci->ncci_ring_list = ncci;
839                         else
840                                 a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
841                         a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
842                 }
843                 a->ncci_ch[ncci] = ch;
844                 a->ch_ncci[ch] = (byte) ncci;
845                 dbug(1, dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
846                                 ncci_mapping_bug, ch, force_ncci, ch, ncci));
847         }
848         return (ncci);
849 }
850
851
852 static void ncci_free_receive_buffers(PLCI *plci, word ncci)
853 {
854         DIVA_CAPI_ADAPTER *a;
855         APPL *appl;
856         word i, ncci_code;
857         dword Id;
858
859         a = plci->adapter;
860         Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
861         if (ncci)
862         {
863                 if (a->ncci_plci[ncci] == plci->Id)
864                 {
865                         if (!plci->appl)
866                         {
867                                 ncci_mapping_bug++;
868                                 dbug(1, dprintf("NCCI mapping appl expected %ld %08lx",
869                                                 ncci_mapping_bug, Id));
870                         }
871                         else
872                         {
873                                 appl = plci->appl;
874                                 ncci_code = ncci | (((word) a->Id) << 8);
875                                 for (i = 0; i < appl->MaxBuffer; i++)
876                                 {
877                                         if ((appl->DataNCCI[i] == ncci_code)
878                                             && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
879                                         {
880                                                 appl->DataNCCI[i] = 0;
881                                         }
882                                 }
883                         }
884                 }
885         }
886         else
887         {
888                 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
889                 {
890                         if (a->ncci_plci[ncci] == plci->Id)
891                         {
892                                 if (!plci->appl)
893                                 {
894                                         ncci_mapping_bug++;
895                                         dbug(1, dprintf("NCCI mapping no appl %ld %08lx",
896                                                         ncci_mapping_bug, Id));
897                                 }
898                                 else
899                                 {
900                                         appl = plci->appl;
901                                         ncci_code = ncci | (((word) a->Id) << 8);
902                                         for (i = 0; i < appl->MaxBuffer; i++)
903                                         {
904                                                 if ((appl->DataNCCI[i] == ncci_code)
905                                                     && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
906                                                 {
907                                                         appl->DataNCCI[i] = 0;
908                                                 }
909                                         }
910                                 }
911                         }
912                 }
913         }
914 }
915
916
917 static void cleanup_ncci_data(PLCI *plci, word ncci)
918 {
919         NCCI *ncci_ptr;
920
921         if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
922         {
923                 ncci_ptr = &(plci->adapter->ncci[ncci]);
924                 if (plci->appl)
925                 {
926                         while (ncci_ptr->data_pending != 0)
927                         {
928                                 if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
929                                         TransmitBufferFree(plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
930                                 (ncci_ptr->data_out)++;
931                                 if (ncci_ptr->data_out == MAX_DATA_B3)
932                                         ncci_ptr->data_out = 0;
933                                 (ncci_ptr->data_pending)--;
934                         }
935                 }
936                 ncci_ptr->data_out = 0;
937                 ncci_ptr->data_pending = 0;
938                 ncci_ptr->data_ack_out = 0;
939                 ncci_ptr->data_ack_pending = 0;
940         }
941 }
942
943
944 static void ncci_remove(PLCI *plci, word ncci, byte preserve_ncci)
945 {
946         DIVA_CAPI_ADAPTER *a;
947         dword Id;
948         word i;
949
950         a = plci->adapter;
951         Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
952         if (!preserve_ncci)
953                 ncci_free_receive_buffers(plci, ncci);
954         if (ncci)
955         {
956                 if (a->ncci_plci[ncci] != plci->Id)
957                 {
958                         ncci_mapping_bug++;
959                         dbug(1, dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
960                                         ncci_mapping_bug, Id, preserve_ncci));
961                 }
962                 else
963                 {
964                         cleanup_ncci_data(plci, ncci);
965                         dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
966                                         ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
967                         a->ch_ncci[a->ncci_ch[ncci]] = 0;
968                         if (!preserve_ncci)
969                         {
970                                 a->ncci_ch[ncci] = 0;
971                                 a->ncci_plci[ncci] = 0;
972                                 a->ncci_state[ncci] = IDLE;
973                                 i = plci->ncci_ring_list;
974                                 while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
975                                         i = a->ncci_next[i];
976                                 if ((i != 0) && (a->ncci_next[i] == ncci))
977                                 {
978                                         if (i == ncci)
979                                                 plci->ncci_ring_list = 0;
980                                         else if (plci->ncci_ring_list == ncci)
981                                                 plci->ncci_ring_list = i;
982                                         a->ncci_next[i] = a->ncci_next[ncci];
983                                 }
984                                 a->ncci_next[ncci] = 0;
985                         }
986                 }
987         }
988         else
989         {
990                 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
991                 {
992                         if (a->ncci_plci[ncci] == plci->Id)
993                         {
994                                 cleanup_ncci_data(plci, ncci);
995                                 dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
996                                                 ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
997                                 a->ch_ncci[a->ncci_ch[ncci]] = 0;
998                                 if (!preserve_ncci)
999                                 {
1000                                         a->ncci_ch[ncci] = 0;
1001                                         a->ncci_plci[ncci] = 0;
1002                                         a->ncci_state[ncci] = IDLE;
1003                                         a->ncci_next[ncci] = 0;
1004                                 }
1005                         }
1006                 }
1007                 if (!preserve_ncci)
1008                         plci->ncci_ring_list = 0;
1009         }
1010 }
1011
1012
1013 /*------------------------------------------------------------------*/
1014 /* PLCI remove function                                             */
1015 /*------------------------------------------------------------------*/
1016
1017 static void plci_free_msg_in_queue(PLCI *plci)
1018 {
1019         word i;
1020
1021         if (plci->appl)
1022         {
1023                 i = plci->msg_in_read_pos;
1024                 while (i != plci->msg_in_write_pos)
1025                 {
1026                         if (i == plci->msg_in_wrap_pos)
1027                                 i = 0;
1028                         if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1029                         {
1030
1031                                 TransmitBufferFree(plci->appl,
1032                                                    (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1033
1034                         }
1035
1036                         i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1037                               MSG_IN_OVERHEAD + 3) & 0xfffc;
1038
1039                 }
1040         }
1041         plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1042         plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1043         plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1044 }
1045
1046
1047 static void plci_remove(PLCI *plci)
1048 {
1049
1050         if (!plci) {
1051                 dbug(1, dprintf("plci_remove(no plci)"));
1052                 return;
1053         }
1054         init_internal_command_queue(plci);
1055         dbug(1, dprintf("plci_remove(%x,tel=%x)", plci->Id, plci->tel));
1056         if (plci_remove_check(plci))
1057         {
1058                 return;
1059         }
1060         if (plci->Sig.Id == 0xff)
1061         {
1062                 dbug(1, dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1063                 if (plci->NL.Id && !plci->nl_remove_id)
1064                 {
1065                         nl_req_ncci(plci, REMOVE, 0);
1066                         send_req(plci);
1067                 }
1068         }
1069         else
1070         {
1071                 if (!plci->sig_remove_id
1072                     && (plci->Sig.Id
1073                         || (plci->req_in != plci->req_out)
1074                         || (plci->nl_req || plci->sig_req)))
1075                 {
1076                         sig_req(plci, HANGUP, 0);
1077                         send_req(plci);
1078                 }
1079         }
1080         ncci_remove(plci, 0, false);
1081         plci_free_msg_in_queue(plci);
1082
1083         plci->channels = 0;
1084         plci->appl = NULL;
1085         if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1086                 plci->State = OUTG_DIS_PENDING;
1087 }
1088
1089 /*------------------------------------------------------------------*/
1090 /* Application Group function helpers                               */
1091 /*------------------------------------------------------------------*/
1092
1093 static void set_group_ind_mask(PLCI *plci)
1094 {
1095         word i;
1096
1097         for (i = 0; i < C_IND_MASK_DWORDS; i++)
1098                 plci->group_optimization_mask_table[i] = 0xffffffffL;
1099 }
1100
1101 static void clear_group_ind_mask_bit(PLCI *plci, word b)
1102 {
1103         plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1104 }
1105
1106 static byte test_group_ind_mask_bit(PLCI *plci, word b)
1107 {
1108         return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1109 }
1110
1111 /*------------------------------------------------------------------*/
1112 /* c_ind_mask operations for arbitrary MAX_APPL                     */
1113 /*------------------------------------------------------------------*/
1114
1115 static void clear_c_ind_mask(PLCI *plci)
1116 {
1117         word i;
1118
1119         for (i = 0; i < C_IND_MASK_DWORDS; i++)
1120                 plci->c_ind_mask_table[i] = 0;
1121 }
1122
1123 static byte c_ind_mask_empty(PLCI *plci)
1124 {
1125         word i;
1126
1127         i = 0;
1128         while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1129                 i++;
1130         return (i == C_IND_MASK_DWORDS);
1131 }
1132
1133 static void set_c_ind_mask_bit(PLCI *plci, word b)
1134 {
1135         plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1136 }
1137
1138 static void clear_c_ind_mask_bit(PLCI *plci, word b)
1139 {
1140         plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1141 }
1142
1143 static byte test_c_ind_mask_bit(PLCI *plci, word b)
1144 {
1145         return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1146 }
1147
1148 static void dump_c_ind_mask(PLCI *plci)
1149 {
1150         word i, j, k;
1151         dword d;
1152         char *p;
1153         char buf[40];
1154
1155         for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1156         {
1157                 p = buf + 36;
1158                 *p = '\0';
1159                 for (j = 0; j < 4; j++)
1160                 {
1161                         if (i + j < C_IND_MASK_DWORDS)
1162                         {
1163                                 d = plci->c_ind_mask_table[i + j];
1164                                 for (k = 0; k < 8; k++)
1165                                 {
1166                                         *(--p) = hex_asc_lo(d);
1167                                         d >>= 4;
1168                                 }
1169                         }
1170                         else if (i != 0)
1171                         {
1172                                 for (k = 0; k < 8; k++)
1173                                         *(--p) = ' ';
1174                         }
1175                         *(--p) = ' ';
1176                 }
1177                 dbug(1, dprintf("c_ind_mask =%s", (char *) p));
1178         }
1179 }
1180
1181
1182
1183
1184
1185 #define dump_plcis(a)
1186
1187
1188
1189 /*------------------------------------------------------------------*/
1190 /* translation function for each message                            */
1191 /*------------------------------------------------------------------*/
1192
1193 static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1194                         PLCI *plci, APPL *appl, API_PARSE *parms)
1195 {
1196         word ch;
1197         word i;
1198         word Info;
1199         byte LinkLayer;
1200         API_PARSE *ai;
1201         API_PARSE *bp;
1202         API_PARSE ai_parms[5];
1203         word channel = 0;
1204         dword ch_mask;
1205         byte m;
1206         static byte esc_chi[35] = {0x02, 0x18, 0x01};
1207         static byte lli[2] = {0x01, 0x00};
1208         byte noCh = 0;
1209         word dir = 0;
1210         byte *p_chi = "";
1211
1212         for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1213
1214         dbug(1, dprintf("connect_req(%d)", parms->length));
1215         Info = _WRONG_IDENTIFIER;
1216         if (a)
1217         {
1218                 if (a->adapter_disabled)
1219                 {
1220                         dbug(1, dprintf("adapter disabled"));
1221                         Id = ((word)1 << 8) | a->Id;
1222                         sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
1223                         sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1224                         return false;
1225                 }
1226                 Info = _OUT_OF_PLCI;
1227                 if ((i = get_plci(a)))
1228                 {
1229                         Info = 0;
1230                         plci = &a->plci[i - 1];
1231                         plci->appl = appl;
1232                         plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1233                         /* check 'external controller' bit for codec support */
1234                         if (Id & EXT_CONTROLLER)
1235                         {
1236                                 if (AdvCodecSupport(a, plci, appl, 0))
1237                                 {
1238                                         plci->Id = 0;
1239                                         sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1240                                         return 2;
1241                                 }
1242                         }
1243                         ai = &parms[9];
1244                         bp = &parms[5];
1245                         ch = 0;
1246                         if (bp->length)LinkLayer = bp->info[3];
1247                         else LinkLayer = 0;
1248                         if (ai->length)
1249                         {
1250                                 ch = 0xffff;
1251                                 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1252                                 {
1253                                         ch = 0;
1254                                         if (ai_parms[0].length)
1255                                         {
1256                                                 ch = GET_WORD(ai_parms[0].info + 1);
1257                                                 if (ch > 4) ch = 0; /* safety -> ignore ChannelID */
1258                                                 if (ch == 4) /* explizit CHI in message */
1259                                                 {
1260                                                         /* check length of B-CH struct */
1261                                                         if ((ai_parms[0].info)[3] >= 1)
1262                                                         {
1263                                                                 if ((ai_parms[0].info)[4] == CHI)
1264                                                                 {
1265                                                                         p_chi = &((ai_parms[0].info)[5]);
1266                                                                 }
1267                                                                 else
1268                                                                 {
1269                                                                         p_chi = &((ai_parms[0].info)[3]);
1270                                                                 }
1271                                                                 if (p_chi[0] > 35) /* check length of channel ID */
1272                                                                 {
1273                                                                         Info = _WRONG_MESSAGE_FORMAT;
1274                                                                 }
1275                                                         }
1276                                                         else Info = _WRONG_MESSAGE_FORMAT;
1277                                                 }
1278
1279                                                 if (ch == 3 && ai_parms[0].length >= 7 && ai_parms[0].length <= 36)
1280                                                 {
1281                                                         dir = GET_WORD(ai_parms[0].info + 3);
1282                                                         ch_mask = 0;
1283                                                         m = 0x3f;
1284                                                         for (i = 0; i + 5 <= ai_parms[0].length; i++)
1285                                                         {
1286                                                                 if (ai_parms[0].info[i + 5] != 0)
1287                                                                 {
1288                                                                         if ((ai_parms[0].info[i + 5] | m) != 0xff)
1289                                                                                 Info = _WRONG_MESSAGE_FORMAT;
1290                                                                         else
1291                                                                         {
1292                                                                                 if (ch_mask == 0)
1293                                                                                         channel = i;
1294                                                                                 ch_mask |= 1L << i;
1295                                                                         }
1296                                                                 }
1297                                                                 m = 0;
1298                                                         }
1299                                                         if (ch_mask == 0)
1300                                                                 Info = _WRONG_MESSAGE_FORMAT;
1301                                                         if (!Info)
1302                                                         {
1303                                                                 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1304                                                                 {
1305                                                                         esc_chi[0] = (byte)(ai_parms[0].length - 2);
1306                                                                         for (i = 0; i + 5 <= ai_parms[0].length; i++)
1307                                                                                 esc_chi[i + 3] = ai_parms[0].info[i + 5];
1308                                                                 }
1309                                                                 else
1310                                                                         esc_chi[0] = 2;
1311                                                                 esc_chi[2] = (byte)channel;
1312                                                                 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1313                                                                 add_p(plci, LLI, lli);
1314                                                                 add_p(plci, ESC, esc_chi);
1315                                                                 plci->State = LOCAL_CONNECT;
1316                                                                 if (!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
1317                                                         }
1318                                                 }
1319                                         }
1320                                 }
1321                                 else  Info = _WRONG_MESSAGE_FORMAT;
1322                         }
1323
1324                         dbug(1, dprintf("ch=%x,dir=%x,p_ch=%d", ch, dir, channel));
1325                         plci->command = _CONNECT_R;
1326                         plci->number = Number;
1327                         /* x.31 or D-ch free SAPI in LinkLayer? */
1328                         if (ch == 1 && LinkLayer != 3 && LinkLayer != 12) noCh = true;
1329                         if ((ch == 0 || ch == 2 || noCh || ch == 3 || ch == 4) && !Info)
1330                         {
1331                                 /* B-channel used for B3 connections (ch==0), or no B channel    */
1332                                 /* is used (ch==2) or perm. connection (3) is used  do a CALL    */
1333                                 if (noCh) Info = add_b1(plci, &parms[5], 2, 0);    /* no resource    */
1334                                 else     Info = add_b1(plci, &parms[5], ch, 0);
1335                                 add_s(plci, OAD, &parms[2]);
1336                                 add_s(plci, OSA, &parms[4]);
1337                                 add_s(plci, BC, &parms[6]);
1338                                 add_s(plci, LLC, &parms[7]);
1339                                 add_s(plci, HLC, &parms[8]);
1340                                 if (a->Info_Mask[appl->Id - 1] & 0x200)
1341                                 {
1342                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
1343                                         add_p(plci, LLI, "\x01\x01");
1344                                 }
1345                                 if (GET_WORD(parms[0].info) < 29) {
1346                                         add_p(plci, BC, cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1347                                         add_p(plci, HLC, cip_hlc[GET_WORD(parms[0].info)]);
1348                                 }
1349                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1350                                 sig_req(plci, ASSIGN, DSIG_ID);
1351                         }
1352                         else if (ch == 1) {
1353
1354                                 /* D-Channel used for B3 connections */
1355                                 plci->Sig.Id = 0xff;
1356                                 Info = 0;
1357                         }
1358
1359                         if (!Info && ch != 2 && !noCh) {
1360                                 Info = add_b23(plci, &parms[5]);
1361                                 if (!Info) {
1362                                         if (!(plci->tel && !plci->adv_nl))nl_req_ncci(plci, ASSIGN, 0);
1363                                 }
1364                         }
1365
1366                         if (!Info)
1367                         {
1368                                 if (ch == 0 || ch == 2 || ch == 3 || noCh || ch == 4)
1369                                 {
1370                                         if (plci->spoofed_msg == SPOOFING_REQUIRED)
1371                                         {
1372                                                 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1373                                                 plci->spoofed_msg = CALL_REQ;
1374                                                 plci->internal_command = BLOCK_PLCI;
1375                                                 plci->command = 0;
1376                                                 dbug(1, dprintf("Spoof"));
1377                                                 send_req(plci);
1378                                                 return false;
1379                                         }
1380                                         if (ch == 4)add_p(plci, CHI, p_chi);
1381                                         add_s(plci, CPN, &parms[1]);
1382                                         add_s(plci, DSA, &parms[3]);
1383                                         if (noCh) add_p(plci, ESC, "\x02\x18\xfd");  /* D-channel, no B-L3 */
1384                                         add_ai(plci, &parms[9]);
1385                                         if (!dir)sig_req(plci, CALL_REQ, 0);
1386                                         else
1387                                         {
1388                                                 plci->command = PERM_LIST_REQ;
1389                                                 plci->appl = appl;
1390                                                 sig_req(plci, LISTEN_REQ, 0);
1391                                                 send_req(plci);
1392                                                 return false;
1393                                         }
1394                                 }
1395                                 send_req(plci);
1396                                 return false;
1397                         }
1398                         plci->Id = 0;
1399                 }
1400         }
1401         sendf(appl,
1402               _CONNECT_R | CONFIRM,
1403               Id,
1404               Number,
1405               "w", Info);
1406         return 2;
1407 }
1408
1409 static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1410                         PLCI *plci, APPL *appl, API_PARSE *parms)
1411 {
1412         word i, Info;
1413         word Reject;
1414         static byte cau_t[] = {0, 0, 0x90, 0x91, 0xac, 0x9d, 0x86, 0xd8, 0x9b};
1415         static byte esc_t[] = {0x03, 0x08, 0x00, 0x00};
1416         API_PARSE *ai;
1417         API_PARSE ai_parms[5];
1418         word ch = 0;
1419
1420         if (!plci) {
1421                 dbug(1, dprintf("connect_res(no plci)"));
1422                 return 0;  /* no plci, no send */
1423         }
1424
1425         dbug(1, dprintf("connect_res(State=0x%x)", plci->State));
1426         for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1427         ai = &parms[5];
1428         dbug(1, dprintf("ai->length=%d", ai->length));
1429
1430         if (ai->length)
1431         {
1432                 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1433                 {
1434                         dbug(1, dprintf("ai_parms[0].length=%d/0x%x", ai_parms[0].length, GET_WORD(ai_parms[0].info + 1)));
1435                         ch = 0;
1436                         if (ai_parms[0].length)
1437                         {
1438                                 ch = GET_WORD(ai_parms[0].info + 1);
1439                                 dbug(1, dprintf("BCH-I=0x%x", ch));
1440                         }
1441                 }
1442         }
1443
1444         if (plci->State == INC_CON_CONNECTED_ALERT)
1445         {
1446                 dbug(1, dprintf("Connected Alert Call_Res"));
1447                 if (a->Info_Mask[appl->Id - 1] & 0x200)
1448                 {
1449                         /* early B3 connect (CIP mask bit 9) no release after a disc */
1450                         add_p(plci, LLI, "\x01\x01");
1451                 }
1452                 add_s(plci, CONN_NR, &parms[2]);
1453                 add_s(plci, LLC, &parms[4]);
1454                 add_ai(plci, &parms[5]);
1455                 plci->State = INC_CON_ACCEPT;
1456                 sig_req(plci, CALL_RES, 0);
1457                 return 1;
1458         }
1459         else if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT) {
1460                 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1461                 dump_c_ind_mask(plci);
1462                 Reject = GET_WORD(parms[0].info);
1463                 dbug(1, dprintf("Reject=0x%x", Reject));
1464                 if (Reject)
1465                 {
1466                         if (c_ind_mask_empty(plci))
1467                         {
1468                                 if ((Reject & 0xff00) == 0x3400)
1469                                 {
1470                                         esc_t[2] = ((byte)(Reject & 0x00ff)) | 0x80;
1471                                         add_p(plci, ESC, esc_t);
1472                                         add_ai(plci, &parms[5]);
1473                                         sig_req(plci, REJECT, 0);
1474                                 }
1475                                 else if (Reject == 1 || Reject >= 9)
1476                                 {
1477                                         add_ai(plci, &parms[5]);
1478                                         sig_req(plci, HANGUP, 0);
1479                                 }
1480                                 else
1481                                 {
1482                                         esc_t[2] = cau_t[(Reject&0x000f)];
1483                                         add_p(plci, ESC, esc_t);
1484                                         add_ai(plci, &parms[5]);
1485                                         sig_req(plci, REJECT, 0);
1486                                 }
1487                                 plci->appl = appl;
1488                         }
1489                         else
1490                         {
1491                                 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1492                         }
1493                 }
1494                 else {
1495                         plci->appl = appl;
1496                         if (Id & EXT_CONTROLLER) {
1497                                 if (AdvCodecSupport(a, plci, appl, 0)) {
1498                                         dbug(1, dprintf("connect_res(error from AdvCodecSupport)"));
1499                                         sig_req(plci, HANGUP, 0);
1500                                         return 1;
1501                                 }
1502                                 if (plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1503                                 {
1504                                         Info = add_b23(plci, &parms[1]);
1505                                         if (Info)
1506                                         {
1507                                                 dbug(1, dprintf("connect_res(error from add_b23)"));
1508                                                 sig_req(plci, HANGUP, 0);
1509                                                 return 1;
1510                                         }
1511                                         if (plci->adv_nl)
1512                                         {
1513                                                 nl_req_ncci(plci, ASSIGN, 0);
1514                                         }
1515                                 }
1516                         }
1517                         else
1518                         {
1519                                 plci->tel = 0;
1520                                 if (ch != 2)
1521                                 {
1522                                         Info = add_b23(plci, &parms[1]);
1523                                         if (Info)
1524                                         {
1525                                                 dbug(1, dprintf("connect_res(error from add_b23 2)"));
1526                                                 sig_req(plci, HANGUP, 0);
1527                                                 return 1;
1528                                         }
1529                                 }
1530                                 nl_req_ncci(plci, ASSIGN, 0);
1531                         }
1532
1533                         if (plci->spoofed_msg == SPOOFING_REQUIRED)
1534                         {
1535                                 api_save_msg(parms, "wsssss", &plci->saved_msg);
1536                                 plci->spoofed_msg = CALL_RES;
1537                                 plci->internal_command = BLOCK_PLCI;
1538                                 plci->command = 0;
1539                                 dbug(1, dprintf("Spoof"));
1540                         }
1541                         else
1542                         {
1543                                 add_b1(plci, &parms[1], ch, plci->B1_facilities);
1544                                 if (a->Info_Mask[appl->Id - 1] & 0x200)
1545                                 {
1546                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
1547                                         add_p(plci, LLI, "\x01\x01");
1548                                 }
1549                                 add_s(plci, CONN_NR, &parms[2]);
1550                                 add_s(plci, LLC, &parms[4]);
1551                                 add_ai(plci, &parms[5]);
1552                                 plci->State = INC_CON_ACCEPT;
1553                                 sig_req(plci, CALL_RES, 0);
1554                         }
1555
1556                         for (i = 0; i < max_appl; i++) {
1557                                 if (test_c_ind_mask_bit(plci, i)) {
1558                                         sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1559                                 }
1560                         }
1561                 }
1562         }
1563         return 1;
1564 }
1565
1566 static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1567                           PLCI *plci, APPL *appl, API_PARSE *msg)
1568 {
1569         dbug(1, dprintf("connect_a_res"));
1570         return false;
1571 }
1572
1573 static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1574                            PLCI *plci, APPL *appl, API_PARSE *msg)
1575 {
1576         word Info;
1577         word i;
1578
1579         dbug(1, dprintf("disconnect_req"));
1580
1581         Info = _WRONG_IDENTIFIER;
1582
1583         if (plci)
1584         {
1585                 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
1586                 {
1587                         clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1588                         plci->appl = appl;
1589                         for (i = 0; i < max_appl; i++)
1590                         {
1591                                 if (test_c_ind_mask_bit(plci, i))
1592                                         sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1593                         }
1594                         plci->State = OUTG_DIS_PENDING;
1595                 }
1596                 if (plci->Sig.Id && plci->appl)
1597                 {
1598                         Info = 0;
1599                         if (plci->Sig.Id != 0xff)
1600                         {
1601                                 if (plci->State != INC_DIS_PENDING)
1602                                 {
1603                                         add_ai(plci, &msg[0]);
1604                                         sig_req(plci, HANGUP, 0);
1605                                         plci->State = OUTG_DIS_PENDING;
1606                                         return 1;
1607                                 }
1608                         }
1609                         else
1610                         {
1611                                 if (plci->NL.Id && !plci->nl_remove_id)
1612                                 {
1613                                         mixer_remove(plci);
1614                                         nl_req_ncci(plci, REMOVE, 0);
1615                                         sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
1616                                         sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1617                                         plci->State = INC_DIS_PENDING;
1618                                 }
1619                                 return 1;
1620                         }
1621                 }
1622         }
1623
1624         if (!appl)  return false;
1625         sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", Info);
1626         return false;
1627 }
1628
1629 static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1630                            PLCI *plci, APPL *appl, API_PARSE *msg)
1631 {
1632         dbug(1, dprintf("disconnect_res"));
1633         if (plci)
1634         {
1635                 /* clear ind mask bit, just in case of collsion of          */
1636                 /* DISCONNECT_IND and CONNECT_RES                           */
1637                 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1638                 ncci_free_receive_buffers(plci, 0);
1639                 if (plci_remove_check(plci))
1640                 {
1641                         return 0;
1642                 }
1643                 if (plci->State == INC_DIS_PENDING
1644                     || plci->State == SUSPENDING) {
1645                         if (c_ind_mask_empty(plci)) {
1646                                 if (plci->State != SUSPENDING) plci->State = IDLE;
1647                                 dbug(1, dprintf("chs=%d", plci->channels));
1648                                 if (!plci->channels) {
1649                                         plci_remove(plci);
1650                                 }
1651                         }
1652                 }
1653         }
1654         return 0;
1655 }
1656
1657 static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1658                        PLCI *plci, APPL *appl, API_PARSE *parms)
1659 {
1660         word Info;
1661         byte i;
1662
1663         dbug(1, dprintf("listen_req(Appl=0x%x)", appl->Id));
1664
1665         Info = _WRONG_IDENTIFIER;
1666         if (a) {
1667                 Info = 0;
1668                 a->Info_Mask[appl->Id - 1] = GET_DWORD(parms[0].info);
1669                 a->CIP_Mask[appl->Id - 1] = GET_DWORD(parms[1].info);
1670                 dbug(1, dprintf("CIP_MASK=0x%lx", GET_DWORD(parms[1].info)));
1671                 if (a->Info_Mask[appl->Id - 1] & 0x200) { /* early B3 connect provides */
1672                         a->Info_Mask[appl->Id - 1] |=  0x10;   /* call progression infos    */
1673                 }
1674
1675                 /* check if external controller listen and switch listen on or off*/
1676                 if (Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)) {
1677                         if (a->profile.Global_Options & ON_BOARD_CODEC) {
1678                                 dummy_plci.State = IDLE;
1679                                 a->codec_listen[appl->Id - 1] = &dummy_plci;
1680                                 a->TelOAD[0] = (byte)(parms[3].length);
1681                                 for (i = 1; parms[3].length >= i && i < 22; i++) {
1682                                         a->TelOAD[i] = parms[3].info[i];
1683                                 }
1684                                 a->TelOAD[i] = 0;
1685                                 a->TelOSA[0] = (byte)(parms[4].length);
1686                                 for (i = 1; parms[4].length >= i && i < 22; i++) {
1687                                         a->TelOSA[i] = parms[4].info[i];
1688                                 }
1689                                 a->TelOSA[i] = 0;
1690                         }
1691                         else Info = 0x2002; /* wrong controller, codec not supported */
1692                 }
1693                 else{               /* clear listen */
1694                         a->codec_listen[appl->Id - 1] = (PLCI *)0;
1695                 }
1696         }
1697         sendf(appl,
1698               _LISTEN_R | CONFIRM,
1699               Id,
1700               Number,
1701               "w", Info);
1702
1703         if (a) listen_check(a);
1704         return false;
1705 }
1706
1707 static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1708                      PLCI *plci, APPL *appl, API_PARSE *msg)
1709 {
1710         word i;
1711         API_PARSE *ai;
1712         PLCI *rc_plci = NULL;
1713         API_PARSE ai_parms[5];
1714         word Info = 0;
1715
1716         dbug(1, dprintf("info_req"));
1717         for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1718
1719         ai = &msg[1];
1720
1721         if (ai->length)
1722         {
1723                 if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1724                 {
1725                         dbug(1, dprintf("AddInfo wrong"));
1726                         Info = _WRONG_MESSAGE_FORMAT;
1727                 }
1728         }
1729         if (!a) Info = _WRONG_STATE;
1730
1731         if (!Info && plci)
1732         {                /* no fac, with CPN, or KEY */
1733                 rc_plci = plci;
1734                 if (!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length))
1735                 {
1736                         /* overlap sending option */
1737                         dbug(1, dprintf("OvlSnd"));
1738                         add_s(plci, CPN, &msg[0]);
1739                         add_s(plci, KEY, &ai_parms[1]);
1740                         sig_req(plci, INFO_REQ, 0);
1741                         send_req(plci);
1742                         return false;
1743                 }
1744
1745                 if (plci->State && ai_parms[2].length)
1746                 {
1747                         /* User_Info option */
1748                         dbug(1, dprintf("UUI"));
1749                         add_s(plci, UUI, &ai_parms[2]);
1750                         sig_req(plci, USER_DATA, 0);
1751                 }
1752                 else if (plci->State && ai_parms[3].length)
1753                 {
1754                         /* Facility option */
1755                         dbug(1, dprintf("FAC"));
1756                         add_s(plci, CPN, &msg[0]);
1757                         add_ai(plci, &msg[1]);
1758                         sig_req(plci, FACILITY_REQ, 0);
1759                 }
1760                 else
1761                 {
1762                         Info = _WRONG_STATE;
1763                 }
1764         }
1765         else if ((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1766         {
1767                 /* NCR_Facility option -> send UUI and Keypad too */
1768                 dbug(1, dprintf("NCR_FAC"));
1769                 if ((i = get_plci(a)))
1770                 {
1771                         rc_plci = &a->plci[i - 1];
1772                         appl->NullCREnable = true;
1773                         rc_plci->internal_command = C_NCR_FAC_REQ;
1774                         rc_plci->appl = appl;
1775                         add_p(rc_plci, CAI, "\x01\x80");
1776                         add_p(rc_plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1777                         sig_req(rc_plci, ASSIGN, DSIG_ID);
1778                         send_req(rc_plci);
1779                 }
1780                 else
1781                 {
1782                         Info = _OUT_OF_PLCI;
1783                 }
1784
1785                 if (!Info)
1786                 {
1787                         add_s(rc_plci, CPN, &msg[0]);
1788                         add_ai(rc_plci, &msg[1]);
1789                         sig_req(rc_plci, NCR_FACILITY, 0);
1790                         send_req(rc_plci);
1791                         return false;
1792                         /* for application controlled supplementary services    */
1793                 }
1794         }
1795
1796         if (!rc_plci)
1797         {
1798                 Info = _WRONG_MESSAGE_FORMAT;
1799         }
1800
1801         if (!Info)
1802         {
1803                 send_req(rc_plci);
1804         }
1805         else
1806         {  /* appl is not assigned to a PLCI or error condition */
1807                 dbug(1, dprintf("localInfoCon"));
1808                 sendf(appl,
1809                       _INFO_R | CONFIRM,
1810                       Id,
1811                       Number,
1812                       "w", Info);
1813         }
1814         return false;
1815 }
1816
1817 static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1818                      PLCI *plci, APPL *appl, API_PARSE *msg)
1819 {
1820         dbug(1, dprintf("info_res"));
1821         return false;
1822 }
1823
1824 static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1825                       PLCI *plci, APPL *appl, API_PARSE *msg)
1826 {
1827         word Info;
1828         byte ret;
1829
1830         dbug(1, dprintf("alert_req"));
1831
1832         Info = _WRONG_IDENTIFIER;
1833         ret = false;
1834         if (plci) {
1835                 Info = _ALERT_IGNORED;
1836                 if (plci->State != INC_CON_ALERT) {
1837                         Info = _WRONG_STATE;
1838                         if (plci->State == INC_CON_PENDING) {
1839                                 Info = 0;
1840                                 plci->State = INC_CON_ALERT;
1841                                 add_ai(plci, &msg[0]);
1842                                 sig_req(plci, CALL_ALERT, 0);
1843                                 ret = 1;
1844                         }
1845                 }
1846         }
1847         sendf(appl,
1848               _ALERT_R | CONFIRM,
1849               Id,
1850               Number,
1851               "w", Info);
1852         return ret;
1853 }
1854
1855 static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1856                          PLCI *plci, APPL *appl, API_PARSE *msg)
1857 {
1858         word Info = 0;
1859         word i    = 0;
1860
1861         word selector;
1862         word SSreq;
1863         long relatedPLCIvalue;
1864         DIVA_CAPI_ADAPTER *relatedadapter;
1865         byte *SSparms  = "";
1866         byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1867         byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1868         API_PARSE *parms;
1869         API_PARSE ss_parms[11];
1870         PLCI *rplci;
1871         byte cai[15];
1872         dword d;
1873         API_PARSE dummy;
1874
1875         dbug(1, dprintf("facility_req"));
1876         for (i = 0; i < 9; i++) ss_parms[i].length = 0;
1877
1878         parms = &msg[1];
1879
1880         if (!a)
1881         {
1882                 dbug(1, dprintf("wrong Ctrl"));
1883                 Info = _WRONG_IDENTIFIER;
1884         }
1885
1886         selector = GET_WORD(msg[0].info);
1887
1888         if (!Info)
1889         {
1890                 switch (selector)
1891                 {
1892                 case SELECTOR_HANDSET:
1893                         Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1894                         break;
1895
1896                 case SELECTOR_SU_SERV:
1897                         if (!msg[1].length)
1898                         {
1899                                 Info = _WRONG_MESSAGE_FORMAT;
1900                                 break;
1901                         }
1902                         SSreq = GET_WORD(&(msg[1].info[1]));
1903                         PUT_WORD(&RCparms[1], SSreq);
1904                         SSparms = RCparms;
1905                         switch (SSreq)
1906                         {
1907                         case S_GET_SUPPORTED_SERVICES:
1908                                 if ((i = get_plci(a)))
1909                                 {
1910                                         rplci = &a->plci[i - 1];
1911                                         rplci->appl = appl;
1912                                         add_p(rplci, CAI, "\x01\x80");
1913                                         add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1914                                         sig_req(rplci, ASSIGN, DSIG_ID);
1915                                         send_req(rplci);
1916                                 }
1917                                 else
1918                                 {
1919                                         PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1920                                         SSparms = (byte *)SSstruct;
1921                                         break;
1922                                 }
1923                                 rplci->internal_command = GETSERV_REQ_PEND;
1924                                 rplci->number = Number;
1925                                 rplci->appl = appl;
1926                                 sig_req(rplci, S_SUPPORTED, 0);
1927                                 send_req(rplci);
1928                                 return false;
1929                                 break;
1930
1931                         case S_LISTEN:
1932                                 if (parms->length == 7)
1933                                 {
1934                                         if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1935                                         {
1936                                                 dbug(1, dprintf("format wrong"));
1937                                                 Info = _WRONG_MESSAGE_FORMAT;
1938                                                 break;
1939                                         }
1940                                 }
1941                                 else
1942                                 {
1943                                         Info = _WRONG_MESSAGE_FORMAT;
1944                                         break;
1945                                 }
1946                                 a->Notification_Mask[appl->Id - 1] = GET_DWORD(ss_parms[2].info);
1947                                 if (a->Notification_Mask[appl->Id - 1] & SMASK_MWI) /* MWI active? */
1948                                 {
1949                                         if ((i = get_plci(a)))
1950                                         {
1951                                                 rplci = &a->plci[i - 1];
1952                                                 rplci->appl = appl;
1953                                                 add_p(rplci, CAI, "\x01\x80");
1954                                                 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1955                                                 sig_req(rplci, ASSIGN, DSIG_ID);
1956                                                 send_req(rplci);
1957                                         }
1958                                         else
1959                                         {
1960                                                 break;
1961                                         }
1962                                         rplci->internal_command = GET_MWI_STATE;
1963                                         rplci->number = Number;
1964                                         sig_req(rplci, MWI_POLL, 0);
1965                                         send_req(rplci);
1966                                 }
1967                                 break;
1968
1969                         case S_HOLD:
1970                                 api_parse(&parms->info[1], (word)parms->length, "ws", ss_parms);
1971                                 if (plci && plci->State && plci->SuppState == IDLE)
1972                                 {
1973                                         plci->SuppState = HOLD_REQUEST;
1974                                         plci->command = C_HOLD_REQ;
1975                                         add_s(plci, CAI, &ss_parms[1]);
1976                                         sig_req(plci, CALL_HOLD, 0);
1977                                         send_req(plci);
1978                                         return false;
1979                                 }
1980                                 else Info = 0x3010;                    /* wrong state           */
1981                                 break;
1982                         case S_RETRIEVE:
1983                                 if (plci && plci->State && plci->SuppState == CALL_HELD)
1984                                 {
1985                                         if (Id & EXT_CONTROLLER)
1986                                         {
1987                                                 if (AdvCodecSupport(a, plci, appl, 0))
1988                                                 {
1989                                                         Info = 0x3010;                    /* wrong state           */
1990                                                         break;
1991                                                 }
1992                                         }
1993                                         else plci->tel = 0;
1994
1995                                         plci->SuppState = RETRIEVE_REQUEST;
1996                                         plci->command = C_RETRIEVE_REQ;
1997                                         if (plci->spoofed_msg == SPOOFING_REQUIRED)
1998                                         {
1999                                                 plci->spoofed_msg = CALL_RETRIEVE;
2000                                                 plci->internal_command = BLOCK_PLCI;
2001                                                 plci->command = 0;
2002                                                 dbug(1, dprintf("Spoof"));
2003                                                 return false;
2004                                         }
2005                                         else
2006                                         {
2007                                                 sig_req(plci, CALL_RETRIEVE, 0);
2008                                                 send_req(plci);
2009                                                 return false;
2010                                         }
2011                                 }
2012                                 else Info = 0x3010;                    /* wrong state           */
2013                                 break;
2014                         case S_SUSPEND:
2015                                 if (parms->length)
2016                                 {
2017                                         if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2018                                         {
2019                                                 dbug(1, dprintf("format wrong"));
2020                                                 Info = _WRONG_MESSAGE_FORMAT;
2021                                                 break;
2022                                         }
2023                                 }
2024                                 if (plci && plci->State)
2025                                 {
2026                                         add_s(plci, CAI, &ss_parms[2]);
2027                                         plci->command = SUSPEND_REQ;
2028                                         sig_req(plci, SUSPEND, 0);
2029                                         plci->State = SUSPENDING;
2030                                         send_req(plci);
2031                                 }
2032                                 else Info = 0x3010;                    /* wrong state           */
2033                                 break;
2034
2035                         case S_RESUME:
2036                                 if (!(i = get_plci(a)))
2037                                 {
2038                                         Info = _OUT_OF_PLCI;
2039                                         break;
2040                                 }
2041                                 rplci = &a->plci[i - 1];
2042                                 rplci->appl = appl;
2043                                 rplci->number = Number;
2044                                 rplci->tel = 0;
2045                                 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2046                                 /* check 'external controller' bit for codec support */
2047                                 if (Id & EXT_CONTROLLER)
2048                                 {
2049                                         if (AdvCodecSupport(a, rplci, appl, 0))
2050                                         {
2051                                                 rplci->Id = 0;
2052                                                 Info = 0x300A;
2053                                                 break;
2054                                         }
2055                                 }
2056                                 if (parms->length)
2057                                 {
2058                                         if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2059                                         {
2060                                                 dbug(1, dprintf("format wrong"));
2061                                                 rplci->Id = 0;
2062                                                 Info = _WRONG_MESSAGE_FORMAT;
2063                                                 break;
2064                                         }
2065                                 }
2066                                 dummy.length = 0;
2067                                 dummy.info = "\x00";
2068                                 add_b1(rplci, &dummy, 0, 0);
2069                                 if (a->Info_Mask[appl->Id - 1] & 0x200)
2070                                 {
2071                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
2072                                         add_p(rplci, LLI, "\x01\x01");
2073                                 }
2074                                 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2075                                 sig_req(rplci, ASSIGN, DSIG_ID);
2076                                 send_req(rplci);
2077                                 add_s(rplci, CAI, &ss_parms[2]);
2078                                 rplci->command = RESUME_REQ;
2079                                 sig_req(rplci, RESUME, 0);
2080                                 rplci->State = RESUMING;
2081                                 send_req(rplci);
2082                                 break;
2083
2084                         case S_CONF_BEGIN: /* Request */
2085                         case S_CONF_DROP:
2086                         case S_CONF_ISOLATE:
2087                         case S_CONF_REATTACH:
2088                                 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2089                                 {
2090                                         dbug(1, dprintf("format wrong"));
2091                                         Info = _WRONG_MESSAGE_FORMAT;
2092                                         break;
2093                                 }
2094                                 if (plci && plci->State && ((plci->SuppState == IDLE) || (plci->SuppState == CALL_HELD)))
2095                                 {
2096                                         d = GET_DWORD(ss_parms[2].info);
2097                                         if (d >= 0x80)
2098                                         {
2099                                                 dbug(1, dprintf("format wrong"));
2100                                                 Info = _WRONG_MESSAGE_FORMAT;
2101                                                 break;
2102                                         }
2103                                         plci->ptyState = (byte)SSreq;
2104                                         plci->command = 0;
2105                                         cai[0] = 2;
2106                                         switch (SSreq)
2107                                         {
2108                                         case S_CONF_BEGIN:
2109                                                 cai[1] = CONF_BEGIN;
2110                                                 plci->internal_command = CONF_BEGIN_REQ_PEND;
2111                                                 break;
2112                                         case S_CONF_DROP:
2113                                                 cai[1] = CONF_DROP;
2114                                                 plci->internal_command = CONF_DROP_REQ_PEND;
2115                                                 break;
2116                                         case S_CONF_ISOLATE:
2117                                                 cai[1] = CONF_ISOLATE;
2118                                                 plci->internal_command = CONF_ISOLATE_REQ_PEND;
2119                                                 break;
2120                                         case S_CONF_REATTACH:
2121                                                 cai[1] = CONF_REATTACH;
2122                                                 plci->internal_command = CONF_REATTACH_REQ_PEND;
2123                                                 break;
2124                                         }
2125                                         cai[2] = (byte)d; /* Conference Size resp. PartyId */
2126                                         add_p(plci, CAI, cai);
2127                                         sig_req(plci, S_SERVICE, 0);
2128                                         send_req(plci);
2129                                         return false;
2130                                 }
2131                                 else Info = 0x3010;                    /* wrong state           */
2132                                 break;
2133
2134                         case S_ECT:
2135                         case S_3PTY_BEGIN:
2136                         case S_3PTY_END:
2137                         case S_CONF_ADD:
2138                                 if (parms->length == 7)
2139                                 {
2140                                         if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2141                                         {
2142                                                 dbug(1, dprintf("format wrong"));
2143                                                 Info = _WRONG_MESSAGE_FORMAT;
2144                                                 break;
2145                                         }
2146                                 }
2147                                 else if (parms->length == 8) /* workaround for the T-View-S */
2148                                 {
2149                                         if (api_parse(&parms->info[1], (word)parms->length, "wbdb", ss_parms))
2150                                         {
2151                                                 dbug(1, dprintf("format wrong"));
2152                                                 Info = _WRONG_MESSAGE_FORMAT;
2153                                                 break;
2154                                         }
2155                                 }
2156                                 else
2157                                 {
2158                                         Info = _WRONG_MESSAGE_FORMAT;
2159                                         break;
2160                                 }
2161                                 if (!msg[1].length)
2162                                 {
2163                                         Info = _WRONG_MESSAGE_FORMAT;
2164                                         break;
2165                                 }
2166                                 if (!plci)
2167                                 {
2168                                         Info = _WRONG_IDENTIFIER;
2169                                         break;
2170                                 }
2171                                 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2172                                 relatedPLCIvalue &= 0x0000FFFF;
2173                                 dbug(1, dprintf("PTY/ECT/addCONF,relPLCI=%lx", relatedPLCIvalue));
2174                                 /* controller starts with 0 up to (max_adapter - 1) */
2175                                 if (((relatedPLCIvalue & 0x7f) == 0)
2176                                     || (MapController((byte)(relatedPLCIvalue & 0x7f)) == 0)
2177                                     || (MapController((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2178                                 {
2179                                         if (SSreq == S_3PTY_END)
2180                                         {
2181                                                 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2182                                                 rplci = plci;
2183                                         }
2184                                         else
2185                                         {
2186                                                 Info = 0x3010;                    /* wrong state           */
2187                                                 break;
2188                                         }
2189                                 }
2190                                 else
2191                                 {
2192                                         relatedadapter = &adapter[MapController((byte)(relatedPLCIvalue & 0x7f)) - 1];
2193                                         relatedPLCIvalue >>= 8;
2194                                         /* find PLCI PTR*/
2195                                         for (i = 0, rplci = NULL; i < relatedadapter->max_plci; i++)
2196                                         {
2197                                                 if (relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2198                                                 {
2199                                                         rplci = &relatedadapter->plci[i];
2200                                                 }
2201                                         }
2202                                         if (!rplci || !relatedPLCIvalue)
2203                                         {
2204                                                 if (SSreq == S_3PTY_END)
2205                                                 {
2206                                                         dbug(1, dprintf("use 2nd PLCI=PLCI"));
2207                                                         rplci = plci;
2208                                                 }
2209                                                 else
2210                                                 {
2211                                                         Info = 0x3010;                    /* wrong state           */
2212                                                         break;
2213                                                 }
2214                                         }
2215                                 }
2216 /*
2217   dbug(1, dprintf("rplci:%x", rplci));
2218   dbug(1, dprintf("plci:%x", plci));
2219   dbug(1, dprintf("rplci->ptyState:%x", rplci->ptyState));
2220   dbug(1, dprintf("plci->ptyState:%x", plci->ptyState));
2221   dbug(1, dprintf("SSreq:%x", SSreq));
2222   dbug(1, dprintf("rplci->internal_command:%x", rplci->internal_command));
2223   dbug(1, dprintf("rplci->appl:%x", rplci->appl));
2224   dbug(1, dprintf("rplci->Id:%x", rplci->Id));
2225 */
2226                                 /* send PTY/ECT req, cannot check all states because of US stuff */
2227                                 if (!rplci->internal_command && rplci->appl)
2228                                 {
2229                                         plci->command = 0;
2230                                         rplci->relatedPTYPLCI = plci;
2231                                         plci->relatedPTYPLCI = rplci;
2232                                         rplci->ptyState = (byte)SSreq;
2233                                         if (SSreq == S_ECT)
2234                                         {
2235                                                 rplci->internal_command = ECT_REQ_PEND;
2236                                                 cai[1] = ECT_EXECUTE;
2237
2238                                                 rplci->vswitchstate = 0;
2239                                                 rplci->vsprot = 0;
2240                                                 rplci->vsprotdialect = 0;
2241                                                 plci->vswitchstate = 0;
2242                                                 plci->vsprot = 0;
2243                                                 plci->vsprotdialect = 0;
2244
2245                                         }
2246                                         else if (SSreq == S_CONF_ADD)
2247                                         {
2248                                                 rplci->internal_command = CONF_ADD_REQ_PEND;
2249                                                 cai[1] = CONF_ADD;
2250                                         }
2251                                         else
2252                                         {
2253                                                 rplci->internal_command = PTY_REQ_PEND;
2254                                                 cai[1] = (byte)(SSreq - 3);
2255                                         }
2256                                         rplci->number = Number;
2257                                         if (plci != rplci) /* explicit invocation */
2258                                         {
2259                                                 cai[0] = 2;
2260                                                 cai[2] = plci->Sig.Id;
2261                                                 dbug(1, dprintf("explicit invocation"));
2262                                         }
2263                                         else
2264                                         {
2265                                                 dbug(1, dprintf("implicit invocation"));
2266                                                 cai[0] = 1;
2267                                         }
2268                                         add_p(rplci, CAI, cai);
2269                                         sig_req(rplci, S_SERVICE, 0);
2270                                         send_req(rplci);
2271                                         return false;
2272                                 }
2273                                 else
2274                                 {
2275                                         dbug(0, dprintf("Wrong line"));
2276                                         Info = 0x3010;                    /* wrong state           */
2277                                         break;
2278                                 }
2279                                 break;
2280
2281                         case S_CALL_DEFLECTION:
2282                                 if (api_parse(&parms->info[1], (word)parms->length, "wbwss", ss_parms))
2283                                 {
2284                                         dbug(1, dprintf("format wrong"));
2285                                         Info = _WRONG_MESSAGE_FORMAT;
2286                                         break;
2287                                 }
2288                                 if (!plci)
2289                                 {
2290                                         Info = _WRONG_IDENTIFIER;
2291                                         break;
2292                                 }
2293                                 /* reuse unused screening indicator */
2294                                 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2295                                 plci->command = 0;
2296                                 plci->internal_command = CD_REQ_PEND;
2297                                 appl->CDEnable = true;
2298                                 cai[0] = 1;
2299                                 cai[1] = CALL_DEFLECTION;
2300                                 add_p(plci, CAI, cai);
2301                                 add_p(plci, CPN, ss_parms[3].info);
2302                                 sig_req(plci, S_SERVICE, 0);
2303                                 send_req(plci);
2304                                 return false;
2305                                 break;
2306
2307                         case S_CALL_FORWARDING_START:
2308                                 if (api_parse(&parms->info[1], (word)parms->length, "wbdwwsss", ss_parms))
2309                                 {
2310                                         dbug(1, dprintf("format wrong"));
2311                                         Info = _WRONG_MESSAGE_FORMAT;
2312                                         break;
2313                                 }
2314
2315                                 if ((i = get_plci(a)))
2316                                 {
2317                                         rplci = &a->plci[i - 1];
2318                                         rplci->appl = appl;
2319                                         add_p(rplci, CAI, "\x01\x80");
2320                                         add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2321                                         sig_req(rplci, ASSIGN, DSIG_ID);
2322                                         send_req(rplci);
2323                                 }
2324                                 else
2325                                 {
2326                                         Info = _OUT_OF_PLCI;
2327                                         break;
2328                                 }
2329
2330                                 /* reuse unused screening indicator */
2331                                 rplci->internal_command = CF_START_PEND;
2332                                 rplci->appl = appl;
2333                                 rplci->number = Number;
2334                                 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2335                                 cai[0] = 2;
2336                                 cai[1] = 0x70 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2337                                 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2338                                 add_p(rplci, CAI, cai);
2339                                 add_p(rplci, OAD, ss_parms[5].info);
2340                                 add_p(rplci, CPN, ss_parms[6].info);
2341                                 sig_req(rplci, S_SERVICE, 0);
2342                                 send_req(rplci);
2343                                 return false;
2344                                 break;
2345
2346                         case S_INTERROGATE_DIVERSION:
2347                         case S_INTERROGATE_NUMBERS:
2348                         case S_CALL_FORWARDING_STOP:
2349                         case S_CCBS_REQUEST:
2350                         case S_CCBS_DEACTIVATE:
2351                         case S_CCBS_INTERROGATE:
2352                                 switch (SSreq)
2353                                 {
2354                                 case S_INTERROGATE_NUMBERS:
2355                                         if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2356                                         {
2357                                                 dbug(0, dprintf("format wrong"));
2358                                                 Info = _WRONG_MESSAGE_FORMAT;
2359                                         }
2360                                         break;
2361                                 case S_CCBS_REQUEST:
2362                                 case S_CCBS_DEACTIVATE:
2363                                         if (api_parse(&parms->info[1], (word)parms->length, "wbdw", ss_parms))
2364                                         {
2365                                                 dbug(0, dprintf("format wrong"));
2366                                                 Info = _WRONG_MESSAGE_FORMAT;
2367                                         }
2368                                         break;
2369                                 case S_CCBS_INTERROGATE:
2370                                         if (api_parse(&parms->info[1], (word)parms->length, "wbdws", ss_parms))
2371                                         {
2372                                                 dbug(0, dprintf("format wrong"));
2373                                                 Info = _WRONG_MESSAGE_FORMAT;
2374                                         }
2375                                         break;
2376                                 default:
2377                                         if (api_parse(&parms->info[1], (word)parms->length, "wbdwws", ss_parms))
2378                                         {
2379                                                 dbug(0, dprintf("format wrong"));
2380                                                 Info = _WRONG_MESSAGE_FORMAT;
2381                                                 break;
2382                                         }
2383                                         break;
2384                                 }
2385
2386                                 if (Info) break;
2387                                 if ((i = get_plci(a)))
2388                                 {
2389                                         rplci = &a->plci[i - 1];
2390                                         switch (SSreq)
2391                                         {
2392                                         case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2393                                                 cai[1] = 0x60 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2394                                                 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2395                                                 break;
2396                                         case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2397                                                 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2398                                                 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2399                                                 break;
2400                                         case S_CALL_FORWARDING_STOP:
2401                                                 rplci->internal_command = CF_STOP_PEND;
2402                                                 cai[1] = 0x80 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2403                                                 break;
2404                                         case S_CCBS_REQUEST:
2405                                                 cai[1] = CCBS_REQUEST;
2406                                                 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2407                                                 break;
2408                                         case S_CCBS_DEACTIVATE:
2409                                                 cai[1] = CCBS_DEACTIVATE;
2410                                                 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2411                                                 break;
2412                                         case S_CCBS_INTERROGATE:
2413                                                 cai[1] = CCBS_INTERROGATE;
2414                                                 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2415                                                 break;
2416                                         default:
2417                                                 cai[1] = 0;
2418                                                 break;
2419                                         }
2420                                         rplci->appl = appl;
2421                                         rplci->number = Number;
2422                                         add_p(rplci, CAI, "\x01\x80");
2423                                         add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2424                                         sig_req(rplci, ASSIGN, DSIG_ID);
2425                                         send_req(rplci);
2426                                 }
2427                                 else
2428                                 {
2429                                         Info = _OUT_OF_PLCI;
2430                                         break;
2431                                 }
2432
2433                                 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2434                                 switch (SSreq)
2435                                 {
2436                                 case S_INTERROGATE_NUMBERS:
2437                                         cai[0] = 1;
2438                                         add_p(rplci, CAI, cai);
2439                                         break;
2440                                 case S_CCBS_REQUEST:
2441                                 case S_CCBS_DEACTIVATE:
2442                                         cai[0] = 3;
2443                                         PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2444                                         add_p(rplci, CAI, cai);
2445                                         break;
2446                                 case S_CCBS_INTERROGATE:
2447                                         cai[0] = 3;
2448                                         PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2449                                         add_p(rplci, CAI, cai);
2450                                         add_p(rplci, OAD, ss_parms[4].info);
2451                                         break;
2452                                 default:
2453                                         cai[0] = 2;
2454                                         cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2455                                         add_p(rplci, CAI, cai);
2456                                         add_p(rplci, OAD, ss_parms[5].info);
2457                                         break;
2458                                 }
2459
2460                                 sig_req(rplci, S_SERVICE, 0);
2461                                 send_req(rplci);
2462                                 return false;
2463                                 break;
2464
2465                         case S_MWI_ACTIVATE:
2466                                 if (api_parse(&parms->info[1], (word)parms->length, "wbwdwwwssss", ss_parms))
2467                                 {
2468                                         dbug(1, dprintf("format wrong"));
2469                                         Info = _WRONG_MESSAGE_FORMAT;
2470                                         break;
2471                                 }
2472                                 if (!plci)
2473                                 {
2474                                         if ((i = get_plci(a)))
2475                                         {
2476                                                 rplci = &a->plci[i - 1];
2477                                                 rplci->appl = appl;
2478                                                 rplci->cr_enquiry = true;
2479                                                 add_p(rplci, CAI, "\x01\x80");
2480                                                 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2481                                                 sig_req(rplci, ASSIGN, DSIG_ID);
2482                                                 send_req(rplci);
2483                                         }
2484                                         else
2485                                         {
2486                                                 Info = _OUT_OF_PLCI;
2487                                                 break;
2488                                         }
2489                                 }
2490                                 else
2491                                 {
2492                                         rplci = plci;
2493                                         rplci->cr_enquiry = false;
2494                                 }
2495
2496                                 rplci->command = 0;
2497                                 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2498                                 rplci->appl = appl;
2499                                 rplci->number = Number;
2500
2501                                 cai[0] = 13;
2502                                 cai[1] = ACTIVATION_MWI; /* Function */
2503                                 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2504                                 PUT_DWORD(&cai[4], GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2505                                 PUT_WORD(&cai[8], GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2506                                 PUT_WORD(&cai[10], GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2507                                 PUT_WORD(&cai[12], GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2508                                 add_p(rplci, CAI, cai);
2509                                 add_p(rplci, CPN, ss_parms[7].info); /* Receiving User Number */
2510                                 add_p(rplci, OAD, ss_parms[8].info); /* Controlling User Number */
2511                                 add_p(rplci, OSA, ss_parms[9].info); /* Controlling User Provided Number */
2512                                 add_p(rplci, UID, ss_parms[10].info); /* Time */
2513                                 sig_req(rplci, S_SERVICE, 0);
2514                                 send_req(rplci);
2515                                 return false;
2516
2517                         case S_MWI_DEACTIVATE:
2518                                 if (api_parse(&parms->info[1], (word)parms->length, "wbwwss", ss_parms))
2519                                 {
2520                                         dbug(1, dprintf("format wrong"));
2521                                         Info = _WRONG_MESSAGE_FORMAT;
2522                                         break;
2523                                 }
2524                                 if (!plci)
2525                                 {
2526                                         if ((i = get_plci(a)))
2527                                         {
2528                                                 rplci = &a->plci[i - 1];
2529                                                 rplci->appl = appl;
2530                                                 rplci->cr_enquiry = true;
2531                                                 add_p(rplci, CAI, "\x01\x80");
2532                                                 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2533                                                 sig_req(rplci, ASSIGN, DSIG_ID);
2534                                                 send_req(rplci);
2535                                         }
2536                                         else
2537                                         {
2538                                                 Info = _OUT_OF_PLCI;
2539                                                 break;
2540                                         }
2541                                 }
2542                                 else
2543                                 {
2544                                         rplci = plci;
2545                                         rplci->cr_enquiry = false;
2546                                 }
2547
2548                                 rplci->command = 0;
2549                                 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2550                                 rplci->appl = appl;
2551                                 rplci->number = Number;
2552
2553                                 cai[0] = 5;
2554                                 cai[1] = DEACTIVATION_MWI; /* Function */
2555                                 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2556                                 PUT_WORD(&cai[4], GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2557                                 add_p(rplci, CAI, cai);
2558                                 add_p(rplci, CPN, ss_parms[4].info); /* Receiving User Number */
2559                                 add_p(rplci, OAD, ss_parms[5].info); /* Controlling User Number */
2560                                 sig_req(rplci, S_SERVICE, 0);
2561                                 send_req(rplci);
2562                                 return false;
2563
2564                         default:
2565                                 Info = 0x300E;  /* not supported */
2566                                 break;
2567                         }
2568                         break; /* case SELECTOR_SU_SERV: end */
2569
2570
2571                 case SELECTOR_DTMF:
2572                         return (dtmf_request(Id, Number, a, plci, appl, msg));
2573
2574
2575
2576                 case SELECTOR_LINE_INTERCONNECT:
2577                         return (mixer_request(Id, Number, a, plci, appl, msg));
2578
2579
2580
2581                 case PRIV_SELECTOR_ECHO_CANCELLER:
2582                         appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2583                         return (ec_request(Id, Number, a, plci, appl, msg));
2584
2585                 case SELECTOR_ECHO_CANCELLER:
2586                         appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2587                         return (ec_request(Id, Number, a, plci, appl, msg));
2588
2589
2590                 case SELECTOR_V42BIS:
2591                 default:
2592                         Info = _FACILITY_NOT_SUPPORTED;
2593                         break;
2594                 } /* end of switch (selector) */
2595         }
2596
2597         dbug(1, dprintf("SendFacRc"));
2598         sendf(appl,
2599               _FACILITY_R | CONFIRM,
2600               Id,
2601               Number,
2602               "wws", Info, selector, SSparms);
2603         return false;
2604 }
2605
2606 static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2607                          PLCI *plci, APPL *appl, API_PARSE *msg)
2608 {
2609         dbug(1, dprintf("facility_res"));
2610         return false;
2611 }
2612
2613 static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2614                            PLCI *plci, APPL *appl, API_PARSE *parms)
2615 {
2616         word Info = 0;
2617         byte req;
2618         byte len;
2619         word w;
2620         word fax_control_bits, fax_feature_bits, fax_info_change;
2621         API_PARSE *ncpi;
2622         byte pvc[2];
2623
2624         API_PARSE fax_parms[9];
2625         word i;
2626
2627
2628         dbug(1, dprintf("connect_b3_req"));
2629         if (plci)
2630         {
2631                 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2632                     || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2633                 {
2634                         Info = _WRONG_STATE;
2635                 }
2636                 else
2637                 {
2638                         /* local reply if assign unsuccessful
2639                            or B3 protocol allows only one layer 3 connection
2640                            and already connected
2641                            or B2 protocol not any LAPD
2642                            and connect_b3_req contradicts originate/answer direction */
2643                         if (!plci->NL.Id
2644                             || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2645                                 && ((plci->channels != 0)
2646                                     || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2647                                         && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2648                         {
2649                                 dbug(1, dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2650                                                 plci->channels, plci->NL.Id, plci->call_dir, plci->SuppState));
2651                                 Info = _WRONG_STATE;
2652                                 sendf(appl,
2653                                       _CONNECT_B3_R | CONFIRM,
2654                                       Id,
2655                                       Number,
2656                                       "w", Info);
2657                                 return false;
2658                         }
2659                         plci->requested_options_conn = 0;
2660
2661                         req = N_CONNECT;
2662                         ncpi = &parms[0];
2663                         if (plci->B3_prot == 2 || plci->B3_prot == 3)
2664                         {
2665                                 if (ncpi->length > 2)
2666                                 {
2667                                         /* check for PVC */
2668                                         if (ncpi->info[2] || ncpi->info[3])
2669                                         {
2670                                                 pvc[0] = ncpi->info[3];
2671                                                 pvc[1] = ncpi->info[2];
2672                                                 add_d(plci, 2, pvc);
2673                                                 req = N_RESET;
2674                                         }
2675                                         else
2676                                         {
2677                                                 if (ncpi->info[1] & 1) req = N_CONNECT | N_D_BIT;
2678                                                 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2679                                         }
2680                                 }
2681                         }
2682                         else if (plci->B3_prot == 5)
2683                         {
2684                                 if (plci->NL.Id && !plci->nl_remove_id)
2685                                 {
2686                                         fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2687                                         fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2688                                         if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2689                                             || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2690                                         {
2691                                                 len = offsetof(T30_INFO, universal_6);
2692                                                 fax_info_change = false;
2693                                                 if (ncpi->length >= 4)
2694                                                 {
2695                                                         w = GET_WORD(&ncpi->info[3]);
2696                                                         if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2697                                                         {
2698                                                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2699                                                                         (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2700                                                                                ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2701                                                                 fax_info_change = true;
2702                                                         }
2703                                                         fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2704                                                         if (w & 0x0002)  /* Fax-polling request */
2705                                                                 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2706                                                         if ((w & 0x0004) /* Request to send / poll another document */
2707                                                             && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2708                                                         {
2709                                                                 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2710                                                         }
2711                                                         if (ncpi->length >= 6)
2712                                                         {
2713                                                                 w = GET_WORD(&ncpi->info[5]);
2714                                                                 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2715                                                                 {
2716                                                                         ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2717                                                                         fax_info_change = true;
2718                                                                 }
2719
2720                                                                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2721                                                                     && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2722                                                                 {
2723                                                                         plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2724                                                                 }
2725                                                                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2726                                                                     && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2727                                                                 {
2728                                                                         plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2729                                                                 }
2730                                                                 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2731                                                                                       T30_CONTROL_BIT_ACCEPT_PASSWORD);
2732                                                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2733                                                                     & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2734                                                                 {
2735                                                                         if (api_parse(&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2736                                                                                 Info = _WRONG_MESSAGE_FORMAT;
2737                                                                         else
2738                                                                         {
2739                                                                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2740                                                                                     & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2741                                                                                 {
2742                                                                                         fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2743                                                                                         if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2744                                                                                                 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2745                                                                                 }
2746                                                                                 w = fax_parms[4].length;
2747                                                                                 if (w > 20)
2748                                                                                         w = 20;
2749                                                                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2750                                                                                 for (i = 0; i < w; i++)
2751                                                                                         ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1 + i];
2752                                                                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2753                                                                                 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2754                                                                                 w = fax_parms[5].length;
2755                                                                                 if (w > 20)
2756                                                                                         w = 20;
2757                                                                                 plci->fax_connect_info_buffer[len++] = (byte) w;
2758                                                                                 for (i = 0; i < w; i++)
2759                                                                                         plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1 + i];
2760                                                                                 w = fax_parms[6].length;
2761                                                                                 if (w > 20)
2762                                                                                         w = 20;
2763                                                                                 plci->fax_connect_info_buffer[len++] = (byte) w;
2764                                                                                 for (i = 0; i < w; i++)
2765                                                                                         plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1 + i];
2766                                                                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2767                                                                                     & (1L << PRIVATE_FAX_NONSTANDARD))
2768                                                                                 {
2769                                                                                         if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2770                                                                                         {
2771                                                                                                 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2772                                                                                                 plci->fax_connect_info_buffer[len++] = 0;
2773                                                                                         }
2774                                                                                         else
2775                                                                                         {
2776                                                                                                 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2777                                                                                                         plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2778                                                                                                 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2779                                                                                                 for (i = 0; i < fax_parms[7].length; i++)
2780                                                                                                         plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2781                                                                                         }
2782                                                                                 }
2783                                                                         }
2784                                                                 }
2785                                                                 else
2786                                                                 {
2787                                                                         len = offsetof(T30_INFO, universal_6);
2788                                                                 }
2789                                                                 fax_info_change = true;
2790
2791                                                         }
2792                                                         if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2793                                                         {
2794                                                                 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2795                                                                 fax_info_change = true;
2796                                                         }
2797                                                 }
2798                                                 if (Info == GOOD)
2799                                                 {
2800                                                         plci->fax_connect_info_length = len;
2801                                                         if (fax_info_change)
2802                                                         {
2803                                                                 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2804                                                                 {
2805                                                                         start_internal_command(Id, plci, fax_connect_info_command);
2806                                                                         return false;
2807                                                                 }
2808                                                                 else
2809                                                                 {
2810                                                                         start_internal_command(Id, plci, fax_adjust_b23_command);
2811                                                                         return false;
2812                                                                 }
2813                                                         }
2814                                                 }
2815                                         }
2816                                         else  Info = _WRONG_STATE;
2817                                 }
2818                                 else  Info = _WRONG_STATE;
2819                         }
2820
2821                         else if (plci->B3_prot == B3_RTP)
2822                         {
2823                                 plci->internal_req_buffer[0] = ncpi->length + 1;
2824                                 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2825                                 for (w = 0; w < ncpi->length; w++)
2826                                         plci->internal_req_buffer[2 + w] = ncpi->info[1 + w];
2827                                 start_internal_command(Id, plci, rtp_connect_b3_req_command);
2828                                 return false;
2829                         }
2830
2831                         if (!Info)
2832                         {
2833                                 nl_req_ncci(plci, req, 0);
2834                                 return 1;
2835                         }
2836                 }
2837         }
2838         else Info = _WRONG_IDENTIFIER;
2839
2840         sendf(appl,
2841               _CONNECT_B3_R | CONFIRM,
2842               Id,
2843               Number,
2844               "w", Info);
2845         return false;
2846 }
2847
2848 static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2849                            PLCI *plci, APPL *appl, API_PARSE *parms)
2850 {
2851         word ncci;
2852         API_PARSE *ncpi;
2853         byte req;
2854
2855         word w;
2856
2857
2858         API_PARSE fax_parms[9];
2859         word i;
2860         byte len;
2861
2862
2863         dbug(1, dprintf("connect_b3_res"));
2864
2865         ncci = (word)(Id >> 16);
2866         if (plci && ncci) {
2867                 if (a->ncci_state[ncci] == INC_CON_PENDING) {
2868                         if (GET_WORD(&parms[0].info[0]) != 0)
2869                         {
2870                                 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2871                                 channel_request_xon(plci, a->ncci_ch[ncci]);
2872                                 channel_xmit_xon(plci);
2873                                 cleanup_ncci_data(plci, ncci);
2874                                 nl_req_ncci(plci, N_DISC, (byte)ncci);
2875                                 return 1;
2876                         }
2877                         a->ncci_state[ncci] = INC_ACT_PENDING;
2878
2879                         req = N_CONNECT_ACK;
2880                         ncpi = &parms[1];
2881                         if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2882                         {
2883
2884                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
2885                                     & (1L << PRIVATE_FAX_NONSTANDARD))
2886                                 {
2887                                         if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2888                                             && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2889                                             && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2890                                         {
2891                                                 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2892                                                 if (plci->fax_connect_info_length < len)
2893                                                 {
2894                                                         ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2895                                                         ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2896                                                 }
2897                                                 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2898                                                 {
2899                                                         dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2900                                                 }
2901                                                 else
2902                                                 {
2903                                                         if (plci->fax_connect_info_length <= len)
2904                                                                 plci->fax_connect_info_buffer[len] = 0;
2905                                                         len += 1 + plci->fax_connect_info_buffer[len];
2906                                                         if (plci->fax_connect_info_length <= len)
2907                                                                 plci->fax_connect_info_buffer[len] = 0;
2908                                                         len += 1 + plci->fax_connect_info_buffer[len];
2909                                                         if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2910                                                                 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2911                                                         plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2912                                                         for (i = 0; i < fax_parms[7].length; i++)
2913                                                                 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2914                                                 }
2915                                                 plci->fax_connect_info_length = len;
2916                                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2917                                                 start_internal_command(Id, plci, fax_connect_ack_command);
2918                                                 return false;
2919                                         }
2920                                 }
2921
2922                                 nl_req_ncci(plci, req, (byte)ncci);
2923                                 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2924                                     && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2925                                 {
2926                                         if (plci->B3_prot == 4)
2927                                                 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2928                                         else
2929                                                 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
2930                                         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2931                                 }
2932                         }
2933
2934                         else if (plci->B3_prot == B3_RTP)
2935                         {
2936                                 plci->internal_req_buffer[0] = ncpi->length + 1;
2937                                 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2938                                 for (w = 0; w < ncpi->length; w++)
2939                                         plci->internal_req_buffer[2 + w] = ncpi->info[1+w];
2940                                 start_internal_command(Id, plci, rtp_connect_b3_res_command);
2941                                 return false;
2942                         }
2943
2944                         else
2945                         {
2946                                 if (ncpi->length > 2) {
2947                                         if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
2948                                         add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2949                                 }
2950                                 nl_req_ncci(plci, req, (byte)ncci);
2951                                 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2952                                 if (plci->adjust_b_restore)
2953                                 {
2954                                         plci->adjust_b_restore = false;
2955                                         start_internal_command(Id, plci, adjust_b_restore);
2956                                 }
2957                         }
2958                         return 1;
2959                 }
2960         }
2961         return false;
2962 }
2963
2964 static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2965                              PLCI *plci, APPL *appl, API_PARSE *parms)
2966 {
2967         word ncci;
2968
2969         ncci = (word)(Id >> 16);
2970         dbug(1, dprintf("connect_b3_a_res(ncci=0x%x)", ncci));
2971
2972         if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2973             && (plci->State != OUTG_DIS_PENDING))
2974         {
2975                 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
2976                         a->ncci_state[ncci] = CONNECTED;
2977                         if (plci->State != INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2978                         channel_request_xon(plci, a->ncci_ch[ncci]);
2979                         channel_xmit_xon(plci);
2980                 }
2981         }
2982         return false;
2983 }
2984
2985 static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2986                               PLCI *plci, APPL *appl, API_PARSE *parms)
2987 {
2988         word Info;
2989         word ncci;
2990         API_PARSE *ncpi;
2991
2992         dbug(1, dprintf("disconnect_b3_req"));
2993
2994         Info = _WRONG_IDENTIFIER;
2995         ncci = (word)(Id >> 16);
2996         if (plci && ncci)
2997         {
2998                 Info = _WRONG_STATE;
2999                 if ((a->ncci_state[ncci] == CONNECTED)
3000                     || (a->ncci_state[ncci] == OUTG_CON_PENDING)
3001                     || (a->ncci_state[ncci] == INC_CON_PENDING)
3002                     || (a->ncci_state[ncci] == INC_ACT_PENDING))
3003                 {
3004                         a->ncci_state[ncci] = OUTG_DIS_PENDING;
3005                         channel_request_xon(plci, a->ncci_ch[ncci]);
3006                         channel_xmit_xon(plci);
3007
3008                         if (a->ncci[ncci].data_pending
3009                             && ((plci->B3_prot == B3_TRANSPARENT)
3010                                 || (plci->B3_prot == B3_T30)
3011                                 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3012                         {
3013                                 plci->send_disc = (byte)ncci;
3014                                 plci->command = 0;
3015                                 return false;
3016                         }
3017                         else
3018                         {
3019                                 cleanup_ncci_data(plci, ncci);
3020
3021                                 if (plci->B3_prot == 2 || plci->B3_prot == 3)
3022                                 {
3023                                         ncpi = &parms[0];
3024                                         if (ncpi->length > 3)
3025                                         {
3026                                                 add_d(plci, (word)(ncpi->length - 3), (byte *)&(ncpi->info[4]));
3027                                         }
3028                                 }
3029                                 nl_req_ncci(plci, N_DISC, (byte)ncci);
3030                         }
3031                         return 1;
3032                 }
3033         }
3034         sendf(appl,
3035               _DISCONNECT_B3_R | CONFIRM,
3036               Id,
3037               Number,
3038               "w", Info);
3039         return false;
3040 }
3041
3042 static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3043                               PLCI *plci, APPL *appl, API_PARSE *parms)
3044 {
3045         word ncci;
3046         word i;
3047
3048         ncci = (word)(Id >> 16);
3049         dbug(1, dprintf("disconnect_b3_res(ncci=0x%x", ncci));
3050         if (plci && ncci) {
3051                 plci->requested_options_conn = 0;
3052                 plci->fax_connect_info_length = 0;
3053                 plci->ncpi_state = 0x00;
3054                 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3055                     && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3056                 {
3057                         plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3058                 }
3059                 for (i = 0; i < MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i] != (byte)ncci; i++);
3060                 if (i < MAX_CHANNELS_PER_PLCI) {
3061                         if (plci->channels)plci->channels--;
3062                         for (; i < MAX_CHANNELS_PER_PLCI - 1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i + 1];
3063                         plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI - 1] = 0;
3064
3065                         ncci_free_receive_buffers(plci, ncci);
3066
3067                         if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
3068                                 if (plci->State == SUSPENDING) {
3069                                         sendf(plci->appl,
3070                                               _FACILITY_I,
3071                                               Id & 0xffffL,
3072                                               0,
3073                                               "ws", (word)3, "\x03\x04\x00\x00");
3074                                         sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3075                                 }
3076                                 plci_remove(plci);
3077                                 plci->State = IDLE;
3078                         }
3079                 }
3080                 else
3081                 {
3082                         if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3083                             && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3084                             && (a->ncci_state[ncci] == INC_DIS_PENDING))
3085                         {
3086                                 ncci_free_receive_buffers(plci, ncci);
3087
3088                                 nl_req_ncci(plci, N_EDATA, (byte)ncci);
3089
3090                                 plci->adapter->ncci_state[ncci] = IDLE;
3091                                 start_internal_command(Id, plci, fax_disconnect_command);
3092                                 return 1;
3093                         }
3094                 }
3095         }
3096         return false;
3097 }
3098
3099 static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3100                         PLCI *plci, APPL *appl, API_PARSE *parms)
3101 {
3102         NCCI *ncci_ptr;
3103         DATA_B3_DESC *data;
3104         word Info;
3105         word ncci;
3106         word i;
3107
3108         dbug(1, dprintf("data_b3_req"));
3109
3110         Info = _WRONG_IDENTIFIER;
3111         ncci = (word)(Id >> 16);
3112         dbug(1, dprintf("ncci=0x%x, plci=0x%x", ncci, plci));
3113
3114         if (plci && ncci)
3115         {
3116                 Info = _WRONG_STATE;
3117                 if ((a->ncci_state[ncci] == CONNECTED)
3118                     || (a->ncci_state[ncci] == INC_ACT_PENDING))
3119                 {
3120                         /* queue data */
3121                         ncci_ptr = &(a->ncci[ncci]);
3122                         i = ncci_ptr->data_out + ncci_ptr->data_pending;
3123                         if (i >= MAX_DATA_B3)
3124                                 i -= MAX_DATA_B3;
3125                         data = &(ncci_ptr->DBuffer[i]);
3126                         data->Number = Number;
3127                         if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3128                             && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3129                         {
3130
3131                                 data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3132
3133                         }
3134                         else
3135                                 data->P = TransmitBufferSet(appl, *(dword *)parms[0].info);
3136                         data->Length = GET_WORD(parms[1].info);
3137                         data->Handle = GET_WORD(parms[2].info);
3138                         data->Flags = GET_WORD(parms[3].info);
3139                         (ncci_ptr->data_pending)++;
3140
3141                         /* check for delivery confirmation */
3142                         if (data->Flags & 0x0004)
3143                         {
3144                                 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3145                                 if (i >= MAX_DATA_ACK)
3146                                         i -= MAX_DATA_ACK;
3147                                 ncci_ptr->DataAck[i].Number = data->Number;
3148                                 ncci_ptr->DataAck[i].Handle = data->Handle;
3149                                 (ncci_ptr->data_ack_pending)++;
3150                         }
3151
3152                         send_data(plci);
3153                         return false;
3154                 }
3155         }
3156         if (appl)
3157         {
3158                 if (plci)
3159                 {
3160                         if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3161                             && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3162                         {
3163
3164                                 TransmitBufferFree(appl, (byte *)(long)(*((dword *)(parms[0].info))));
3165
3166                         }
3167                 }
3168                 sendf(appl,
3169                       _DATA_B3_R | CONFIRM,
3170                       Id,
3171                       Number,
3172                       "ww", GET_WORD(parms[2].info), Info);
3173         }
3174         return false;
3175 }
3176
3177 static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3178                         PLCI *plci, APPL *appl, API_PARSE *parms)
3179 {
3180         word n;
3181         word ncci;
3182         word NCCIcode;
3183
3184         dbug(1, dprintf("data_b3_res"));
3185
3186         ncci = (word)(Id >> 16);
3187         if (plci && ncci) {
3188                 n = GET_WORD(parms[0].info);
3189                 dbug(1, dprintf("free(%d)", n));
3190                 NCCIcode = ncci | (((word) a->Id) << 8);
3191                 if (n < appl->MaxBuffer &&
3192                     appl->DataNCCI[n] == NCCIcode &&
3193                     (byte)(appl->DataFlags[n] >> 8) == plci->Id) {
3194                         dbug(1, dprintf("found"));
3195                         appl->DataNCCI[n] = 0;
3196
3197                         if (channel_can_xon(plci, a->ncci_ch[ncci])) {
3198                                 channel_request_xon(plci, a->ncci_ch[ncci]);
3199                         }
3200                         channel_xmit_xon(plci);
3201
3202                         if (appl->DataFlags[n] & 4) {
3203                                 nl_req_ncci(plci, N_DATA_ACK, (byte)ncci);
3204                                 return 1;
3205                         }
3206                 }
3207         }
3208         return false;
3209 }
3210
3211 static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3212                          PLCI *plci, APPL *appl, API_PARSE *parms)
3213 {
3214         word Info;
3215         word ncci;
3216
3217         dbug(1, dprintf("reset_b3_req"));
3218
3219         Info = _WRONG_IDENTIFIER;
3220         ncci = (word)(Id >> 16);
3221         if (plci && ncci)
3222         {
3223                 Info = _WRONG_STATE;
3224                 switch (plci->B3_prot)
3225                 {
3226                 case B3_ISO8208:
3227                 case B3_X25_DCE:
3228                         if (a->ncci_state[ncci] == CONNECTED)
3229                         {
3230                                 nl_req_ncci(plci, N_RESET, (byte)ncci);
3231                                 send_req(plci);
3232                                 Info = GOOD;
3233                         }
3234                         break;
3235                 case B3_TRANSPARENT:
3236                         if (a->ncci_state[ncci] == CONNECTED)
3237                         {
3238                                 start_internal_command(Id, plci, reset_b3_command);
3239                                 Info = GOOD;
3240                         }
3241                         break;
3242                 }
3243         }
3244         /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3245         sendf(appl,
3246               _RESET_B3_R | CONFIRM,
3247               Id,
3248               Number,
3249               "w", Info);
3250         return false;
3251 }
3252
3253 static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3254                          PLCI *plci, APPL *appl, API_PARSE *parms)
3255 {
3256         word ncci;
3257
3258         dbug(1, dprintf("reset_b3_res"));
3259
3260         ncci = (word)(Id >> 16);
3261         if (plci && ncci) {
3262                 switch (plci->B3_prot)
3263                 {
3264                 case B3_ISO8208:
3265                 case B3_X25_DCE:
3266                         if (a->ncci_state[ncci] == INC_RES_PENDING)
3267                         {
3268                                 a->ncci_state[ncci] = CONNECTED;
3269                                 nl_req_ncci(plci, N_RESET_ACK, (byte)ncci);
3270                                 return true;
3271                         }
3272                         break;
3273                 }
3274         }
3275         return false;
3276 }
3277
3278 static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3279                                  PLCI *plci, APPL *appl, API_PARSE *parms)
3280 {
3281         word ncci;
3282         API_PARSE *ncpi;
3283         byte req;
3284
3285         dbug(1, dprintf("connect_b3_t90_a_res"));
3286
3287         ncci = (word)(Id >> 16);
3288         if (plci && ncci) {
3289                 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
3290                         a->ncci_state[ncci] = CONNECTED;
3291                 }
3292                 else if (a->ncci_state[ncci] == INC_CON_PENDING) {
3293                         a->ncci_state[ncci] = CONNECTED;
3294
3295                         req = N_CONNECT_ACK;
3296
3297                         /* parms[0]==0 for CAPI original message definition! */
3298                         if (parms[0].info) {
3299                                 ncpi = &parms[1];
3300                                 if (ncpi->length > 2) {
3301                                         if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
3302                                         add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
3303                                 }
3304                         }
3305                         nl_req_ncci(plci, req, (byte)ncci);
3306                         return 1;
3307                 }
3308         }
3309         return false;
3310 }
3311
3312
3313 static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3314                          PLCI *plci, APPL *appl, API_PARSE *msg)
3315 {
3316         word Info = 0;
3317         word i;
3318         byte tel;
3319         API_PARSE bp_parms[7];
3320
3321         if (!plci || !msg)
3322         {
3323                 Info = _WRONG_IDENTIFIER;
3324         }
3325         else
3326         {
3327                 dbug(1, dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3328                                 msg->length, plci->Id, plci->tel, plci->NL.Id, plci->appl, plci->SuppState));
3329                 dbug(1, dprintf("PlciState=0x%x", plci->State));
3330                 for (i = 0; i < 7; i++) bp_parms[i].length = 0;
3331
3332                 /* check if no channel is open, no B3 connected only */
3333                 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3334                     || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3335                 {
3336                         Info = _WRONG_STATE;
3337                 }
3338                 /* check message format and fill bp_parms pointer */
3339                 else if (msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3340                 {
3341                         Info = _WRONG_MESSAGE_FORMAT;
3342                 }
3343                 else
3344                 {
3345                         if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT)) /* send alert tone inband to the network, */
3346                         {                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3347                                 if (Id & EXT_CONTROLLER)
3348                                 {
3349                                         sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3350                                         return 0;
3351                                 }
3352                                 plci->State = INC_CON_CONNECTED_ALERT;
3353                                 plci->appl = appl;
3354                                 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
3355                                 dump_c_ind_mask(plci);
3356                                 for (i = 0; i < max_appl; i++) /* disconnect the other appls */
3357                                 {                         /* its quasi a connect        */
3358                                         if (test_c_ind_mask_bit(plci, i))
3359                                                 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3360                                 }
3361                         }
3362
3363                         api_save_msg(msg, "s", &plci->saved_msg);
3364                         tel = plci->tel;
3365                         if (Id & EXT_CONTROLLER)
3366                         {
3367                                 if (tel) /* external controller in use by this PLCI */
3368                                 {
3369                                         if (a->AdvSignalAppl && a->AdvSignalAppl != appl)
3370                                         {
3371                                                 dbug(1, dprintf("Ext_Ctrl in use 1"));
3372                                                 Info = _WRONG_STATE;
3373                                         }
3374                                 }
3375                                 else  /* external controller NOT in use by this PLCI ? */
3376                                 {
3377                                         if (a->AdvSignalPLCI)
3378                                         {
3379                                                 dbug(1, dprintf("Ext_Ctrl in use 2"));
3380                                                 Info = _WRONG_STATE;
3381                                         }
3382                                         else /* activate the codec */
3383                                         {
3384                                                 dbug(1, dprintf("Ext_Ctrl start"));
3385                                                 if (AdvCodecSupport(a, plci, appl, 0))
3386                                                 {
3387                                                         dbug(1, dprintf("Error in codec procedures"));
3388                                                         Info = _WRONG_STATE;
3389                                                 }
3390                                                 else if (plci->spoofed_msg == SPOOFING_REQUIRED) /* wait until codec is active */
3391                                                 {
3392                                                         plci->spoofed_msg = AWAITING_SELECT_B;
3393                                                         plci->internal_command = BLOCK_PLCI; /* lock other commands */
3394                                                         plci->command = 0;
3395                                                         dbug(1, dprintf("continue if codec loaded"));
3396                                                         return false;
3397                                                 }
3398                                         }
3399                                 }
3400                         }
3401                         else /* external controller bit is OFF */
3402                         {
3403                                 if (tel) /* external controller in use, need to switch off */
3404                                 {
3405                                         if (a->AdvSignalAppl == appl)
3406                                         {
3407                                                 CodecIdCheck(a, plci);
3408                                                 plci->tel = 0;
3409                                                 plci->adv_nl = 0;
3410                                                 dbug(1, dprintf("Ext_Ctrl disable"));
3411                                         }
3412                                         else
3413                                         {
3414                                                 dbug(1, dprintf("Ext_Ctrl not requested"));
3415                                         }
3416                                 }
3417                         }
3418                         if (!Info)
3419                         {
3420                                 if (plci->call_dir & CALL_DIR_OUT)
3421                                         plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3422                                 else if (plci->call_dir & CALL_DIR_IN)
3423                                         plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3424                                 start_internal_command(Id, plci, select_b_command);
3425                                 return false;
3426                         }
3427                 }
3428         }
3429         sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", Info);
3430         return false;
3431 }
3432
3433 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3434                              PLCI *plci, APPL *appl, API_PARSE *parms)
3435 {
3436         word command;
3437         word i;
3438         word ncci;
3439         API_PARSE *m;
3440         API_PARSE m_parms[5];
3441         word codec;
3442         byte req;
3443         byte ch;
3444         byte dir;
3445         static byte chi[2] = {0x01, 0x00};
3446         static byte lli[2] = {0x01, 0x00};
3447         static byte codec_cai[2] = {0x01, 0x01};
3448         static byte null_msg = {0};
3449         static API_PARSE null_parms = { 0, &null_msg };
3450         PLCI *v_plci;
3451         word Info = 0;
3452
3453         dbug(1, dprintf("manufacturer_req"));
3454         for (i = 0; i < 5; i++) m_parms[i].length = 0;
3455
3456         if (GET_DWORD(parms[0].info) != _DI_MANU_ID) {
3457                 Info = _WRONG_MESSAGE_FORMAT;
3458         }
3459         command = GET_WORD(parms[1].info);
3460         m = &parms[2];
3461         if (!Info)
3462         {
3463                 switch (command) {
3464                 case _DI_ASSIGN_PLCI:
3465                         if (api_parse(&m->info[1], (word)m->length, "wbbs", m_parms)) {
3466                                 Info = _WRONG_MESSAGE_FORMAT;
3467                                 break;
3468                         }
3469                         codec = GET_WORD(m_parms[0].info);
3470                         ch = m_parms[1].info[0];
3471                         dir = m_parms[2].info[0];
3472                         if ((i = get_plci(a))) {
3473                                 plci = &a->plci[i - 1];
3474                                 plci->appl = appl;
3475                                 plci->command = _MANUFACTURER_R;
3476                                 plci->m_command = command;
3477                                 plci->number = Number;
3478                                 plci->State = LOCAL_CONNECT;
3479                                 Id = (((word)plci->Id << 8) | plci->adapter->Id | 0x80);
3480                                 dbug(1, dprintf("ManCMD,plci=0x%x", Id));
3481
3482                                 if ((ch == 1 || ch == 2) && (dir <= 2)) {
3483                                         chi[1] = (byte)(0x80 | ch);
3484                                         lli[1] = 0;
3485                                         plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3486                                         switch (codec)
3487                                         {
3488                                         case 0:
3489                                                 Info = add_b1(plci, &m_parms[3], 0, 0);
3490                                                 break;
3491                                         case 1:
3492                                                 add_p(plci, CAI, codec_cai);
3493                                                 break;
3494                                                 /* manual 'swich on' to the codec support without signalling */
3495                                                 /* first 'assign plci' with this function, then use */
3496                                         case 2:
3497                                                 if (AdvCodecSupport(a, plci, appl, 0)) {
3498                                                         Info = _RESOURCE_ERROR;
3499                                                 }
3500                                                 else {
3501                                                         Info = add_b1(plci, &null_parms, 0, B1_FACILITY_LOCAL);
3502                                                         lli[1] = 0x10; /* local call codec stream */
3503                                                 }
3504                                                 break;
3505                                         }
3506
3507                                         plci->State = LOCAL_CONNECT;
3508                                         plci->manufacturer = true;
3509                                         plci->command = _MANUFACTURER_R;
3510                                         plci->m_command = command;
3511                                         plci->number = Number;
3512
3513                                         if (!Info)
3514                                         {
3515                                                 add_p(plci, LLI, lli);
3516                                                 add_p(plci, CHI, chi);
3517                                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
3518                                                 sig_req(plci, ASSIGN, DSIG_ID);
3519
3520                                                 if (!codec)
3521                                                 {
3522                                                         Info = add_b23(plci, &m_parms[3]);
3523                                                         if (!Info)
3524                                                         {
3525                                                                 nl_req_ncci(plci, ASSIGN, 0);
3526                                                                 send_req(plci);
3527                                                         }
3528                                                 }
3529                                                 if (!Info)
3530                                                 {
3531                                                         dbug(1, dprintf("dir=0x%x,spoof=0x%x", dir, plci->spoofed_msg));
3532                                                         if (plci->spoofed_msg == SPOOFING_REQUIRED)
3533                                                         {
3534                                                                 api_save_msg(m_parms, "wbbs", &plci->saved_msg);
3535                                                                 plci->spoofed_msg = AWAITING_MANUF_CON;
3536                                                                 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3537                                                                 plci->command = 0;
3538                                                                 send_req(plci);
3539                                                                 return false;
3540                                                         }
3541                                                         if (dir == 1) {
3542                                                                 sig_req(plci, CALL_REQ, 0);
3543                                                         }
3544                                                         else if (!dir) {
3545                                                                 sig_req(plci, LISTEN_REQ, 0);
3546                                                         }
3547                                                         send_req(plci);
3548                                                 }
3549                                                 else
3550                                                 {
3551                                                         sendf(appl,
3552                                                               _MANUFACTURER_R | CONFIRM,
3553                                                               Id,
3554                                                               Number,
3555                                                               "dww", _DI_MANU_ID, command, Info);
3556                                                         return 2;
3557                                                 }
3558                                         }
3559                                 }
3560                         }
3561                         else  Info = _OUT_OF_PLCI;
3562                         break;
3563
3564                 case _DI_IDI_CTRL:
3565                         if (!plci)
3566                         {
3567                                 Info = _WRONG_IDENTIFIER;
3568                                 break;
3569                         }
3570                         if (api_parse(&m->info[1], (word)m->length, "bs", m_parms)) {
3571                                 Info = _WRONG_MESSAGE_FORMAT;
3572                                 break;
3573                         }
3574                         req = m_parms[0].info[0];
3575                         plci->command = _MANUFACTURER_R;
3576                         plci->m_command = command;
3577                         plci->number = Number;
3578                         if (req == CALL_REQ)
3579                         {
3580                                 plci->b_channel = getChannel(&m_parms[1]);
3581                                 mixer_set_bchannel_id_esc(plci, plci->b_channel);
3582                                 if (plci->spoofed_msg == SPOOFING_REQUIRED)
3583                                 {
3584                                         plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3585                                         plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3586                                         plci->command = 0;
3587                                         break;
3588                                 }
3589                         }
3590                         else if (req == LAW_REQ)
3591                         {
3592                                 plci->cr_enquiry = true;
3593                         }
3594                         add_ss(plci, FTY, &m_parms[1]);
3595                         sig_req(plci, req, 0);
3596                         send_req(plci);
3597                         if (req == HANGUP)
3598                         {
3599                                 if (plci->NL.Id && !plci->nl_remove_id)
3600                                 {
3601                                         if (plci->channels)
3602                                         {
3603                                                 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
3604                                                 {
3605                                                         if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3606                                                         {
3607                                                                 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3608                                                                 cleanup_ncci_data(plci, ncci);
3609                                                                 nl_req_ncci(plci, N_DISC, (byte)ncci);
3610                                                         }
3611                                                 }
3612                                         }
3613                                         mixer_remove(plci);
3614                                         nl_req_ncci(plci, REMOVE, 0);
3615                                         send_req(plci);
3616                                 }
3617                         }
3618                         break;
3619
3620                 case _DI_SIG_CTRL:
3621                         /* signalling control for loop activation B-channel */
3622                         if (!plci)
3623                         {
3624                                 Info = _WRONG_IDENTIFIER;
3625                                 break;
3626                         }
3627                         if (m->length) {
3628                                 plci->command = _MANUFACTURER_R;
3629                                 plci->number = Number;
3630                                 add_ss(plci, FTY, m);
3631                                 sig_req(plci, SIG_CTRL, 0);
3632                                 send_req(plci);
3633                         }
3634                         else Info = _WRONG_MESSAGE_FORMAT;
3635                         break;
3636
3637                 case _DI_RXT_CTRL:
3638                         /* activation control for receiver/transmitter B-channel */
3639                         if (!plci)
3640                         {
3641                                 Info = _WRONG_IDENTIFIER;
3642                                 break;
3643                         }
3644                         if (m->length) {
3645                                 plci->command = _MANUFACTURER_R;
3646                                 plci->number = Number;
3647                                 add_ss(plci, FTY, m);
3648                                 sig_req(plci, DSP_CTRL, 0);
3649                                 send_req(plci);
3650                         }
3651                         else Info = _WRONG_MESSAGE_FORMAT;
3652                         break;
3653
3654                 case _DI_ADV_CODEC:
3655                 case _DI_DSP_CTRL:
3656                         /* TEL_CTRL commands to support non standard adjustments: */
3657                         /* Ring on/off, Handset micro volume, external micro vol. */
3658                         /* handset+external speaker volume, receiver+transm. gain,*/
3659                         /* handsfree on (hookinfo off), set mixer command         */
3660
3661                         if (command == _DI_ADV_CODEC)
3662                         {
3663                                 if (!a->AdvCodecPLCI) {
3664                                         Info = _WRONG_STATE;
3665                                         break;
3666                                 }
3667                                 v_plci = a->AdvCodecPLCI;
3668                         }
3669                         else
3670                         {
3671                                 if (plci
3672                                     && (m->length >= 3)
3673                                     && (m->info[1] == 0x1c)
3674                                     && (m->info[2] >= 1))
3675                                 {
3676                                         if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3677                                         {
3678                                                 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3679                                                 {
3680                                                         Info = _WRONG_STATE;
3681                                                         break;
3682                                                 }
3683                                                 a->adv_voice_coef_length = m->info[2] - 1;
3684                                                 if (a->adv_voice_coef_length > m->length - 3)
3685                                                         a->adv_voice_coef_length = (byte)(m->length - 3);
3686                                                 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3687                                                         a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3688                                                 for (i = 0; i < a->adv_voice_coef_length; i++)
3689                                                         a->adv_voice_coef_buffer[i] = m->info[4 + i];
3690                                                 if (plci->B1_facilities & B1_FACILITY_VOICE)
3691                                                         adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
3692                                                 break;
3693                                         }
3694                                         else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3695                                         {
3696                                                 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3697                                                 {
3698                                                         Info = _FACILITY_NOT_SUPPORTED;
3699                                                         break;
3700                                                 }
3701
3702                                                 plci->dtmf_parameter_length = m->info[2] - 1;
3703                                                 if (plci->dtmf_parameter_length > m->length - 3)
3704                                                         plci->dtmf_parameter_length = (byte)(m->length - 3);
3705                                                 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3706                                                         plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3707                                                 for (i = 0; i < plci->dtmf_parameter_length; i++)
3708                                                         plci->dtmf_parameter_buffer[i] = m->info[4 + i];
3709                                                 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3710                                                         dtmf_parameter_write(plci);
3711                                                 break;
3712
3713                                         }
3714                                 }
3715                                 v_plci = plci;
3716                         }
3717
3718                         if (!v_plci)
3719                         {
3720                                 Info = _WRONG_IDENTIFIER;
3721                                 break;
3722                         }
3723                         if (m->length) {
3724                                 add_ss(v_plci, FTY, m);
3725                                 sig_req(v_plci, TEL_CTRL, 0);
3726                                 send_req(v_plci);
3727                         }
3728                         else Info = _WRONG_MESSAGE_FORMAT;
3729
3730                         break;
3731
3732                 case _DI_OPTIONS_REQUEST:
3733                         if (api_parse(&m->info[1], (word)m->length, "d", m_parms)) {
3734                                 Info = _WRONG_MESSAGE_FORMAT;
3735                                 break;
3736                         }
3737                         if (GET_DWORD(m_parms[0].info) & ~a->man_profile.private_options)
3738                         {
3739                                 Info = _FACILITY_NOT_SUPPORTED;
3740                                 break;
3741                         }
3742                         a->requested_options_table[appl->Id - 1] = GET_DWORD(m_parms[0].info);
3743                         break;
3744
3745
3746
3747                 default:
3748                         Info = _WRONG_MESSAGE_FORMAT;
3749                         break;
3750                 }
3751         }
3752
3753         sendf(appl,
3754               _MANUFACTURER_R | CONFIRM,
3755               Id,
3756               Number,
3757               "dww", _DI_MANU_ID, command, Info);
3758         return false;
3759 }
3760
3761
3762 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3763                              PLCI *plci, APPL *appl, API_PARSE *msg)
3764 {
3765         word indication;
3766
3767         API_PARSE m_parms[3];
3768         API_PARSE *ncpi;
3769         API_PARSE fax_parms[9];
3770         word i;
3771         byte len;
3772
3773
3774         dbug(1, dprintf("manufacturer_res"));
3775
3776         if ((msg[0].length == 0)
3777             || (msg[1].length == 0)
3778             || (GET_DWORD(msg[0].info) != _DI_MANU_ID))
3779         {
3780                 return false;
3781         }
3782         indication = GET_WORD(msg[1].info);
3783         switch (indication)
3784         {
3785
3786         case _DI_NEGOTIATE_B3:
3787                 if (!plci)
3788                         break;
3789                 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3790                     || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3791                 {
3792                         dbug(1, dprintf("wrong state for NEGOTIATE_B3 parameters"));
3793                         break;
3794                 }
3795                 if (api_parse(&msg[2].info[1], msg[2].length, "ws", m_parms))
3796                 {
3797                         dbug(1, dprintf("wrong format in NEGOTIATE_B3 parameters"));
3798                         break;
3799                 }
3800                 ncpi = &m_parms[1];
3801                 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
3802                 if (plci->fax_connect_info_length < len)
3803                 {
3804                         ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3805                         ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3806                 }
3807                 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3808                 {
3809                         dbug(1, dprintf("non-standard facilities info missing or wrong format"));
3810                 }
3811                 else
3812                 {
3813                         if (plci->fax_connect_info_length <= len)
3814                                 plci->fax_connect_info_buffer[len] = 0;
3815                         len += 1 + plci->fax_connect_info_buffer[len];
3816                         if (plci->fax_connect_info_length <= len)
3817                                 plci->fax_connect_info_buffer[len] = 0;
3818                         len += 1 + plci->fax_connect_info_buffer[len];
3819                         if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3820                                 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3821                         plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3822                         for (i = 0; i < fax_parms[7].length; i++)
3823                                 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
3824                 }
3825                 plci->fax_connect_info_length = len;
3826                 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3827                 start_internal_command(Id, plci, fax_edata_ack_command);
3828                 break;
3829
3830         }
3831         return false;
3832 }
3833
3834 /*------------------------------------------------------------------*/
3835 /* IDI callback function                                            */
3836 /*------------------------------------------------------------------*/
3837
3838 void callback(ENTITY *e)
3839 {
3840         DIVA_CAPI_ADAPTER *a;
3841         APPL *appl;
3842         PLCI *plci;
3843         CAPI_MSG *m;
3844         word i, j;
3845         byte rc;
3846         byte ch;
3847         byte req;
3848         byte global_req;
3849         int no_cancel_rc;
3850
3851         dbug(1, dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3852                         (e->user[0] + 1) & 0x7fff, e->Id, e->Req, e->Rc, e->Ind));
3853
3854         a = &(adapter[(byte)e->user[0]]);
3855         plci = &(a->plci[e->user[1]]);
3856         no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3857
3858         /*
3859           If new protocol code and new XDI is used then CAPI should work
3860           fully in accordance with IDI cpec an look on callback field instead
3861           of Rc field for return codes.
3862         */
3863         if (((e->complete == 0xff) && no_cancel_rc) ||
3864             (e->Rc && !no_cancel_rc)) {
3865                 rc = e->Rc;
3866                 ch = e->RcCh;
3867                 req = e->Req;
3868                 e->Rc = 0;
3869
3870                 if (e->user[0] & 0x8000)
3871                 {
3872                         /*
3873                           If REMOVE request was sent then we have to wait until
3874                           return code with Id set to zero arrives.
3875                           All other return codes should be ignored.
3876                         */
3877                         if (req == REMOVE)
3878                         {
3879                                 if (e->Id)
3880                                 {
3881                                         dbug(1, dprintf("cancel RC in REMOVE state"));
3882                                         return;
3883                                 }
3884                                 channel_flow_control_remove(plci);
3885                                 for (i = 0; i < 256; i++)
3886                                 {
3887                                         if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3888                                                 a->FlowControlIdTable[i] = 0;
3889                                 }
3890                                 plci->nl_remove_id = 0;
3891                                 if (plci->rx_dma_descriptor > 0) {
3892                                         diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3893                                         plci->rx_dma_descriptor = 0;
3894                                 }
3895                         }
3896                         if (rc == OK_FC)
3897                         {
3898                                 a->FlowControlIdTable[ch] = e->Id;
3899                                 a->FlowControlSkipTable[ch] = 0;
3900
3901                                 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3902                                 a->ch_flow_plci[ch] = plci->Id;
3903                                 plci->nl_req = 0;
3904                         }
3905                         else
3906                         {
3907                                 /*
3908                                   Cancel return codes self, if feature was requested
3909                                 */
3910                                 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3911                                         a->FlowControlIdTable[ch] = 0;
3912                                         if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3913                                                 dbug(3, dprintf("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3914                                                 return;
3915                                         }
3916                                 }
3917
3918                                 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3919                                 {
3920                                         a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3921                                         if (ch == e->ReqCh)
3922                                                 plci->nl_req = 0;
3923                                 }
3924                                 else
3925                                         plci->nl_req = 0;
3926                         }
3927                         if (plci->nl_req)
3928                                 control_rc(plci, 0, rc, ch, 0, true);
3929                         else
3930                         {
3931                                 if (req == N_XON)
3932                                 {
3933                                         channel_x_on(plci, ch);
3934                                         if (plci->internal_command)
3935                                                 control_rc(plci, req, rc, ch, 0, true);
3936                                 }
3937                                 else
3938                                 {
3939                                         if (plci->nl_global_req)
3940                                         {
3941                                                 global_req = plci->nl_global_req;
3942                                                 plci->nl_global_req = 0;
3943                                                 if (rc != ASSIGN_OK) {
3944                                                         e->Id = 0;
3945                                                         if (plci->rx_dma_descriptor > 0) {
3946                                                                 diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3947                                                                 plci->rx_dma_descriptor = 0;
3948                                                         }
3949                                                 }
3950                                                 channel_xmit_xon(plci);
3951                                                 control_rc(plci, 0, rc, ch, global_req, true);
3952                                         }
3953                                         else if (plci->data_sent)
3954                                         {
3955                                                 channel_xmit_xon(plci);
3956                                                 plci->data_sent = false;
3957                                                 plci->NL.XNum = 1;
3958                                                 data_rc(plci, ch);
3959                                                 if (plci->internal_command)
3960                                                         control_rc(plci, req, rc, ch, 0, true);
3961                                         }
3962                                         else
3963                                         {
3964                                                 channel_xmit_xon(plci);
3965                                                 control_rc(plci, req, rc, ch, 0, true);
3966                                         }
3967                                 }
3968                         }
3969                 }
3970                 else
3971                 {
3972                         /*
3973                           If REMOVE request was sent then we have to wait until
3974                           return code with Id set to zero arrives.
3975                           All other return codes should be ignored.
3976                         */
3977                         if (req == REMOVE)
3978                         {
3979                                 if (e->Id)
3980                                 {
3981                                         dbug(1, dprintf("cancel RC in REMOVE state"));
3982                                         return;
3983                                 }
3984                                 plci->sig_remove_id = 0;
3985                         }
3986                         plci->sig_req = 0;
3987                         if (plci->sig_global_req)
3988                         {
3989                                 global_req = plci->sig_global_req;
3990                                 plci->sig_global_req = 0;
3991                                 if (rc != ASSIGN_OK)
3992                                         e->Id = 0;
3993                                 channel_xmit_xon(plci);
3994                                 control_rc(plci, 0, rc, ch, global_req, false);
3995                         }
3996                         else
3997                         {
3998                                 channel_xmit_xon(plci);
3999                                 control_rc(plci, req, rc, ch, 0, false);
4000                         }
4001                 }
4002                 /*
4003                   Again: in accordance with IDI spec Rc and Ind can't be delivered in the
4004                   same callback. Also if new XDI and protocol code used then jump
4005                   direct to finish.
4006                 */
4007                 if (no_cancel_rc) {
4008                         channel_xmit_xon(plci);
4009                         goto capi_callback_suffix;
4010                 }
4011         }
4012
4013         channel_xmit_xon(plci);
4014
4015         if (e->Ind) {
4016                 if (e->user[0] & 0x8000) {
4017                         byte Ind = e->Ind & 0x0f;
4018                         byte Ch = e->IndCh;
4019                         if (((Ind == N_DISC) || (Ind == N_DISC_ACK)) &&
4020                             (a->ch_flow_plci[Ch] == plci->Id)) {
4021                                 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4022                                         dbug(3, dprintf("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4023                                 }
4024                                 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4025                         }
4026                         nl_ind(plci);
4027                         if ((e->RNR != 1) &&
4028                             (a->ch_flow_plci[Ch] == plci->Id) &&
4029                             (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4030                                 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4031                                 dbug(3, dprintf("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4032                         }
4033                 } else {
4034                         sig_ind(plci);
4035                 }
4036                 e->Ind = 0;
4037         }
4038
4039 capi_callback_suffix:
4040
4041         while (!plci->req_in
4042                && !plci->internal_command
4043                && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4044         {
4045                 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4046
4047                 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4048
4049                 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4050                 appl = *((APPL **)(&((byte *)(plci->msg_in_queue))[j + i]));
4051                 dbug(1, dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4052                                 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4053                 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4054                 {
4055                         plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4056                         plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4057                 }
4058                 else
4059                 {
4060                         plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4061                 }
4062                 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4063                 {
4064                         plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4065                         plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4066                 }
4067                 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4068                 {
4069                         plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4070                         plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4071                 }
4072                 i = api_put(appl, m);
4073                 if (i != 0)
4074                 {
4075                         if (m->header.command == _DATA_B3_R)
4076
4077                                 TransmitBufferFree(appl, (byte *)(long)(m->info.data_b3_req.Data));
4078
4079                         dbug(1, dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4080                         break;
4081                 }
4082
4083                 if (plci->li_notify_update)
4084                 {
4085                         plci->li_notify_update = false;
4086                         mixer_notify_update(plci, false);
4087                 }
4088
4089         }
4090         send_data(plci);
4091         send_req(plci);
4092 }
4093
4094
4095 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4096                        byte nl_rc)
4097 {
4098         dword Id;
4099         dword rId;
4100         word Number;
4101         word Info = 0;
4102         word i;
4103         word ncci;
4104         DIVA_CAPI_ADAPTER *a;
4105         APPL *appl;
4106         PLCI *rplci;
4107         byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4108         byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4109
4110         if (!plci) {
4111                 dbug(0, dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4112                 return;
4113         }
4114         dbug(1, dprintf("req0_in/out=%d/%d", plci->req_in, plci->req_out));
4115         if (plci->req_in != plci->req_out)
4116         {
4117                 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4118                 {
4119                         dbug(1, dprintf("req_1return"));
4120                         return;
4121                 }
4122                 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4123         }
4124         plci->req_in = plci->req_in_start = plci->req_out = 0;
4125         dbug(1, dprintf("control_rc"));
4126
4127         appl = plci->appl;
4128         a = plci->adapter;
4129         ncci = a->ch_ncci[ch];
4130         if (appl)
4131         {
4132                 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4133                 if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4134                 Number = plci->number;
4135                 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));
4136                 dbug(1, dprintf("channels=0x%x", plci->channels));
4137                 if (plci_remove_check(plci))
4138                         return;
4139                 if (req == REMOVE && rc == ASSIGN_OK)
4140                 {
4141                         sig_req(plci, HANGUP, 0);
4142                         sig_req(plci, REMOVE, 0);
4143                         send_req(plci);
4144                 }
4145                 if (plci->command)
4146                 {
4147                         switch (plci->command)
4148                         {
4149                         case C_HOLD_REQ:
4150                                 dbug(1, dprintf("HoldRC=0x%x", rc));
4151                                 SSparms[1] = (byte)S_HOLD;
4152                                 if (rc != OK)
4153                                 {
4154                                         plci->SuppState = IDLE;
4155                                         Info = 0x2001;
4156                                 }
4157                                 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4158                                 break;
4159
4160                         case C_RETRIEVE_REQ:
4161                                 dbug(1, dprintf("RetrieveRC=0x%x", rc));
4162                                 SSparms[1] = (byte)S_RETRIEVE;
4163                                 if (rc != OK)
4164                                 {
4165                                         plci->SuppState = CALL_HELD;
4166                                         Info = 0x2001;
4167                                 }
4168                                 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4169                                 break;
4170
4171                         case _INFO_R:
4172                                 dbug(1, dprintf("InfoRC=0x%x", rc));
4173                                 if (rc != OK) Info = _WRONG_STATE;
4174                                 sendf(appl, _INFO_R | CONFIRM, Id, Number, "w", Info);
4175                                 break;
4176
4177                         case _CONNECT_R:
4178                                 dbug(1, dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x", req, rc, global_req, nl_rc));
4179                                 if (plci->State == INC_DIS_PENDING)
4180                                         break;
4181                                 if (plci->Sig.Id != 0xff)
4182                                 {
4183                                         if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4184                                             || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4185                                         {
4186                                                 dbug(1, dprintf("No more IDs/Call_Req failed"));
4187                                                 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4188                                                 plci_remove(plci);
4189                                                 plci->State = IDLE;
4190                                                 break;
4191                                         }
4192                                         if (plci->State != LOCAL_CONNECT) plci->State = OUTG_CON_PENDING;
4193                                         sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4194                                 }
4195                                 else /* D-ch activation */
4196                                 {
4197                                         if (rc != ASSIGN_OK)
4198                                         {
4199                                                 dbug(1, dprintf("No more IDs/X.25 Call_Req failed"));
4200                                                 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4201                                                 plci_remove(plci);
4202                                                 plci->State = IDLE;
4203                                                 break;
4204                                         }
4205                                         sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4206                                         sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "sss", "", "", "");
4207                                         plci->State = INC_ACT_PENDING;
4208                                 }
4209                                 break;
4210
4211                         case _CONNECT_I | RESPONSE:
4212                                 if (plci->State != INC_DIS_PENDING)
4213                                         plci->State = INC_CON_ACCEPT;
4214                                 break;
4215
4216                         case _DISCONNECT_R:
4217                                 if (plci->State == INC_DIS_PENDING)
4218                                         break;
4219                                 if (plci->Sig.Id != 0xff)
4220                                 {
4221                                         plci->State = OUTG_DIS_PENDING;
4222                                         sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
4223                                 }
4224                                 break;
4225
4226                         case SUSPEND_REQ:
4227                                 break;
4228
4229                         case RESUME_REQ:
4230                                 break;
4231
4232                         case _CONNECT_B3_R:
4233                                 if (rc != OK)
4234                                 {
4235                                         sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
4236                                         break;
4237                                 }
4238                                 ncci = get_ncci(plci, ch, 0);
4239                                 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4240                                 plci->channels++;
4241                                 if (req == N_RESET)
4242                                 {
4243                                         a->ncci_state[ncci] = INC_ACT_PENDING;
4244                                         sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4245                                         sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
4246                                 }
4247                                 else
4248                                 {
4249                                         a->ncci_state[ncci] = OUTG_CON_PENDING;
4250                                         sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4251                                 }
4252                                 break;
4253
4254                         case _CONNECT_B3_I | RESPONSE:
4255                                 break;
4256
4257                         case _RESET_B3_R:
4258 /*        sendf(appl, _RESET_B3_R | CONFIRM, Id, Number, "w", 0);*/
4259                                 break;
4260
4261                         case _DISCONNECT_B3_R:
4262                                 sendf(appl, _DISCONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4263                                 break;
4264
4265                         case _MANUFACTURER_R:
4266                                 break;
4267
4268                         case PERM_LIST_REQ:
4269                                 if (rc != OK)
4270                                 {
4271                                         Info = _WRONG_IDENTIFIER;
4272                                         sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4273                                         plci_remove(plci);
4274                                 }
4275                                 else
4276                                         sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4277                                 break;
4278
4279                         default:
4280                                 break;
4281                         }
4282                         plci->command = 0;
4283                 }
4284                 else if (plci->internal_command)
4285                 {
4286                         switch (plci->internal_command)
4287                         {
4288                         case BLOCK_PLCI:
4289                                 return;
4290
4291                         case GET_MWI_STATE:
4292                                 if (rc == OK) /* command supported, wait for indication */
4293                                 {
4294                                         return;
4295                                 }
4296                                 plci_remove(plci);
4297                                 break;
4298
4299                                 /* Get Supported Services */
4300                         case GETSERV_REQ_PEND:
4301                                 if (rc == OK) /* command supported, wait for indication */
4302                                 {
4303                                         break;
4304                                 }
4305                                 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4306                                 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", 0, 3, SSstruct);
4307                                 plci_remove(plci);
4308                                 break;
4309
4310                         case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
4311                         case INTERR_NUMBERS_REQ_PEND:
4312                         case CF_START_PEND:                  /* Call Forwarding Start pending */
4313                         case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
4314                         case CCBS_REQUEST_REQ_PEND:
4315                         case CCBS_DEACTIVATE_REQ_PEND:
4316                         case CCBS_INTERROGATE_REQ_PEND:
4317                                 switch (plci->internal_command)
4318                                 {
4319                                 case INTERR_DIVERSION_REQ_PEND:
4320                                         SSparms[1] = S_INTERROGATE_DIVERSION;
4321                                         break;
4322                                 case INTERR_NUMBERS_REQ_PEND:
4323                                         SSparms[1] = S_INTERROGATE_NUMBERS;
4324                                         break;
4325                                 case CF_START_PEND:
4326                                         SSparms[1] = S_CALL_FORWARDING_START;
4327                                         break;
4328                                 case CF_STOP_PEND:
4329                                         SSparms[1] = S_CALL_FORWARDING_STOP;
4330                                         break;
4331                                 case CCBS_REQUEST_REQ_PEND:
4332                                         SSparms[1] = S_CCBS_REQUEST;
4333                                         break;
4334                                 case CCBS_DEACTIVATE_REQ_PEND:
4335                                         SSparms[1] = S_CCBS_DEACTIVATE;
4336                                         break;
4337                                 case CCBS_INTERROGATE_REQ_PEND:
4338                                         SSparms[1] = S_CCBS_INTERROGATE;
4339                                         break;
4340                                 }
4341                                 if (global_req == ASSIGN)
4342                                 {
4343                                         dbug(1, dprintf("AssignDiversion_RC=0x%x/0x%x", req, rc));
4344                                         return;
4345                                 }
4346                                 if (!plci->appl) break;
4347                                 if (rc == ISDN_GUARD_REJ)
4348                                 {
4349                                         Info = _CAPI_GUARD_ERROR;
4350                                 }
4351                                 else if (rc != OK)
4352                                 {
4353                                         Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4354                                 }
4355                                 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7,
4356                                       plci->number, "wws", Info, (word)3, SSparms);
4357                                 if (Info) plci_remove(plci);
4358                                 break;
4359
4360                                 /* 3pty conference pending */
4361                         case PTY_REQ_PEND:
4362                                 if (!plci->relatedPTYPLCI) break;
4363                                 rplci = plci->relatedPTYPLCI;
4364                                 SSparms[1] = plci->ptyState;
4365                                 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4366                                 if (rplci->tel) rId |= EXT_CONTROLLER;
4367                                 if (rc != OK)
4368                                 {
4369                                         Info = 0x300E; /* not supported */
4370                                         plci->relatedPTYPLCI = NULL;
4371                                         plci->ptyState = 0;
4372                                 }
4373                                 sendf(rplci->appl,
4374                                       _FACILITY_R | CONFIRM,
4375                                       rId,
4376                                       plci->number,
4377                                       "wws", Info, (word)3, SSparms);
4378                                 break;
4379
4380                                 /* Explicit Call Transfer pending */
4381                         case ECT_REQ_PEND:
4382                                 dbug(1, dprintf("ECT_RC=0x%x/0x%x", req, rc));
4383                                 if (!plci->relatedPTYPLCI) break;
4384                                 rplci = plci->relatedPTYPLCI;
4385                                 SSparms[1] = S_ECT;
4386                                 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4387                                 if (rplci->tel) rId |= EXT_CONTROLLER;
4388                                 if (rc != OK)
4389                                 {
4390                                         Info = 0x300E; /* not supported */
4391                                         plci->relatedPTYPLCI = NULL;
4392                                         plci->ptyState = 0;
4393                                 }
4394                                 sendf(rplci->appl,
4395                                       _FACILITY_R | CONFIRM,
4396                                       rId,
4397                                       plci->number,
4398                                       "wws", Info, (word)3, SSparms);
4399                                 break;
4400
4401                         case _MANUFACTURER_R:
4402                                 dbug(1, dprintf("_Manufacturer_R=0x%x/0x%x", req, rc));
4403                                 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4404                                 {
4405                                         dbug(1, dprintf("No more IDs"));
4406                                         sendf(appl, _MANUFACTURER_R | CONFIRM, Id, Number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
4407                                         plci_remove(plci);  /* after codec init, internal codec commands pending */
4408                                 }
4409                                 break;
4410
4411                         case _CONNECT_R:
4412                                 dbug(1, dprintf("_Connect_R=0x%x/0x%x", req, rc));
4413                                 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4414                                 {
4415                                         dbug(1, dprintf("No more IDs"));
4416                                         sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4417                                         plci_remove(plci);  /* after codec init, internal codec commands pending */
4418                                 }
4419                                 break;
4420
4421                         case PERM_COD_HOOK:                     /* finished with Hook_Ind */
4422                                 return;
4423
4424                         case PERM_COD_CALL:
4425                                 dbug(1, dprintf("***Codec Connect_Pending A, Rc = 0x%x", rc));
4426                                 plci->internal_command = PERM_COD_CONN_PEND;
4427                                 return;
4428
4429                         case PERM_COD_ASSIGN:
4430                                 dbug(1, dprintf("***Codec Assign A, Rc = 0x%x", rc));
4431                                 if (rc != ASSIGN_OK) break;
4432                                 sig_req(plci, CALL_REQ, 0);
4433                                 send_req(plci);
4434                                 plci->internal_command = PERM_COD_CALL;
4435                                 return;
4436
4437                                 /* Null Call Reference Request pending */
4438                         case C_NCR_FAC_REQ:
4439                                 dbug(1, dprintf("NCR_FAC=0x%x/0x%x", req, rc));
4440                                 if (global_req == ASSIGN)
4441                                 {
4442                                         if (rc == ASSIGN_OK)
4443                                         {
4444                                                 return;
4445                                         }
4446                                         else
4447                                         {
4448                                                 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4449                                                 appl->NullCREnable = false;
4450                                                 plci_remove(plci);
4451                                         }
4452                                 }
4453                                 else if (req == NCR_FACILITY)
4454                                 {
4455                                         if (rc == OK)
4456                                         {
4457                                                 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", 0);
4458                                         }
4459                                         else
4460                                         {
4461                                                 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4462                                                 appl->NullCREnable = false;
4463                                         }
4464                                         plci_remove(plci);
4465                                 }
4466                                 break;
4467
4468                         case HOOK_ON_REQ:
4469                                 if (plci->channels)
4470                                 {
4471                                         if (a->ncci_state[ncci] == CONNECTED)
4472                                         {
4473                                                 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4474                                                 cleanup_ncci_data(plci, ncci);
4475                                                 nl_req_ncci(plci, N_DISC, (byte)ncci);
4476                                         }
4477                                         break;
4478                                 }
4479                                 break;
4480
4481                         case HOOK_OFF_REQ:
4482                                 if (plci->State == INC_DIS_PENDING)
4483                                         break;
4484                                 sig_req(plci, CALL_REQ, 0);
4485                                 send_req(plci);
4486                                 plci->State = OUTG_CON_PENDING;
4487                                 break;
4488
4489
4490                         case MWI_ACTIVATE_REQ_PEND:
4491                         case MWI_DEACTIVATE_REQ_PEND:
4492                                 if (global_req == ASSIGN && rc == ASSIGN_OK)
4493                                 {
4494                                         dbug(1, dprintf("MWI_REQ assigned"));
4495                                         return;
4496                                 }
4497                                 else if (rc != OK)
4498                                 {
4499                                         if (rc == WRONG_IE)
4500                                         {
4501                                                 Info = 0x2007; /* Illegal message parameter coding */
4502                                                 dbug(1, dprintf("MWI_REQ invalid parameter"));
4503                                         }
4504                                         else
4505                                         {
4506                                                 Info = 0x300B; /* not supported */
4507                                                 dbug(1, dprintf("MWI_REQ not supported"));
4508                                         }
4509                                         /* 0x3010: Request not allowed in this state */
4510                                         PUT_WORD(&SSparms[4], 0x300E); /* SS not supported */
4511
4512                                 }
4513                                 if (plci->internal_command == MWI_ACTIVATE_REQ_PEND)
4514                                 {
4515                                         PUT_WORD(&SSparms[1], S_MWI_ACTIVATE);
4516                                 }
4517                                 else PUT_WORD(&SSparms[1], S_MWI_DEACTIVATE);
4518
4519                                 if (plci->cr_enquiry)
4520                                 {
4521                                         sendf(plci->appl,
4522                                               _FACILITY_R | CONFIRM,
4523                                               Id & 0xf,
4524                                               plci->number,
4525                                               "wws", Info, (word)3, SSparms);
4526                                         if (rc != OK) plci_remove(plci);
4527                                 }
4528                                 else
4529                                 {
4530                                         sendf(plci->appl,
4531                                               _FACILITY_R | CONFIRM,
4532                                               Id,
4533                                               plci->number,
4534                                               "wws", Info, (word)3, SSparms);
4535                                 }
4536                                 break;
4537
4538                         case CONF_BEGIN_REQ_PEND:
4539                         case CONF_ADD_REQ_PEND:
4540                         case CONF_SPLIT_REQ_PEND:
4541                         case CONF_DROP_REQ_PEND:
4542                         case CONF_ISOLATE_REQ_PEND:
4543                         case CONF_REATTACH_REQ_PEND:
4544                                 dbug(1, dprintf("CONF_RC=0x%x/0x%x", req, rc));
4545                                 if ((plci->internal_command == CONF_ADD_REQ_PEND) && (!plci->relatedPTYPLCI)) break;
4546                                 rplci = plci;
4547                                 rId = Id;
4548                                 switch (plci->internal_command)
4549                                 {
4550                                 case CONF_BEGIN_REQ_PEND:
4551                                         SSparms[1] = S_CONF_BEGIN;
4552                                         break;
4553                                 case CONF_ADD_REQ_PEND:
4554                                         SSparms[1] = S_CONF_ADD;
4555                                         rplci = plci->relatedPTYPLCI;
4556                                         rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4557                                         break;
4558                                 case CONF_SPLIT_REQ_PEND:
4559                                         SSparms[1] = S_CONF_SPLIT;
4560                                         break;
4561                                 case CONF_DROP_REQ_PEND:
4562                                         SSparms[1] = S_CONF_DROP;
4563                                         break;
4564                                 case CONF_ISOLATE_REQ_PEND:
4565                                         SSparms[1] = S_CONF_ISOLATE;
4566                                         break;
4567                                 case CONF_REATTACH_REQ_PEND:
4568                                         SSparms[1] = S_CONF_REATTACH;
4569                                         break;
4570                                 }
4571
4572                                 if (rc != OK)
4573                                 {
4574                                         Info = 0x300E; /* not supported */
4575                                         plci->relatedPTYPLCI = NULL;
4576                                         plci->ptyState = 0;
4577                                 }
4578                                 sendf(rplci->appl,
4579                                       _FACILITY_R | CONFIRM,
4580                                       rId,
4581                                       plci->number,
4582                                       "wws", Info, (word)3, SSparms);
4583                                 break;
4584
4585                         case VSWITCH_REQ_PEND:
4586                                 if (rc != OK)
4587                                 {
4588                                         if (plci->relatedPTYPLCI)
4589                                         {
4590                                                 plci->relatedPTYPLCI->vswitchstate = 0;
4591                                                 plci->relatedPTYPLCI->vsprot = 0;
4592                                                 plci->relatedPTYPLCI->vsprotdialect = 0;
4593                                         }
4594                                         plci->vswitchstate = 0;
4595                                         plci->vsprot = 0;
4596                                         plci->vsprotdialect = 0;
4597                                 }
4598                                 else
4599                                 {
4600                                         if (plci->relatedPTYPLCI &&
4601                                             plci->vswitchstate == 1 &&
4602                                             plci->relatedPTYPLCI->vswitchstate == 3) /* join complete */
4603                                                 plci->vswitchstate = 3;
4604                                 }
4605                                 break;
4606
4607                                 /* Call Deflection Request pending (SSCT) */
4608                         case CD_REQ_PEND:
4609                                 SSparms[1] = S_CALL_DEFLECTION;
4610                                 if (rc != OK)
4611                                 {
4612                                         Info = 0x300E; /* not supported */
4613                                         plci->appl->CDEnable = 0;
4614                                 }
4615                                 sendf(plci->appl, _FACILITY_R | CONFIRM, Id,
4616                                       plci->number, "wws", Info, (word)3, SSparms);
4617                                 break;
4618
4619                         case RTP_CONNECT_B3_REQ_COMMAND_2:
4620                                 if (rc == OK)
4621                                 {
4622                                         ncci = get_ncci(plci, ch, 0);
4623                                         Id = (Id & 0xffff) | (((dword) ncci) << 16);
4624                                         plci->channels++;
4625                                         a->ncci_state[ncci] = OUTG_CON_PENDING;
4626                                 }
4627
4628                         default:
4629                                 if (plci->internal_command_queue[0])
4630                                 {
4631                                         (*(plci->internal_command_queue[0]))(Id, plci, rc);
4632                                         if (plci->internal_command)
4633                                                 return;
4634                                 }
4635                                 break;
4636                         }
4637                         next_internal_command(Id, plci);
4638                 }
4639         }
4640         else /* appl==0 */
4641         {
4642                 Id = ((word)plci->Id << 8) | plci->adapter->Id;
4643                 if (plci->tel) Id |= EXT_CONTROLLER;
4644
4645                 switch (plci->internal_command)
4646                 {
4647                 case BLOCK_PLCI:
4648                         return;
4649
4650                 case START_L1_SIG_ASSIGN_PEND:
4651                 case REM_L1_SIG_ASSIGN_PEND:
4652                         if (global_req == ASSIGN)
4653                         {
4654                                 break;
4655                         }
4656                         else
4657                         {
4658                                 dbug(1, dprintf("***L1 Req rem PLCI"));
4659                                 plci->internal_command = 0;
4660                                 sig_req(plci, REMOVE, 0);
4661                                 send_req(plci);
4662                         }
4663                         break;
4664
4665                         /* Call Deflection Request pending, just no appl ptr assigned */
4666                 case CD_REQ_PEND:
4667                         SSparms[1] = S_CALL_DEFLECTION;
4668                         if (rc != OK)
4669                         {
4670                                 Info = 0x300E; /* not supported */
4671                         }
4672                         for (i = 0; i < max_appl; i++)
4673                         {
4674                                 if (application[i].CDEnable)
4675                                 {
4676                                         if (!application[i].Id) application[i].CDEnable = 0;
4677                                         else
4678                                         {
4679                                                 sendf(&application[i], _FACILITY_R | CONFIRM, Id,
4680                                                       plci->number, "wws", Info, (word)3, SSparms);
4681                                                 if (Info) application[i].CDEnable = 0;
4682                                         }
4683                                 }
4684                         }
4685                         plci->internal_command = 0;
4686                         break;
4687
4688                 case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4689                         return;
4690
4691                 case PERM_COD_CALL:
4692                         plci->internal_command = PERM_COD_CONN_PEND;
4693                         dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc));
4694                         return;
4695
4696                 case PERM_COD_ASSIGN:
4697                         dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc));
4698                         plci->internal_command = 0;
4699                         if (rc != ASSIGN_OK) break;
4700                         plci->internal_command = PERM_COD_CALL;
4701                         sig_req(plci, CALL_REQ, 0);
4702                         send_req(plci);
4703                         return;
4704
4705                 case LISTEN_SIG_ASSIGN_PEND:
4706                         if (rc == ASSIGN_OK)
4707                         {
4708                                 plci->internal_command = 0;
4709                                 dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci->Sig.Id));
4710                                 add_p(plci, ESC, "\x02\x18\x00");             /* support call waiting */
4711                                 sig_req(plci, INDICATE_REQ, 0);
4712                                 send_req(plci);
4713                         }
4714                         else
4715                         {
4716                                 dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc));
4717                                 a->listen_active--;
4718                                 plci_remove(plci);
4719                                 plci->State = IDLE;
4720                         }
4721                         break;
4722
4723                 case USELAW_REQ:
4724                         if (global_req == ASSIGN)
4725                         {
4726                                 if (rc == ASSIGN_OK)
4727                                 {
4728                                         sig_req(plci, LAW_REQ, 0);
4729                                         send_req(plci);
4730                                         dbug(1, dprintf("Auto-Law assigned"));
4731                                 }
4732                                 else
4733                                 {
4734                                         dbug(1, dprintf("Auto-Law assign failed"));
4735                                         a->automatic_law = 3;
4736                                         plci->internal_command = 0;
4737                                         a->automatic_lawPLCI = NULL;
4738                                 }
4739                                 break;
4740                         }
4741                         else if (req == LAW_REQ && rc == OK)
4742                         {
4743                                 dbug(1, dprintf("Auto-Law initiated"));
4744                                 a->automatic_law = 2;
4745                                 plci->internal_command = 0;
4746                         }
4747                         else
4748                         {
4749                                 dbug(1, dprintf("Auto-Law not supported"));
4750                                 a->automatic_law = 3;
4751                                 plci->internal_command = 0;
4752                                 sig_req(plci, REMOVE, 0);
4753                                 send_req(plci);
4754                                 a->automatic_lawPLCI = NULL;
4755                         }
4756                         break;
4757                 }
4758                 plci_remove_check(plci);
4759         }
4760 }
4761
4762 static void data_rc(PLCI *plci, byte ch)
4763 {
4764         dword Id;
4765         DIVA_CAPI_ADAPTER *a;
4766         NCCI *ncci_ptr;
4767         DATA_B3_DESC *data;
4768         word ncci;
4769
4770         if (plci->appl)
4771         {
4772                 TransmitBufferFree(plci->appl, plci->data_sent_ptr);
4773                 a = plci->adapter;
4774                 ncci = a->ch_ncci[ch];
4775                 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4776                 {
4777                         ncci_ptr = &(a->ncci[ncci]);
4778                         dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr->data_out, ncci_ptr->data_pending));
4779                         if (ncci_ptr->data_pending)
4780                         {
4781                                 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4782                                 if (!(data->Flags & 4) && a->ncci_state[ncci])
4783                                 {
4784                                         Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4785                                         if (plci->tel) Id |= EXT_CONTROLLER;
4786                                         sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, data->Number,
4787                                               "ww", data->Handle, 0);
4788                                 }
4789                                 (ncci_ptr->data_out)++;
4790                                 if (ncci_ptr->data_out == MAX_DATA_B3)
4791                                         ncci_ptr->data_out = 0;
4792                                 (ncci_ptr->data_pending)--;
4793                         }
4794                 }
4795         }
4796 }
4797
4798 static void data_ack(PLCI *plci, byte ch)
4799 {
4800         dword Id;
4801         DIVA_CAPI_ADAPTER *a;
4802         NCCI *ncci_ptr;
4803         word ncci;
4804
4805         a = plci->adapter;
4806         ncci = a->ch_ncci[ch];
4807         ncci_ptr = &(a->ncci[ncci]);
4808         if (ncci_ptr->data_ack_pending)
4809         {
4810                 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4811                 {
4812                         Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4813                         if (plci->tel) Id |= EXT_CONTROLLER;
4814                         sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4815                               "ww", ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle, 0);
4816                 }
4817                 (ncci_ptr->data_ack_out)++;
4818                 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4819                         ncci_ptr->data_ack_out = 0;
4820                 (ncci_ptr->data_ack_pending)--;
4821         }
4822 }
4823
4824 static void sig_ind(PLCI *plci)
4825 {
4826         dword x_Id;
4827         dword Id;
4828         dword rId;
4829         word i;
4830         word cip;
4831         dword cip_mask;
4832         byte *ie;
4833         DIVA_CAPI_ADAPTER *a;
4834         API_PARSE saved_parms[MAX_MSG_PARMS + 1];
4835 #define MAXPARMSIDS 31
4836         byte *parms[MAXPARMSIDS];
4837         byte *add_i[4];
4838         byte *multi_fac_parms[MAX_MULTI_IE];
4839         byte *multi_pi_parms[MAX_MULTI_IE];
4840         byte *multi_ssext_parms[MAX_MULTI_IE];
4841         byte *multi_CiPN_parms[MAX_MULTI_IE];
4842
4843         byte *multi_vswitch_parms[MAX_MULTI_IE];
4844
4845         byte ai_len;
4846         byte *esc_chi = "";
4847         byte *esc_law = "";
4848         byte *pty_cai = "";
4849         byte *esc_cr  = "";
4850         byte *esc_profile = "";
4851
4852         byte facility[256];
4853         PLCI *tplci = NULL;
4854         byte chi[] = "\x02\x18\x01";
4855         byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4856         byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4857         /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4858         /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4859         /* SMSG is situated at the end because its 0 (for compatibility reasons */
4860         /* (see Info_Mask Bit 4, first IE. then the message type)           */
4861         static const word parms_id[] =
4862                 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4863                  UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4864                  RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4865                  CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4866         /* 14 FTY repl by ESC_CHI */
4867         /* 18 PI  repl by ESC_LAW */
4868         /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4869         static const word multi_fac_id[] = {1, FTY};
4870         static const word multi_pi_id[]  = {1, PI};
4871         static const word multi_CiPN_id[]  = {1, OAD};
4872         static const word multi_ssext_id[]  = {1, ESC_SSEXT};
4873
4874         static const word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4875
4876         byte *cau;
4877         word ncci;
4878         byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4879         byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4880         byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4881         byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\x00\x00\x00\x00";
4882         byte force_mt_info = false;
4883         byte dir;
4884         dword d;
4885         word w;
4886
4887         a = plci->adapter;
4888         Id = ((word)plci->Id << 8) | a->Id;
4889         PUT_WORD(&SS_Ind[4], 0x0000);
4890
4891         if (plci->sig_remove_id)
4892         {
4893                 plci->Sig.RNR = 2; /* discard */
4894                 dbug(1, dprintf("SIG discard while remove pending"));
4895                 return;
4896         }
4897         if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4898         dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4899                         Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4900         if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4901         {
4902                 plci->Sig.RNR = 1;
4903                 return;
4904         }
4905         if (plci->Sig.Ind == HANGUP && plci->channels)
4906         {
4907                 plci->Sig.RNR = 1;
4908                 plci->hangup_flow_ctrl_timer++;
4909                 /* recover the network layer after timeout */
4910                 if (plci->hangup_flow_ctrl_timer == 100)
4911                 {
4912                         dbug(1, dprintf("Exceptional disc"));
4913                         plci->Sig.RNR = 0;
4914                         plci->hangup_flow_ctrl_timer = 0;
4915                         for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4916                         {
4917                                 if (a->ncci_plci[ncci] == plci->Id)
4918                                 {
4919                                         cleanup_ncci_data(plci, ncci);
4920                                         if (plci->channels)plci->channels--;
4921                                         if (plci->appl)
4922                                                 sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4923                                 }
4924                         }
4925                         if (plci->appl)
4926                                 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4927                         plci_remove(plci);
4928                         plci->State = IDLE;
4929                 }
4930                 return;
4931         }
4932
4933         /* do first parse the info with no OAD in, because OAD will be converted */
4934         /* first the multiple facility IE, then mult. progress ind.              */
4935         /* then the parameters for the info_ind + conn_ind                       */
4936         IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4937         IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4938         IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4939
4940         IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4941
4942         IndParse(plci, parms_id, parms, 0);
4943         IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4944         esc_chi  = parms[14];
4945         esc_law  = parms[18];
4946         pty_cai  = parms[24];
4947         esc_cr   = parms[25];
4948         esc_profile = parms[27];
4949         if (esc_cr[0] && plci)
4950         {
4951                 if (plci->cr_enquiry && plci->appl)
4952                 {
4953                         plci->cr_enquiry = false;
4954                         /* d = MANU_ID            */
4955                         /* w = m_command          */
4956                         /* b = total length       */
4957                         /* b = indication type    */
4958                         /* b = length of all IEs  */
4959                         /* b = IE1                */
4960                         /* S = IE1 length + cont. */
4961                         /* b = IE2                */
4962                         /* S = IE2 length + cont. */
4963                         sendf(plci->appl,
4964                               _MANUFACTURER_I,
4965                               Id,
4966                               0,
4967                               "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4968                               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);
4969                 }
4970         }
4971         /* create the additional info structure                                  */
4972         add_i[1] = parms[15]; /* KEY of additional info */
4973         add_i[2] = parms[11]; /* UUI of additional info */
4974         ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4975
4976         /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4977         /* indication returns by the card if requested by the function           */
4978         /* AutomaticLaw() after driver init                                      */
4979         if (a->automatic_law < 4)
4980         {
4981                 if (esc_law[0]) {
4982                         if (esc_law[2]) {
4983                                 dbug(0, dprintf("u-Law selected"));
4984                                 a->u_law = 1;
4985                         }
4986                         else {
4987                                 dbug(0, dprintf("a-Law selected"));
4988                                 a->u_law = 0;
4989                         }
4990                         a->automatic_law = 4;
4991                         if (plci == a->automatic_lawPLCI) {
4992                                 plci->internal_command = 0;
4993                                 sig_req(plci, REMOVE, 0);
4994                                 send_req(plci);
4995                                 a->automatic_lawPLCI = NULL;
4996                         }
4997                 }
4998                 if (esc_profile[0])
4999                 {
5000                         dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
5001                                         UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
5002                                         GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
5003                                         GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
5004
5005                         a->profile.Global_Options &= 0x000000ffL;
5006                         a->profile.B1_Protocols &= 0x000003ffL;
5007                         a->profile.B2_Protocols &= 0x00001fdfL;
5008                         a->profile.B3_Protocols &= 0x000000b7L;
5009
5010                         a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
5011                                 GL_BCHANNEL_OPERATION_SUPPORTED;
5012                         a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
5013                         a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
5014                         a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
5015                         a->manufacturer_features = GET_DWORD(&esc_profile[46]);
5016                         a->man_profile.private_options = 0;
5017
5018                         if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5019                         {
5020                                 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5021                                 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5022                         }
5023
5024
5025                         if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5026                                 a->man_profile.private_options |= 1L << PRIVATE_RTP;
5027                         a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
5028                         a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
5029
5030
5031                         if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5032                                 a->man_profile.private_options |= 1L << PRIVATE_T38;
5033
5034
5035                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5036                                 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5037
5038
5039                         if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5040                                 a->man_profile.private_options |= 1L << PRIVATE_V18;
5041
5042
5043                         if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5044                                 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5045
5046
5047                         if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5048                                 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5049
5050
5051                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5052                                 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5053
5054
5055                         if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5056                                 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5057
5058
5059                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5060                                 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5061
5062                 }
5063                 else
5064                 {
5065                         a->profile.Global_Options &= 0x0000007fL;
5066                         a->profile.B1_Protocols &= 0x000003dfL;
5067                         a->profile.B2_Protocols &= 0x00001adfL;
5068                         a->profile.B3_Protocols &= 0x000000b7L;
5069                         a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5070                 }
5071                 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5072                                                 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5073                 {
5074                         a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5075                 }
5076                 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5077                 dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
5078                                 UnMapController(a->Id), a->profile.Global_Options,
5079                                 a->profile.B1_Protocols, a->profile.B2_Protocols,
5080                                 a->profile.B3_Protocols, a->manufacturer_features));
5081         }
5082         /* codec plci for the handset/hook state support is just an internal id  */
5083         if (plci != a->AdvCodecPLCI)
5084         {
5085                 force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
5086                 force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
5087                 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5088                 SendInfo(plci, Id, parms, force_mt_info);
5089
5090                 VSwitchReqInd(plci, Id, multi_vswitch_parms);
5091
5092         }
5093
5094         /* switch the codec to the b-channel                                     */
5095         if (esc_chi[0] && plci && !plci->SuppState) {
5096                 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5097                 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5098                 dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
5099                 if (plci->tel == ADV_VOICE && plci->appl) {
5100                         SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5101                 }
5102         }
5103
5104         if (plci->appl) plci->appl->Number++;
5105
5106         switch (plci->Sig.Ind) {
5107                 /* Response to Get_Supported_Services request */
5108         case S_SUPPORTED:
5109                 dbug(1, dprintf("S_Supported"));
5110                 if (!plci->appl) break;
5111                 if (pty_cai[0] == 4)
5112                 {
5113                         PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
5114                 }
5115                 else
5116                 {
5117                         PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5118                 }
5119                 PUT_WORD(&CF_Ind[1], 0);
5120                 PUT_WORD(&CF_Ind[4], 0);
5121                 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
5122                 plci_remove(plci);
5123                 break;
5124
5125                 /* Supplementary Service rejected */
5126         case S_SERVICE_REJ:
5127                 dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5128                 if (!pty_cai[0]) break;
5129                 switch (pty_cai[5])
5130                 {
5131                 case ECT_EXECUTE:
5132                 case THREE_PTY_END:
5133                 case THREE_PTY_BEGIN:
5134                         if (!plci->relatedPTYPLCI) break;
5135                         tplci = plci->relatedPTYPLCI;
5136                         rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5137                         if (tplci->tel) rId |= EXT_CONTROLLER;
5138                         if (pty_cai[5] == ECT_EXECUTE)
5139                         {
5140                                 PUT_WORD(&SS_Ind[1], S_ECT);
5141
5142                                 plci->vswitchstate = 0;
5143                                 plci->relatedPTYPLCI->vswitchstate = 0;
5144
5145                         }
5146                         else
5147                         {
5148                                 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5149                         }
5150                         if (pty_cai[2] != 0xff)
5151                         {
5152                                 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5153                         }
5154                         else
5155                         {
5156                                 PUT_WORD(&SS_Ind[4], 0x300E);
5157                         }
5158                         plci->relatedPTYPLCI = NULL;
5159                         plci->ptyState = 0;
5160                         sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5161                         break;
5162
5163                 case CALL_DEFLECTION:
5164                         if (pty_cai[2] != 0xff)
5165                         {
5166                                 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5167                         }
5168                         else
5169                         {
5170                                 PUT_WORD(&SS_Ind[4], 0x300E);
5171                         }
5172                         PUT_WORD(&SS_Ind[1], pty_cai[5]);
5173                         for (i = 0; i < max_appl; i++)
5174                         {
5175                                 if (application[i].CDEnable)
5176                                 {
5177                                         if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5178                                         application[i].CDEnable = false;
5179                                 }
5180                         }
5181                         break;
5182
5183                 case DEACTIVATION_DIVERSION:
5184                 case ACTIVATION_DIVERSION:
5185                 case DIVERSION_INTERROGATE_CFU:
5186                 case DIVERSION_INTERROGATE_CFB:
5187                 case DIVERSION_INTERROGATE_CFNR:
5188                 case DIVERSION_INTERROGATE_NUM:
5189                 case CCBS_REQUEST:
5190                 case CCBS_DEACTIVATE:
5191                 case CCBS_INTERROGATE:
5192                         if (!plci->appl) break;
5193                         if (pty_cai[2] != 0xff)
5194                         {
5195                                 PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5196                         }
5197                         else
5198                         {
5199                                 PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5200                         }
5201                         switch (pty_cai[5])
5202                         {
5203                         case DEACTIVATION_DIVERSION:
5204                                 dbug(1, dprintf("Deact_Div"));
5205                                 Interr_Err_Ind[0] = 0x9;
5206                                 Interr_Err_Ind[3] = 0x6;
5207                                 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5208                                 break;
5209                         case ACTIVATION_DIVERSION:
5210                                 dbug(1, dprintf("Act_Div"));
5211                                 Interr_Err_Ind[0] = 0x9;
5212                                 Interr_Err_Ind[3] = 0x6;
5213                                 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5214                                 break;
5215                         case DIVERSION_INTERROGATE_CFU:
5216                         case DIVERSION_INTERROGATE_CFB:
5217                         case DIVERSION_INTERROGATE_CFNR:
5218                                 dbug(1, dprintf("Interr_Div"));
5219                                 Interr_Err_Ind[0] = 0xa;
5220                                 Interr_Err_Ind[3] = 0x7;
5221                                 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5222                                 break;
5223                         case DIVERSION_INTERROGATE_NUM:
5224                                 dbug(1, dprintf("Interr_Num"));
5225                                 Interr_Err_Ind[0] = 0xa;
5226                                 Interr_Err_Ind[3] = 0x7;
5227                                 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5228                                 break;
5229                         case CCBS_REQUEST:
5230                                 dbug(1, dprintf("CCBS Request"));
5231                                 Interr_Err_Ind[0] = 0xd;
5232                                 Interr_Err_Ind[3] = 0xa;
5233                                 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5234                                 break;
5235                         case CCBS_DEACTIVATE:
5236                                 dbug(1, dprintf("CCBS Deactivate"));
5237                                 Interr_Err_Ind[0] = 0x9;
5238                                 Interr_Err_Ind[3] = 0x6;
5239                                 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5240                                 break;
5241                         case CCBS_INTERROGATE:
5242                                 dbug(1, dprintf("CCBS Interrogate"));
5243                                 Interr_Err_Ind[0] = 0xb;
5244                                 Interr_Err_Ind[3] = 0x8;
5245                                 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5246                                 break;
5247                         }
5248                         PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5249                         sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5250                         plci_remove(plci);
5251                         break;
5252                 case ACTIVATION_MWI:
5253                 case DEACTIVATION_MWI:
5254                         if (pty_cai[5] == ACTIVATION_MWI)
5255                         {
5256                                 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5257                         }
5258                         else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5259
5260                         if (pty_cai[2] != 0xff)
5261                         {
5262                                 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5263                         }
5264                         else
5265                         {
5266                                 PUT_WORD(&SS_Ind[4], 0x300E);
5267                         }
5268
5269                         if (plci->cr_enquiry)
5270                         {
5271                                 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5272                                 plci_remove(plci);
5273                         }
5274                         else
5275                         {
5276                                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5277                         }
5278                         break;
5279                 case CONF_ADD: /* ERROR */
5280                 case CONF_BEGIN:
5281                 case CONF_DROP:
5282                 case CONF_ISOLATE:
5283                 case CONF_REATTACH:
5284                         CONF_Ind[0] = 9;
5285                         CONF_Ind[3] = 6;
5286                         switch (pty_cai[5])
5287                         {
5288                         case CONF_BEGIN:
5289                                 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5290                                 plci->ptyState = 0;
5291                                 break;
5292                         case CONF_DROP:
5293                                 CONF_Ind[0] = 5;
5294                                 CONF_Ind[3] = 2;
5295                                 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5296                                 plci->ptyState = CONNECTED;
5297                                 break;
5298                         case CONF_ISOLATE:
5299                                 CONF_Ind[0] = 5;
5300                                 CONF_Ind[3] = 2;
5301                                 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5302                                 plci->ptyState = CONNECTED;
5303                                 break;
5304                         case CONF_REATTACH:
5305                                 CONF_Ind[0] = 5;
5306                                 CONF_Ind[3] = 2;
5307                                 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5308                                 plci->ptyState = CONNECTED;
5309                                 break;
5310                         case CONF_ADD:
5311                                 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5312                                 plci->relatedPTYPLCI = NULL;
5313                                 tplci = plci->relatedPTYPLCI;
5314                                 if (tplci) tplci->ptyState = CONNECTED;
5315                                 plci->ptyState = CONNECTED;
5316                                 break;
5317                         }
5318
5319                         if (pty_cai[2] != 0xff)
5320                         {
5321                                 PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5322                         }
5323                         else
5324                         {
5325                                 PUT_WORD(&CONF_Ind[4], 0x3303); /* Time-out: network did not respond
5326                                                                   within the required time */
5327                         }
5328
5329                         PUT_DWORD(&CONF_Ind[6], 0x0);
5330                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5331                         break;
5332                 }
5333                 break;
5334
5335                 /* Supplementary Service indicates success */
5336         case S_SERVICE:
5337                 dbug(1, dprintf("Service_Ind"));
5338                 PUT_WORD(&CF_Ind[4], 0);
5339                 switch (pty_cai[5])
5340                 {
5341                 case THREE_PTY_END:
5342                 case THREE_PTY_BEGIN:
5343                 case ECT_EXECUTE:
5344                         if (!plci->relatedPTYPLCI) break;
5345                         tplci = plci->relatedPTYPLCI;
5346                         rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5347                         if (tplci->tel) rId |= EXT_CONTROLLER;
5348                         if (pty_cai[5] == ECT_EXECUTE)
5349                         {
5350                                 PUT_WORD(&SS_Ind[1], S_ECT);
5351
5352                                 if (plci->vswitchstate != 3)
5353                                 {
5354
5355                                         plci->ptyState = IDLE;
5356                                         plci->relatedPTYPLCI = NULL;
5357                                         plci->ptyState = 0;
5358
5359                                 }
5360
5361                                 dbug(1, dprintf("ECT OK"));
5362                                 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5363
5364
5365
5366                         }
5367                         else
5368                         {
5369                                 switch (plci->ptyState)
5370                                 {
5371                                 case S_3PTY_BEGIN:
5372                                         plci->ptyState = CONNECTED;
5373                                         dbug(1, dprintf("3PTY ON"));
5374                                         break;
5375
5376                                 case S_3PTY_END:
5377                                         plci->ptyState = IDLE;
5378                                         plci->relatedPTYPLCI = NULL;
5379                                         plci->ptyState = 0;
5380                                         dbug(1, dprintf("3PTY OFF"));
5381                                         break;
5382                                 }
5383                                 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5384                                 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5385                         }
5386                         break;
5387
5388                 case CALL_DEFLECTION:
5389                         PUT_WORD(&SS_Ind[1], pty_cai[5]);
5390                         for (i = 0; i < max_appl; i++)
5391                         {
5392                                 if (application[i].CDEnable)
5393                                 {
5394                                         if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5395                                         application[i].CDEnable = false;
5396                                 }
5397                         }
5398                         break;
5399
5400                 case DEACTIVATION_DIVERSION:
5401                 case ACTIVATION_DIVERSION:
5402                         if (!plci->appl) break;
5403                         PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5404                         PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5405                         sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5406                         plci_remove(plci);
5407                         break;
5408
5409                 case DIVERSION_INTERROGATE_CFU:
5410                 case DIVERSION_INTERROGATE_CFB:
5411                 case DIVERSION_INTERROGATE_CFNR:
5412                 case DIVERSION_INTERROGATE_NUM:
5413                 case CCBS_REQUEST:
5414                 case CCBS_DEACTIVATE:
5415                 case CCBS_INTERROGATE:
5416                         if (!plci->appl) break;
5417                         switch (pty_cai[5])
5418                         {
5419                         case DIVERSION_INTERROGATE_CFU:
5420                         case DIVERSION_INTERROGATE_CFB:
5421                         case DIVERSION_INTERROGATE_CFNR:
5422                                 dbug(1, dprintf("Interr_Div"));
5423                                 PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5424                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5425                                 break;
5426                         case DIVERSION_INTERROGATE_NUM:
5427                                 dbug(1, dprintf("Interr_Num"));
5428                                 PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5429                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5430                                 break;
5431                         case CCBS_REQUEST:
5432                                 dbug(1, dprintf("CCBS Request"));
5433                                 PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5434                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5435                                 break;
5436                         case CCBS_DEACTIVATE:
5437                                 dbug(1, dprintf("CCBS Deactivate"));
5438                                 PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5439                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5440                                 break;
5441                         case CCBS_INTERROGATE:
5442                                 dbug(1, dprintf("CCBS Interrogate"));
5443                                 PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5444                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5445                                 break;
5446                         }
5447                         PUT_WORD(&pty_cai[4], 0); /* Supplementary Service Reason */
5448                         PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5449                         sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5450                         plci_remove(plci);
5451                         break;
5452
5453                 case ACTIVATION_MWI:
5454                 case DEACTIVATION_MWI:
5455                         if (pty_cai[5] == ACTIVATION_MWI)
5456                         {
5457                                 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5458                         }
5459                         else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5460                         if (plci->cr_enquiry)
5461                         {
5462                                 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5463                                 plci_remove(plci);
5464                         }
5465                         else
5466                         {
5467                                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5468                         }
5469                         break;
5470                 case MWI_INDICATION:
5471                         if (pty_cai[0] >= 0x12)
5472                         {
5473                                 PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5474                                 pty_cai[2] = pty_cai[0] - 2; /* len Parameter */
5475                                 pty_cai[5] = pty_cai[0] - 5; /* Supplementary Service-specific parameter len */
5476                                 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5477                                 {
5478                                         if (plci->internal_command == GET_MWI_STATE) /* result on Message Waiting Listen */
5479                                         {
5480                                                 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5481                                                 plci_remove(plci);
5482                                                 return;
5483                                         }
5484                                         else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5485                                         pty_cai[0] = 0;
5486                                 }
5487                                 else
5488                                 {
5489                                         for (i = 0; i < max_appl; i++)
5490                                         {
5491                                                 if (a->Notification_Mask[i]&SMASK_MWI)
5492                                                 {
5493                                                         sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5494                                                         pty_cai[0] = 0;
5495                                                 }
5496                                         }
5497                                 }
5498
5499                                 if (!pty_cai[0])
5500                                 { /* acknowledge */
5501                                         facility[2] = 0; /* returncode */
5502                                 }
5503                                 else facility[2] = 0xff;
5504                         }
5505                         else
5506                         {
5507                                 /* reject */
5508                                 facility[2] = 0xff; /* returncode */
5509                         }
5510                         facility[0] = 2;
5511                         facility[1] = MWI_RESPONSE; /* Function */
5512                         add_p(plci, CAI, facility);
5513                         add_p(plci, ESC, multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5514                         sig_req(plci, S_SERVICE, 0);
5515                         send_req(plci);
5516                         plci->command = 0;
5517                         next_internal_command(Id, plci);
5518                         break;
5519                 case CONF_ADD: /* OK */
5520                 case CONF_BEGIN:
5521                 case CONF_DROP:
5522                 case CONF_ISOLATE:
5523                 case CONF_REATTACH:
5524                 case CONF_PARTYDISC:
5525                         CONF_Ind[0] = 9;
5526                         CONF_Ind[3] = 6;
5527                         switch (pty_cai[5])
5528                         {
5529                         case CONF_BEGIN:
5530                                 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5531                                 if (pty_cai[0] == 6)
5532                                 {
5533                                         d = pty_cai[6];
5534                                         PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5535                                 }
5536                                 else
5537                                 {
5538                                         PUT_DWORD(&CONF_Ind[6], 0x0);
5539                                 }
5540                                 break;
5541                         case CONF_ISOLATE:
5542                                 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5543                                 CONF_Ind[0] = 5;
5544                                 CONF_Ind[3] = 2;
5545                                 break;
5546                         case CONF_REATTACH:
5547                                 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5548                                 CONF_Ind[0] = 5;
5549                                 CONF_Ind[3] = 2;
5550                                 break;
5551                         case CONF_DROP:
5552                                 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5553                                 CONF_Ind[0] = 5;
5554                                 CONF_Ind[3] = 2;
5555                                 break;
5556                         case CONF_ADD:
5557                                 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5558                                 d = pty_cai[6];
5559                                 PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5560                                 tplci = plci->relatedPTYPLCI;
5561                                 if (tplci) tplci->ptyState = CONNECTED;
5562                                 break;
5563                         case CONF_PARTYDISC:
5564                                 CONF_Ind[0] = 7;
5565                                 CONF_Ind[3] = 4;
5566                                 PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5567                                 d = pty_cai[6];
5568                                 PUT_DWORD(&CONF_Ind[4], d); /* PartyID */
5569                                 break;
5570                         }
5571                         plci->ptyState = CONNECTED;
5572                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5573                         break;
5574                 case CCBS_INFO_RETAIN:
5575                 case CCBS_ERASECALLLINKAGEID:
5576                 case CCBS_STOP_ALERTING:
5577                         CONF_Ind[0] = 5;
5578                         CONF_Ind[3] = 2;
5579                         switch (pty_cai[5])
5580                         {
5581                         case CCBS_INFO_RETAIN:
5582                                 PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5583                                 break;
5584                         case CCBS_STOP_ALERTING:
5585                                 PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5586                                 break;
5587                         case CCBS_ERASECALLLINKAGEID:
5588                                 PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5589                                 CONF_Ind[0] = 7;
5590                                 CONF_Ind[3] = 4;
5591                                 CONF_Ind[6] = 0;
5592                                 CONF_Ind[7] = 0;
5593                                 break;
5594                         }
5595                         w = pty_cai[6];
5596                         PUT_WORD(&CONF_Ind[4], w); /* PartyID */
5597
5598                         if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5599                         {
5600                                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5601                         }
5602                         else
5603                         {
5604                                 for (i = 0; i < max_appl; i++)
5605                                         if (a->Notification_Mask[i] & SMASK_CCBS)
5606                                                 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5607                         }
5608                         break;
5609                 }
5610                 break;
5611         case CALL_HOLD_REJ:
5612                 cau = parms[7];
5613                 if (cau)
5614                 {
5615                         i = _L3_CAUSE | cau[2];
5616                         if (cau[2] == 0) i = 0x3603;
5617                 }
5618                 else
5619                 {
5620                         i = 0x3603;
5621                 }
5622                 PUT_WORD(&SS_Ind[1], S_HOLD);
5623                 PUT_WORD(&SS_Ind[4], i);
5624                 if (plci->SuppState == HOLD_REQUEST)
5625                 {
5626                         plci->SuppState = IDLE;
5627                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5628                 }
5629                 break;
5630
5631         case CALL_HOLD_ACK:
5632                 if (plci->SuppState == HOLD_REQUEST)
5633                 {
5634                         plci->SuppState = CALL_HELD;
5635                         CodecIdCheck(a, plci);
5636                         start_internal_command(Id, plci, hold_save_command);
5637                 }
5638                 break;
5639
5640         case CALL_RETRIEVE_REJ:
5641                 cau = parms[7];
5642                 if (cau)
5643                 {
5644                         i = _L3_CAUSE | cau[2];
5645                         if (cau[2] == 0) i = 0x3603;
5646                 }
5647                 else
5648                 {
5649                         i = 0x3603;
5650                 }
5651                 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5652                 PUT_WORD(&SS_Ind[4], i);
5653                 if (plci->SuppState == RETRIEVE_REQUEST)
5654                 {
5655                         plci->SuppState = CALL_HELD;
5656                         CodecIdCheck(a, plci);
5657                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5658                 }
5659                 break;
5660
5661         case CALL_RETRIEVE_ACK:
5662                 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5663                 if (plci->SuppState == RETRIEVE_REQUEST)
5664                 {
5665                         plci->SuppState = IDLE;
5666                         plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5667                         plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5668                         if (plci->tel)
5669                         {
5670                                 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5671                                 dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5672                                 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5673                                 if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5674                                 {
5675                                         dbug(1, dprintf("Get B-ch"));
5676                                         start_internal_command(Id, plci, retrieve_restore_command);
5677                                 }
5678                                 else
5679                                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5680                         }
5681                         else
5682                                 start_internal_command(Id, plci, retrieve_restore_command);
5683                 }
5684                 break;
5685
5686         case INDICATE_IND:
5687                 if (plci->State != LISTENING) {
5688                         sig_req(plci, HANGUP, 0);
5689                         send_req(plci);
5690                         break;
5691                 }
5692                 cip = find_cip(a, parms[4], parms[6]);
5693                 cip_mask = 1L << cip;
5694                 dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5695                 clear_c_ind_mask(plci);
5696                 if (!remove_started && !a->adapter_disabled)
5697                 {
5698                         set_c_ind_mask_bit(plci, MAX_APPL);
5699                         group_optimization(a, plci);
5700                         for (i = 0; i < max_appl; i++) {
5701                                 if (application[i].Id
5702                                     && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5703                                     && CPN_filter_ok(parms[0], a, i)
5704                                     && test_group_ind_mask_bit(plci, i)) {
5705                                         dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5706                                         set_c_ind_mask_bit(plci, i);
5707                                         dump_c_ind_mask(plci);
5708                                         plci->State = INC_CON_PENDING;
5709                                         plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5710                                                 CALL_DIR_IN | CALL_DIR_ANSWER;
5711                                         if (esc_chi[0]) {
5712                                                 plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5713                                                 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5714                                         }
5715                                         /* if a listen on the ext controller is done, check if hook states */
5716                                         /* are supported or if just a on board codec must be activated     */
5717                                         if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5718                                                 if (a->profile.Global_Options & HANDSET)
5719                                                         plci->tel = ADV_VOICE;
5720                                                 else if (a->profile.Global_Options & ON_BOARD_CODEC)
5721                                                         plci->tel = CODEC;
5722                                                 if (plci->tel) Id |= EXT_CONTROLLER;
5723                                                 a->codec_listen[i] = plci;
5724                                         }
5725
5726                                         sendf(&application[i], _CONNECT_I, Id, 0,
5727                                               "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5728                                               parms[0],    /* CalledPartyNumber   */
5729                                               multi_CiPN_parms[0],    /* CallingPartyNumber  */
5730                                               parms[2],    /* CalledPartySubad    */
5731                                               parms[3],    /* CallingPartySubad   */
5732                                               parms[4],    /* BearerCapability    */
5733                                               parms[5],    /* LowLC               */
5734                                               parms[6],    /* HighLC              */
5735                                               ai_len,      /* nested struct add_i */
5736                                               add_i[0],    /* B channel info    */
5737                                               add_i[1],    /* keypad facility   */
5738                                               add_i[2],    /* user user data    */
5739                                               add_i[3],    /* nested facility   */
5740                                               multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5741                                                 );
5742                                         SendSSExtInd(&application[i],
5743                                                      plci,
5744                                                      Id,
5745                                                      multi_ssext_parms);
5746                                         SendSetupInfo(&application[i],
5747                                                       plci,
5748                                                       Id,
5749                                                       parms,
5750                                                       SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5751                                 }
5752                         }
5753                         clear_c_ind_mask_bit(plci, MAX_APPL);
5754                         dump_c_ind_mask(plci);
5755                 }
5756                 if (c_ind_mask_empty(plci)) {
5757                         sig_req(plci, HANGUP, 0);
5758                         send_req(plci);
5759                         plci->State = IDLE;
5760                 }
5761                 plci->notifiedcall = 0;
5762                 a->listen_active--;
5763                 listen_check(a);
5764                 break;
5765
5766         case CALL_PEND_NOTIFY:
5767                 plci->notifiedcall = 1;
5768                 listen_check(a);
5769                 break;
5770
5771         case CALL_IND:
5772         case CALL_CON:
5773                 if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5774                 {
5775                         if (plci->internal_command == PERM_COD_CONN_PEND)
5776                         {
5777                                 if (plci->State == ADVANCED_VOICE_NOSIG)
5778                                 {
5779                                         dbug(1, dprintf("***Codec OK"));
5780                                         if (a->AdvSignalPLCI)
5781                                         {
5782                                                 tplci = a->AdvSignalPLCI;
5783                                                 if (tplci->spoofed_msg)
5784                                                 {
5785                                                         dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5786                                                         tplci->command = 0;
5787                                                         tplci->internal_command = 0;
5788                                                         x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5789                                                         switch (tplci->spoofed_msg)
5790                                                         {
5791                                                         case CALL_RES:
5792                                                                 tplci->command = _CONNECT_I | RESPONSE;
5793                                                                 api_load_msg(&tplci->saved_msg, saved_parms);
5794                                                                 add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5795                                                                 if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5796                                                                 {
5797                                                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
5798                                                                         add_p(tplci, LLI, "\x01\x01");
5799                                                                 }
5800                                                                 add_s(tplci, CONN_NR, &saved_parms[2]);
5801                                                                 add_s(tplci, LLC, &saved_parms[4]);
5802                                                                 add_ai(tplci, &saved_parms[5]);
5803                                                                 tplci->State = INC_CON_ACCEPT;
5804                                                                 sig_req(tplci, CALL_RES, 0);
5805                                                                 send_req(tplci);
5806                                                                 break;
5807
5808                                                         case AWAITING_SELECT_B:
5809                                                                 dbug(1, dprintf("Select_B continue"));
5810                                                                 start_internal_command(x_Id, tplci, select_b_command);
5811                                                                 break;
5812
5813                                                         case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5814                                                                 if (!tplci->Sig.Id)
5815                                                                 {
5816                                                                         dbug(1, dprintf("No SigID!"));
5817                                                                         sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5818                                                                         plci_remove(tplci);
5819                                                                         break;
5820                                                                 }
5821                                                                 tplci->command = _MANUFACTURER_R;
5822                                                                 api_load_msg(&tplci->saved_msg, saved_parms);
5823                                                                 dir = saved_parms[2].info[0];
5824                                                                 if (dir == 1) {
5825                                                                         sig_req(tplci, CALL_REQ, 0);
5826                                                                 }
5827                                                                 else if (!dir) {
5828                                                                         sig_req(tplci, LISTEN_REQ, 0);
5829                                                                 }
5830                                                                 send_req(tplci);
5831                                                                 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5832                                                                 break;
5833
5834                                                         case (CALL_REQ | AWAITING_MANUF_CON):
5835                                                                 sig_req(tplci, CALL_REQ, 0);
5836                                                                 send_req(tplci);
5837                                                                 break;
5838
5839                                                         case CALL_REQ:
5840                                                                 if (!tplci->Sig.Id)
5841                                                                 {
5842                                                                         dbug(1, dprintf("No SigID!"));
5843                                                                         sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5844                                                                         plci_remove(tplci);
5845                                                                         break;
5846                                                                 }
5847                                                                 tplci->command = _CONNECT_R;
5848                                                                 api_load_msg(&tplci->saved_msg, saved_parms);
5849                                                                 add_s(tplci, CPN, &saved_parms[1]);
5850                                                                 add_s(tplci, DSA, &saved_parms[3]);
5851                                                                 add_ai(tplci, &saved_parms[9]);
5852                                                                 sig_req(tplci, CALL_REQ, 0);
5853                                                                 send_req(tplci);
5854                                                                 break;
5855
5856                                                         case CALL_RETRIEVE:
5857                                                                 tplci->command = C_RETRIEVE_REQ;
5858                                                                 sig_req(tplci, CALL_RETRIEVE, 0);
5859                                                                 send_req(tplci);
5860                                                                 break;
5861                                                         }
5862                                                         tplci->spoofed_msg = 0;
5863                                                         if (tplci->internal_command == 0)
5864                                                                 next_internal_command(x_Id, tplci);
5865                                                 }
5866                                         }
5867                                         next_internal_command(Id, plci);
5868                                         break;
5869                                 }
5870                                 dbug(1, dprintf("***Codec Hook Init Req"));
5871                                 plci->internal_command = PERM_COD_HOOK;
5872                                 add_p(plci, FTY, "\x01\x09");             /* Get Hook State*/
5873                                 sig_req(plci, TEL_CTRL, 0);
5874                                 send_req(plci);
5875                         }
5876                 }
5877                 else if (plci->command != _MANUFACTURER_R  /* old style permanent connect */
5878                          && plci->State != INC_ACT_PENDING)
5879                 {
5880                         mixer_set_bchannel_id_esc(plci, plci->b_channel);
5881                         if (plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5882                         {
5883                                 chi[2] = plci->b_channel;
5884                                 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5885                         }
5886                         sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5887                         plci->State = INC_ACT_PENDING;
5888                 }
5889                 break;
5890
5891         case TEL_CTRL:
5892                 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5893                 if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5894                         switch (ie[1] & 0x91) {
5895                         case 0x80:   /* hook off */
5896                         case 0x81:
5897                                 if (plci->internal_command == PERM_COD_HOOK)
5898                                 {
5899                                         dbug(1, dprintf("init:hook_off"));
5900                                         plci->hook_state = ie[1];
5901                                         next_internal_command(Id, plci);
5902                                         break;
5903                                 }
5904                                 else /* ignore doubled hook indications */
5905                                 {
5906                                         if (((plci->hook_state) & 0xf0) == 0x80)
5907                                         {
5908                                                 dbug(1, dprintf("ignore hook"));
5909                                                 break;
5910                                         }
5911                                         plci->hook_state = ie[1]&0x91;
5912                                 }
5913                                 /* check for incoming call pending */
5914                                 /* and signal '+'.Appl must decide */
5915                                 /* with connect_res if call must   */
5916                                 /* accepted or not                 */
5917                                 for (i = 0, tplci = NULL; i < max_appl; i++) {
5918                                         if (a->codec_listen[i]
5919                                             && (a->codec_listen[i]->State == INC_CON_PENDING
5920                                                 || a->codec_listen[i]->State == INC_CON_ALERT)) {
5921                                                 tplci = a->codec_listen[i];
5922                                                 tplci->appl = &application[i];
5923                                         }
5924                                 }
5925                                 /* no incoming call, do outgoing call */
5926                                 /* and signal '+' if outg. setup   */
5927                                 if (!a->AdvSignalPLCI && !tplci) {
5928                                         if ((i = get_plci(a))) {
5929                                                 a->AdvSignalPLCI = &a->plci[i - 1];
5930                                                 tplci = a->AdvSignalPLCI;
5931                                                 tplci->tel  = ADV_VOICE;
5932                                                 PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5933                                                 if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5934                                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
5935                                                         add_p(tplci, LLI, "\x01\x01");
5936                                                 }
5937                                                 add_p(tplci, CAI, voice_cai);
5938                                                 add_p(tplci, OAD, a->TelOAD);
5939                                                 add_p(tplci, OSA, a->TelOSA);
5940                                                 add_p(tplci, SHIFT | 6, NULL);
5941                                                 add_p(tplci, SIN, "\x02\x01\x00");
5942                                                 add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5943                                                 sig_req(tplci, ASSIGN, DSIG_ID);
5944                                                 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5945                                                 a->AdvSignalPLCI->command = 0;
5946                                                 tplci->appl = a->AdvSignalAppl;
5947                                                 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5948                                                 send_req(tplci);
5949                                         }
5950
5951                                 }
5952
5953                                 if (!tplci) break;
5954                                 Id = ((word)tplci->Id << 8) | a->Id;
5955                                 Id |= EXT_CONTROLLER;
5956                                 sendf(tplci->appl,
5957                                       _FACILITY_I,
5958                                       Id,
5959                                       0,
5960                                       "ws", (word)0, "\x01+");
5961                                 break;
5962
5963                         case 0x90:   /* hook on  */
5964                         case 0x91:
5965                                 if (plci->internal_command == PERM_COD_HOOK)
5966                                 {
5967                                         dbug(1, dprintf("init:hook_on"));
5968                                         plci->hook_state = ie[1] & 0x91;
5969                                         next_internal_command(Id, plci);
5970                                         break;
5971                                 }
5972                                 else /* ignore doubled hook indications */
5973                                 {
5974                                         if (((plci->hook_state) & 0xf0) == 0x90) break;
5975                                         plci->hook_state = ie[1] & 0x91;
5976                                 }
5977                                 /* hangup the adv. voice call and signal '-' to the appl */
5978                                 if (a->AdvSignalPLCI) {
5979                                         Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5980                                         if (plci->tel) Id |= EXT_CONTROLLER;
5981                                         sendf(a->AdvSignalAppl,
5982                                               _FACILITY_I,
5983                                               Id,
5984                                               0,
5985                                               "ws", (word)0, "\x01-");
5986                                         a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5987                                         a->AdvSignalPLCI->command = 0;
5988                                         sig_req(a->AdvSignalPLCI, HANGUP, 0);
5989                                         send_req(a->AdvSignalPLCI);
5990                                 }
5991                                 break;
5992                         }
5993                 }
5994                 break;
5995
5996         case RESUME:
5997                 clear_c_ind_mask_bit(plci, (word)(plci->appl->Id - 1));
5998                 PUT_WORD(&resume_cau[4], GOOD);
5999                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6000                 break;
6001
6002         case SUSPEND:
6003                 clear_c_ind_mask(plci);
6004
6005                 if (plci->NL.Id && !plci->nl_remove_id) {
6006                         mixer_remove(plci);
6007                         nl_req_ncci(plci, REMOVE, 0);
6008                 }
6009                 if (!plci->sig_remove_id) {
6010                         plci->internal_command = 0;
6011                         sig_req(plci, REMOVE, 0);
6012                 }
6013                 send_req(plci);
6014                 if (!plci->channels) {
6015                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6016                         sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6017                 }
6018                 break;
6019
6020         case SUSPEND_REJ:
6021                 break;
6022
6023         case HANGUP:
6024                 plci->hangup_flow_ctrl_timer = 0;
6025                 if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
6026                 cau = parms[7];
6027                 if (cau) {
6028                         i = _L3_CAUSE | cau[2];
6029                         if (cau[2] == 0) i = 0;
6030                         else if (cau[2] == 8) i = _L1_ERROR;
6031                         else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
6032                         else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
6033                 }
6034                 else {
6035                         i = _L3_ERROR;
6036                 }
6037
6038                 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
6039                 {
6040                         for (i = 0; i < max_appl; i++)
6041                         {
6042                                 if (test_c_ind_mask_bit(plci, i))
6043                                         sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6044                         }
6045                 }
6046                 else
6047                 {
6048                         clear_c_ind_mask(plci);
6049                 }
6050                 if (!plci->appl)
6051                 {
6052                         if (plci->State == LISTENING)
6053                         {
6054                                 plci->notifiedcall = 0;
6055                                 a->listen_active--;
6056                         }
6057                         plci->State = INC_DIS_PENDING;
6058                         if (c_ind_mask_empty(plci))
6059                         {
6060                                 plci->State = IDLE;
6061                                 if (plci->NL.Id && !plci->nl_remove_id)
6062                                 {
6063                                         mixer_remove(plci);
6064                                         nl_req_ncci(plci, REMOVE, 0);
6065                                 }
6066                                 if (!plci->sig_remove_id)
6067                                 {
6068                                         plci->internal_command = 0;
6069                                         sig_req(plci, REMOVE, 0);
6070                                 }
6071                                 send_req(plci);
6072                         }
6073                 }
6074                 else
6075                 {
6076                         /* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
6077                         /* result in a second HANGUP! Don't generate another        */
6078                         /* DISCONNECT                                               */
6079                         if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
6080                         {
6081                                 if (plci->State == RESUMING)
6082                                 {
6083                                         PUT_WORD(&resume_cau[4], i);
6084                                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6085                                 }
6086                                 plci->State = INC_DIS_PENDING;
6087                                 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
6088                         }
6089                 }
6090                 break;
6091
6092         case SSEXT_IND:
6093                 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
6094                 break;
6095
6096         case VSWITCH_REQ:
6097                 VSwitchReqInd(plci, Id, multi_vswitch_parms);
6098                 break;
6099         case VSWITCH_IND:
6100                 if (plci->relatedPTYPLCI &&
6101                     plci->vswitchstate == 3 &&
6102                     plci->relatedPTYPLCI->vswitchstate == 3 &&
6103                     parms[MAXPARMSIDS - 1][0])
6104                 {
6105                         add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
6106                         sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
6107                         send_req(plci->relatedPTYPLCI);
6108                 }
6109                 else VSwitchReqInd(plci, Id, multi_vswitch_parms);
6110                 break;
6111
6112         }
6113 }
6114
6115
6116 static void SendSetupInfo(APPL *appl, PLCI *plci, dword Id, byte **parms, byte Info_Sent_Flag)
6117 {
6118         word i;
6119         byte *ie;
6120         word Info_Number;
6121         byte *Info_Element;
6122         word Info_Mask = 0;
6123
6124         dbug(1, dprintf("SetupInfo"));
6125
6126         for (i = 0; i < MAXPARMSIDS; i++) {
6127                 ie = parms[i];
6128                 Info_Number = 0;
6129                 Info_Element = ie;
6130                 if (ie[0]) {
6131                         switch (i) {
6132                         case 0:
6133                                 dbug(1, dprintf("CPN "));
6134                                 Info_Number = 0x0070;
6135                                 Info_Mask = 0x80;
6136                                 Info_Sent_Flag = true;
6137                                 break;
6138                         case 8:  /* display      */
6139                                 dbug(1, dprintf("display(%d)", i));
6140                                 Info_Number = 0x0028;
6141                                 Info_Mask = 0x04;
6142                                 Info_Sent_Flag = true;
6143                                 break;
6144                         case 16: /* Channel Id */
6145                                 dbug(1, dprintf("CHI"));
6146                                 Info_Number = 0x0018;
6147                                 Info_Mask = 0x100;
6148                                 Info_Sent_Flag = true;
6149                                 mixer_set_bchannel_id(plci, Info_Element);
6150                                 break;
6151                         case 19: /* Redirected Number */
6152                                 dbug(1, dprintf("RDN"));
6153                                 Info_Number = 0x0074;
6154                                 Info_Mask = 0x400;
6155                                 Info_Sent_Flag = true;
6156                                 break;
6157                         case 20: /* Redirected Number extended */
6158                                 dbug(1, dprintf("RDX"));
6159                                 Info_Number = 0x0073;
6160                                 Info_Mask = 0x400;
6161                                 Info_Sent_Flag = true;
6162                                 break;
6163                         case 22: /* Redirecing Number  */
6164                                 dbug(1, dprintf("RIN"));
6165                                 Info_Number = 0x0076;
6166                                 Info_Mask = 0x400;
6167                                 Info_Sent_Flag = true;
6168                                 break;
6169                         default:
6170                                 Info_Number = 0;
6171                                 break;
6172                         }
6173                 }
6174
6175                 if (i == MAXPARMSIDS - 2) { /* to indicate the message type "Setup" */
6176                         Info_Number = 0x8000 | 5;
6177                         Info_Mask = 0x10;
6178                         Info_Element = "";
6179                 }
6180
6181                 if (Info_Sent_Flag && Info_Number) {
6182                         if (plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask) {
6183                                 sendf(appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6184                         }
6185                 }
6186         }
6187 }
6188
6189
6190 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6191 {
6192         word i;
6193         word j;
6194         word k;
6195         byte *ie;
6196         word Info_Number;
6197         byte *Info_Element;
6198         word Info_Mask = 0;
6199         static byte charges[5] = {4, 0, 0, 0, 0};
6200         static byte cause[] = {0x02, 0x80, 0x00};
6201         APPL *appl;
6202
6203         dbug(1, dprintf("InfoParse "));
6204
6205         if (
6206                 !plci->appl
6207                 && !plci->State
6208                 && plci->Sig.Ind != NCR_FACILITY
6209                 )
6210         {
6211                 dbug(1, dprintf("NoParse "));
6212                 return;
6213         }
6214         cause[2] = 0;
6215         for (i = 0; i < MAXPARMSIDS; i++) {
6216                 ie = parms[i];
6217                 Info_Number = 0;
6218                 Info_Element = ie;
6219                 if (ie[0]) {
6220                         switch (i) {
6221                         case 0:
6222                                 dbug(1, dprintf("CPN "));
6223                                 Info_Number = 0x0070;
6224                                 Info_Mask   = 0x80;
6225                                 break;
6226                         case 7: /* ESC_CAU */
6227                                 dbug(1, dprintf("cau(0x%x)", ie[2]));
6228                                 Info_Number = 0x0008;
6229                                 Info_Mask = 0x00;
6230                                 cause[2] = ie[2];
6231                                 Info_Element = NULL;
6232                                 break;
6233                         case 8:  /* display      */
6234                                 dbug(1, dprintf("display(%d)", i));
6235                                 Info_Number = 0x0028;
6236                                 Info_Mask = 0x04;
6237                                 break;
6238                         case 9:  /* Date display */
6239                                 dbug(1, dprintf("date(%d)", i));
6240                                 Info_Number = 0x0029;
6241                                 Info_Mask = 0x02;
6242                                 break;
6243                         case 10: /* charges */
6244                                 for (j = 0; j < 4; j++) charges[1 + j] = 0;
6245                                 for (j = 0; j < ie[0] && !(ie[1 + j] & 0x80); j++);
6246                                 for (k = 1, j++; j < ie[0] && k <= 4; j++, k++) charges[k] = ie[1 + j];
6247                                 Info_Number = 0x4000;
6248                                 Info_Mask = 0x40;
6249                                 Info_Element = charges;
6250                                 break;
6251                         case 11: /* user user info */
6252                                 dbug(1, dprintf("uui"));
6253                                 Info_Number = 0x007E;
6254                                 Info_Mask = 0x08;
6255                                 break;
6256                         case 12: /* congestion receiver ready */
6257                                 dbug(1, dprintf("clRDY"));
6258                                 Info_Number = 0x00B0;
6259                                 Info_Mask = 0x08;
6260                                 Info_Element = "";
6261                                 break;
6262                         case 13: /* congestion receiver not ready */
6263                                 dbug(1, dprintf("clNRDY"));
6264                                 Info_Number = 0x00BF;
6265                                 Info_Mask = 0x08;
6266                                 Info_Element = "";
6267                                 break;
6268                         case 15: /* Keypad Facility */
6269                                 dbug(1, dprintf("KEY"));
6270                                 Info_Number = 0x002C;
6271                                 Info_Mask = 0x20;
6272                                 break;
6273                         case 16: /* Channel Id */
6274                                 dbug(1, dprintf("CHI"));
6275                                 Info_Number = 0x0018;
6276                                 Info_Mask = 0x100;
6277                                 mixer_set_bchannel_id(plci, Info_Element);
6278                                 break;
6279                         case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6280                                 dbug(1, dprintf("q9cau(0x%x)", ie[2]));
6281                                 if (!cause[2] || cause[2] < 0x80) break;  /* eg. layer 1 error */
6282                                 Info_Number = 0x0008;
6283                                 Info_Mask = 0x01;
6284                                 if (cause[2] != ie[2]) Info_Element = cause;
6285                                 break;
6286                         case 19: /* Redirected Number */
6287                                 dbug(1, dprintf("RDN"));
6288                                 Info_Number = 0x0074;
6289                                 Info_Mask = 0x400;
6290                                 break;
6291                         case 22: /* Redirecing Number  */
6292                                 dbug(1, dprintf("RIN"));
6293                                 Info_Number = 0x0076;
6294                                 Info_Mask = 0x400;
6295                                 break;
6296                         case 23: /* Notification Indicator  */
6297                                 dbug(1, dprintf("NI"));
6298                                 Info_Number = (word)NI;
6299                                 Info_Mask = 0x210;
6300                                 break;
6301                         case 26: /* Call State  */
6302                                 dbug(1, dprintf("CST"));
6303                                 Info_Number = (word)CST;
6304                                 Info_Mask = 0x01; /* do with cause i.e. for now */
6305                                 break;
6306                         case MAXPARMSIDS - 2:  /* Escape Message Type, must be the last indication */
6307                                 dbug(1, dprintf("ESC/MT[0x%x]", ie[3]));
6308                                 Info_Number = 0x8000 | ie[3];
6309                                 if (iesent) Info_Mask = 0xffff;
6310                                 else  Info_Mask = 0x10;
6311                                 Info_Element = "";
6312                                 break;
6313                         default:
6314                                 Info_Number  = 0;
6315                                 Info_Mask    = 0;
6316                                 Info_Element = "";
6317                                 break;
6318                         }
6319                 }
6320
6321                 if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6322                 {
6323                         for (j = 0; j < max_appl; j++)
6324                         {
6325                                 appl = &application[j];
6326                                 if (Info_Number
6327                                     && appl->Id
6328                                     && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6329                                 {
6330                                         dbug(1, dprintf("NCR_Ind"));
6331                                         iesent = true;
6332                                         sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6333                                 }
6334                         }
6335                 }
6336                 else if (!plci->appl)
6337                 { /* overlap receiving broadcast */
6338                         if (Info_Number == CPN
6339                             || Info_Number == KEY
6340                             || Info_Number == NI
6341                             || Info_Number == DSP
6342                             || Info_Number == UUI)
6343                         {
6344                                 for (j = 0; j < max_appl; j++)
6345                                 {
6346                                         if (test_c_ind_mask_bit(plci, j))
6347                                         {
6348                                                 dbug(1, dprintf("Ovl_Ind"));
6349                                                 iesent = true;
6350                                                 sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6351                                         }
6352                                 }
6353                         }
6354                 }               /* all other signalling states */
6355                 else if (Info_Number
6356                          && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6357                 {
6358                         dbug(1, dprintf("Std_Ind"));
6359                         iesent = true;
6360                         sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6361                 }
6362         }
6363 }
6364
6365
6366 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6367                         dword info_mask, byte setupParse)
6368 {
6369         word i;
6370         word j;
6371         byte *ie;
6372         word Info_Number;
6373         byte *Info_Element;
6374         APPL *appl;
6375         word Info_Mask = 0;
6376         byte iesent = 0;
6377
6378         if (
6379                 !plci->appl
6380                 && !plci->State
6381                 && plci->Sig.Ind != NCR_FACILITY
6382                 && !setupParse
6383                 )
6384         {
6385                 dbug(1, dprintf("NoM-IEParse "));
6386                 return 0;
6387         }
6388         dbug(1, dprintf("M-IEParse "));
6389
6390         for (i = 0; i < MAX_MULTI_IE; i++)
6391         {
6392                 ie = parms[i];
6393                 Info_Number = 0;
6394                 Info_Element = ie;
6395                 if (ie[0])
6396                 {
6397                         dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci->Sig.Ind, ie_type));
6398                         Info_Number = (word)ie_type;
6399                         Info_Mask = (word)info_mask;
6400                 }
6401
6402                 if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6403                 {
6404                         for (j = 0; j < max_appl; j++)
6405                         {
6406                                 appl = &application[j];
6407                                 if (Info_Number
6408                                     && appl->Id
6409                                     && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6410                                 {
6411                                         iesent = true;
6412                                         dbug(1, dprintf("Mlt_NCR_Ind"));
6413                                         sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6414                                 }
6415                         }
6416                 }
6417                 else if (!plci->appl && Info_Number)
6418                 {                                        /* overlap receiving broadcast */
6419                         for (j = 0; j < max_appl; j++)
6420                         {
6421                                 if (test_c_ind_mask_bit(plci, j))
6422                                 {
6423                                         iesent = true;
6424                                         dbug(1, dprintf("Mlt_Ovl_Ind"));
6425                                         sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6426                                 }
6427                         }
6428                 }                                        /* all other signalling states */
6429                 else if (Info_Number
6430                          && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6431                 {
6432                         iesent = true;
6433                         dbug(1, dprintf("Mlt_Std_Ind"));
6434                         sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6435                 }
6436         }
6437         return iesent;
6438 }
6439
6440 static void SendSSExtInd(APPL *appl, PLCI *plci, dword Id, byte **parms)
6441 {
6442         word i;
6443         /* Format of multi_ssext_parms[i][]:
6444            0 byte length
6445            1 byte SSEXTIE
6446            2 byte SSEXT_REQ/SSEXT_IND
6447            3 byte length
6448            4 word SSExtCommand
6449            6... Params
6450         */
6451         if (
6452                 plci
6453                 && plci->State
6454                 && plci->Sig.Ind != NCR_FACILITY
6455                 )
6456                 for (i = 0; i < MAX_MULTI_IE; i++)
6457                 {
6458                         if (parms[i][0] < 6) continue;
6459                         if (parms[i][2] == SSEXT_REQ) continue;
6460
6461                         if (appl)
6462                         {
6463                                 parms[i][0] = 0; /* kill it */
6464                                 sendf(appl, _MANUFACTURER_I,
6465                                       Id,
6466                                       0,
6467                                       "dwS",
6468                                       _DI_MANU_ID,
6469                                       _DI_SSEXT_CTRL,
6470                                       &parms[i][3]);
6471                         }
6472                         else if (plci->appl)
6473                         {
6474                                 parms[i][0] = 0; /* kill it */
6475                                 sendf(plci->appl, _MANUFACTURER_I,
6476                                       Id,
6477                                       0,
6478                                       "dwS",
6479                                       _DI_MANU_ID,
6480                                       _DI_SSEXT_CTRL,
6481                                       &parms[i][3]);
6482                         }
6483                 }
6484 };
6485
6486 static void nl_ind(PLCI *plci)
6487 {
6488         byte ch;
6489         word ncci;
6490         dword Id;
6491         DIVA_CAPI_ADAPTER *a;
6492         word NCCIcode;
6493         APPL *APPLptr;
6494         word count;
6495         word Num;
6496         word i, ncpi_state;
6497         byte len, ncci_state;
6498         word msg;
6499         word info = 0;
6500         word fax_feature_bits;
6501         byte fax_send_edata_ack;
6502         static byte v120_header_buffer[2 + 3];
6503         static word fax_info[] = {
6504                 0,                     /* T30_SUCCESS                        */
6505                 _FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
6506                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
6507                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
6508                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
6509                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
6510                 _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
6511                 _FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
6512                 _FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
6513                 _FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
6514                 _FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
6515                 _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
6516                 _FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
6517                 _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
6518                 _FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
6519                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
6520                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
6521                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
6522                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
6523                 _FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
6524                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
6525                 _FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
6526                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
6527                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
6528                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
6529                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
6530                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
6531                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
6532                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
6533                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
6534                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
6535                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
6536                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
6537                 0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
6538                 0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
6539                 0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
6540                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
6541                 _FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
6542                 _FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
6543                 _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
6544                 _FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
6545                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6546                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
6547                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
6548                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
6549                 _FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
6550                 _FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
6551         };
6552
6553         byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6554
6555
6556         static word rtp_info[] = {
6557                 GOOD,                  /* RTP_SUCCESS                       */
6558                 0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
6559         };
6560
6561         static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6562                 {
6563                         0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6564                         0x00000000, 0x00000000, 0x00000000, 0x00000000
6565                 };
6566
6567         ch = plci->NL.IndCh;
6568         a = plci->adapter;
6569         ncci = a->ch_ncci[ch];
6570         Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6571         if (plci->tel) Id |= EXT_CONTROLLER;
6572         APPLptr = plci->appl;
6573         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",
6574                         plci->NL.Id, Id, plci->Id, plci->tel, plci->State, ch, plci->channels, plci->NL.Ind & 0x0f));
6575
6576         /* in the case if no connect_active_Ind was sent to the appl we wait for */
6577
6578         if (plci->nl_remove_id)
6579         {
6580                 plci->NL.RNR = 2; /* discard */
6581                 dbug(1, dprintf("NL discard while remove pending"));
6582                 return;
6583         }
6584         if ((plci->NL.Ind & 0x0f) == N_CONNECT)
6585         {
6586                 if (plci->State == INC_DIS_PENDING
6587                     || plci->State == OUTG_DIS_PENDING
6588                     || plci->State == IDLE)
6589                 {
6590                         plci->NL.RNR = 2; /* discard */
6591                         dbug(1, dprintf("discard n_connect"));
6592                         return;
6593                 }
6594                 if (plci->State < INC_ACT_PENDING)
6595                 {
6596                         plci->NL.RNR = 1; /* flow control */
6597                         channel_x_off(plci, ch, N_XON_CONNECT_IND);
6598                         return;
6599                 }
6600         }
6601
6602         if (!APPLptr)                         /* no application or invalid data */
6603         {                                    /* while reloading the DSP        */
6604                 dbug(1, dprintf("discard1"));
6605                 plci->NL.RNR = 2;
6606                 return;
6607         }
6608
6609         if (((plci->NL.Ind & 0x0f) == N_UDATA)
6610             && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6611                 || (plci->B2_prot == 7)
6612                 || (plci->B3_prot == 7)))
6613         {
6614                 plci->ncpi_buffer[0] = 0;
6615
6616                 ncpi_state = plci->ncpi_state;
6617                 if (plci->NL.complete == 1)
6618                 {
6619                         byte *data = &plci->NL.RBuffer->P[0];
6620
6621                         if ((plci->NL.RBuffer->length >= 12)
6622                             && ((*data == DSP_UDATA_INDICATION_DCD_ON)
6623                                 || (*data == DSP_UDATA_INDICATION_CTS_ON)))
6624                         {
6625                                 word conn_opt, ncpi_opt = 0x00;
6626 /*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6627
6628                                 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6629                                         plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6630                                 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6631                                         plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6632
6633                                 data++;    /* indication code */
6634                                 data += 2; /* timestamp */
6635                                 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6636                                         ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6637                                 data++;    /* connected norm */
6638                                 conn_opt = GET_WORD(data);
6639                                 data += 2; /* connected options */
6640
6641                                 PUT_WORD(&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6642
6643                                 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6644                                 {
6645                                         ncpi_opt |= MDM_NCPI_ECM_V42;
6646                                 }
6647                                 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6648                                 {
6649                                         ncpi_opt |= MDM_NCPI_ECM_MNP;
6650                                 }
6651                                 else
6652                                 {
6653                                         ncpi_opt |= MDM_NCPI_TRANSPARENT;
6654                                 }
6655                                 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6656                                 {
6657                                         ncpi_opt |= MDM_NCPI_COMPRESSED;
6658                                 }
6659                                 PUT_WORD(&(plci->ncpi_buffer[3]), ncpi_opt);
6660                                 plci->ncpi_buffer[0] = 4;
6661
6662                                 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6663                         }
6664                 }
6665                 if (plci->B3_prot == 7)
6666                 {
6667                         if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6668                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6669                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6670                         {
6671                                 a->ncci_state[ncci] = INC_ACT_PENDING;
6672                                 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6673                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6674                         }
6675                 }
6676
6677                 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
6678                       & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6679                     || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6680                     || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6681
6682                 {
6683                         plci->NL.RNR = 2;
6684                         return;
6685                 }
6686         }
6687
6688         if (plci->NL.complete == 2)
6689         {
6690                 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6691                     && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6692                 {
6693                         switch (plci->RData[0].P[0])
6694                         {
6695
6696                         case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6697                                 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6698                                         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01X");
6699                                 break;
6700                         case DTMF_UDATA_INDICATION_ANSWER_TONE:
6701                                 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6702                                         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01Y");
6703                                 break;
6704                         case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6705                                 dtmf_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6706                                 break;
6707                         case DTMF_UDATA_INDICATION_DIGITS_SENT:
6708                                 dtmf_confirmation(Id, plci);
6709                                 break;
6710
6711
6712                         case UDATA_INDICATION_MIXER_TAP_DATA:
6713                                 capidtmf_recv_process_block(&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6714                                 i = capidtmf_indication(&(plci->capidtmf_state), dtmf_code_buffer + 1);
6715                                 if (i != 0)
6716                                 {
6717                                         dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6718                                         dtmf_indication(Id, plci, dtmf_code_buffer, (word)(i + 1));
6719                                 }
6720                                 break;
6721
6722
6723                         case UDATA_INDICATION_MIXER_COEFS_SET:
6724                                 mixer_indication_coefs_set(Id, plci);
6725                                 break;
6726                         case UDATA_INDICATION_XCONNECT_FROM:
6727                                 mixer_indication_xconnect_from(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6728                                 break;
6729                         case UDATA_INDICATION_XCONNECT_TO:
6730                                 mixer_indication_xconnect_to(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6731                                 break;
6732
6733
6734                         case LEC_UDATA_INDICATION_DISABLE_DETECT:
6735                                 ec_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6736                                 break;
6737
6738
6739
6740                         default:
6741                                 break;
6742                         }
6743                 }
6744                 else
6745                 {
6746                         if ((plci->RData[0].PLength != 0)
6747                             && ((plci->B2_prot == B2_V120_ASYNC)
6748                                 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6749                                 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6750                         {
6751
6752                                 sendf(plci->appl, _DATA_B3_I, Id, 0,
6753                                       "dwww",
6754                                       plci->RData[1].P,
6755                                       (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6756                                       plci->RNum,
6757                                       plci->RFlags);
6758
6759                         }
6760                         else
6761                         {
6762
6763                                 sendf(plci->appl, _DATA_B3_I, Id, 0,
6764                                       "dwww",
6765                                       plci->RData[0].P,
6766                                       plci->RData[0].PLength,
6767                                       plci->RNum,
6768                                       plci->RFlags);
6769
6770                         }
6771                 }
6772                 return;
6773         }
6774
6775         fax_feature_bits = 0;
6776         if ((plci->NL.Ind & 0x0f) == N_CONNECT ||
6777             (plci->NL.Ind & 0x0f) == N_CONNECT_ACK ||
6778             (plci->NL.Ind & 0x0f) == N_DISC ||
6779             (plci->NL.Ind & 0x0f) == N_EDATA ||
6780             (plci->NL.Ind & 0x0f) == N_DISC_ACK)
6781         {
6782                 info = 0;
6783                 plci->ncpi_buffer[0] = 0;
6784                 switch (plci->B3_prot) {
6785                 case  0: /*XPARENT*/
6786                 case  1: /*T.90 NL*/
6787                         break;    /* no network control protocol info - jfr */
6788                 case  2: /*ISO8202*/
6789                 case  3: /*X25 DCE*/
6790                         for (i = 0; i < plci->NL.RLength; i++) plci->ncpi_buffer[4 + i] = plci->NL.RBuffer->P[i];
6791                         plci->ncpi_buffer[0] = (byte)(i + 3);
6792                         plci->ncpi_buffer[1] = (byte)(plci->NL.Ind & N_D_BIT ? 1 : 0);
6793                         plci->ncpi_buffer[2] = 0;
6794                         plci->ncpi_buffer[3] = 0;
6795                         break;
6796                 case  4: /*T.30 - FAX*/
6797                 case  5: /*T.30 - FAX*/
6798                         if (plci->NL.RLength >= sizeof(T30_INFO))
6799                         {
6800                                 dbug(1, dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6801                                 len = 9;
6802                                 PUT_WORD(&(plci->ncpi_buffer[1]), ((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6803                                 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6804                                 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6805                                 if (plci->B3_prot == 5)
6806                                 {
6807                                         if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6808                                                 i |= 0x8000; /* This is not an ECM connection */
6809                                         if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6810                                                 i |= 0x4000; /* This is a connection with MMR compression */
6811                                         if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6812                                                 i |= 0x2000; /* This is a connection with MR compression */
6813                                         if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6814                                                 i |= 0x0004; /* More documents */
6815                                         if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6816                                                 i |= 0x0002; /* Fax-polling indication */
6817                                 }
6818                                 dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits, i));
6819                                 PUT_WORD(&(plci->ncpi_buffer[3]), i);
6820                                 PUT_WORD(&(plci->ncpi_buffer[5]), ((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6821                                 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6822                                 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6823                                 plci->ncpi_buffer[len] = 0;
6824                                 if (((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6825                                 {
6826                                         plci->ncpi_buffer[len] = 20;
6827                                         for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6828                                                 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6829                                 }
6830                                 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6831                                 {
6832                                         if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6833                                                 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6834                                         else
6835                                                 info = _FAX_PROTOCOL_ERROR;
6836                                 }
6837
6838                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6839                                     & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6840                                 {
6841                                         i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6842                                         while (i < plci->NL.RBuffer->length)
6843                                                 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6844                                 }
6845
6846                                 plci->ncpi_buffer[0] = len;
6847                                 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6848                                 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6849
6850                                 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6851                                 if (((plci->NL.Ind & 0x0f) == N_CONNECT_ACK)
6852                                     || (((plci->NL.Ind & 0x0f) == N_CONNECT)
6853                                         && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6854                                     || (((plci->NL.Ind & 0x0f) == N_EDATA)
6855                                         && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6856                                             || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6857                                             || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6858                                 {
6859                                         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6860                                 }
6861                                 if (((plci->NL.Ind & 0x0f) == N_DISC)
6862                                     || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)
6863                                     || (((plci->NL.Ind & 0x0f) == N_EDATA)
6864                                         && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6865                                 {
6866                                         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6867                                 }
6868                         }
6869                         break;
6870
6871                 case B3_RTP:
6872                         if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6873                         {
6874                                 if (plci->NL.RLength != 0)
6875                                 {
6876                                         info = rtp_info[plci->NL.RBuffer->P[0]];
6877                                         plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6878                                         for (i = 1; i < plci->NL.RLength; i++)
6879                                                 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6880                                 }
6881                         }
6882                         break;
6883
6884                 }
6885                 plci->NL.RNR = 2;
6886         }
6887         switch (plci->NL.Ind & 0x0f) {
6888         case N_EDATA:
6889                 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6890                 {
6891                         dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6892                                         ((T30_INFO *)plci->NL.RBuffer->P)->code));
6893                         fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6894
6895                         if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6896                             && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6897                             && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6898                             && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6899                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6900                             && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6901                         {
6902                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6903                                 sendf(plci->appl, _MANUFACTURER_I, Id, 0, "dwbS", _DI_MANU_ID, _DI_NEGOTIATE_B3,
6904                                       (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6905                                 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6906                                 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6907                                         fax_send_edata_ack = false;
6908                         }
6909
6910                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6911                         {
6912                                 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6913                                 {
6914                                 case EDATA_T30_DIS:
6915                                         if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6916                                             && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6917                                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6918                                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6919                                         {
6920                                                 a->ncci_state[ncci] = INC_ACT_PENDING;
6921                                                 if (plci->B3_prot == 4)
6922                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6923                                                 else
6924                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6925                                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6926                                         }
6927                                         break;
6928
6929                                 case EDATA_T30_TRAIN_OK:
6930                                         if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6931                                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6932                                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6933                                         {
6934                                                 if (plci->B3_prot == 4)
6935                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6936                                                 else
6937                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6938                                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6939                                         }
6940                                         break;
6941
6942                                 case EDATA_T30_EOP_CAPI:
6943                                         if (a->ncci_state[ncci] == CONNECTED)
6944                                         {
6945                                                 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", GOOD, plci->ncpi_buffer);
6946                                                 a->ncci_state[ncci] = INC_DIS_PENDING;
6947                                                 plci->ncpi_state = 0;
6948                                                 fax_send_edata_ack = false;
6949                                         }
6950                                         break;
6951                                 }
6952                         }
6953                         else
6954                         {
6955                                 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6956                                 {
6957                                 case EDATA_T30_TRAIN_OK:
6958                                         if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6959                                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6960                                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6961                                         {
6962                                                 if (plci->B3_prot == 4)
6963                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6964                                                 else
6965                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6966                                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6967                                         }
6968                                         break;
6969                                 }
6970                         }
6971                         if (fax_send_edata_ack)
6972                         {
6973                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6974                                 plci->fax_edata_ack_length = 1;
6975                                 start_internal_command(Id, plci, fax_edata_ack_command);
6976                         }
6977                 }
6978                 else
6979                 {
6980                         dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6981                 }
6982                 break;
6983         case N_CONNECT:
6984                 if (!a->ch_ncci[ch])
6985                 {
6986                         ncci = get_ncci(plci, ch, 0);
6987                         Id = (Id & 0xffff) | (((dword) ncci) << 16);
6988                 }
6989                 dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6990                                 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6991
6992                 msg = _CONNECT_B3_I;
6993                 if (a->ncci_state[ncci] == IDLE)
6994                         plci->channels++;
6995                 else if (plci->B3_prot == 1)
6996                         msg = _CONNECT_B3_T90_ACTIVE_I;
6997
6998                 a->ncci_state[ncci] = INC_CON_PENDING;
6999                 if (plci->B3_prot == 4)
7000                         sendf(plci->appl, msg, Id, 0, "s", "");
7001                 else
7002                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7003                 break;
7004         case N_CONNECT_ACK:
7005                 dbug(1, dprintf("N_connect_Ack"));
7006                 if (plci->internal_command_queue[0]
7007                     && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
7008                         || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
7009                         || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
7010                 {
7011                         (*(plci->internal_command_queue[0]))(Id, plci, 0);
7012                         if (!plci->internal_command)
7013                                 next_internal_command(Id, plci);
7014                         break;
7015                 }
7016                 msg = _CONNECT_B3_ACTIVE_I;
7017                 if (plci->B3_prot == 1)
7018                 {
7019                         if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7020                                 msg = _CONNECT_B3_T90_ACTIVE_I;
7021                         a->ncci_state[ncci] = INC_ACT_PENDING;
7022                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7023                 }
7024                 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7025                 {
7026                         if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7027                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7028                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7029                         {
7030                                 a->ncci_state[ncci] = INC_ACT_PENDING;
7031                                 if (plci->B3_prot == 4)
7032                                         sendf(plci->appl, msg, Id, 0, "s", "");
7033                                 else
7034                                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7035                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7036                         }
7037                 }
7038                 else
7039                 {
7040                         a->ncci_state[ncci] = INC_ACT_PENDING;
7041                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7042                 }
7043                 if (plci->adjust_b_restore)
7044                 {
7045                         plci->adjust_b_restore = false;
7046                         start_internal_command(Id, plci, adjust_b_restore);
7047                 }
7048                 break;
7049         case N_DISC:
7050         case N_DISC_ACK:
7051                 if (plci->internal_command_queue[0]
7052                     && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7053                         || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7054                         || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7055                 {
7056                         (*(plci->internal_command_queue[0]))(Id, plci, 0);
7057                         if (!plci->internal_command)
7058                                 next_internal_command(Id, plci);
7059                 }
7060                 ncci_state = a->ncci_state[ncci];
7061                 ncci_remove(plci, ncci, false);
7062
7063                 /* with N_DISC or N_DISC_ACK the IDI frees the respective   */
7064                 /* channel, so we cannot store the state in ncci_state! The */
7065                 /* information which channel we received a N_DISC is thus   */
7066                 /* stored in the inc_dis_ncci_table buffer.                 */
7067                 for (i = 0; plci->inc_dis_ncci_table[i]; i++);
7068                 plci->inc_dis_ncci_table[i] = (byte) ncci;
7069
7070                 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7071                 if (!plci->channels
7072                     && (plci->B1_resource == 16)
7073                     && (plci->State <= CONNECTED))
7074                 {
7075                         len = 9;
7076                         i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7077                         PUT_WORD(&plci->ncpi_buffer[1], i);
7078                         PUT_WORD(&plci->ncpi_buffer[3], 0);
7079                         i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7080                         PUT_WORD(&plci->ncpi_buffer[5], i);
7081                         PUT_WORD(&plci->ncpi_buffer[7], 0);
7082                         plci->ncpi_buffer[len] = 0;
7083                         plci->ncpi_buffer[0] = len;
7084                         if (plci->B3_prot == 4)
7085                                 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "s", "");
7086                         else
7087                         {
7088
7089                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
7090                                     & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7091                                 {
7092                                         plci->ncpi_buffer[++len] = 0;
7093                                         plci->ncpi_buffer[++len] = 0;
7094                                         plci->ncpi_buffer[++len] = 0;
7095                                         plci->ncpi_buffer[0] = len;
7096                                 }
7097
7098                                 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "S", plci->ncpi_buffer);
7099                         }
7100                         sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7101                         plci->ncpi_state = 0;
7102                         sig_req(plci, HANGUP, 0);
7103                         send_req(plci);
7104                         plci->State = OUTG_DIS_PENDING;
7105                         /* disc here */
7106                 }
7107                 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7108                          && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7109                          && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7110                 {
7111                         if (ncci_state == IDLE)
7112                         {
7113                                 if (plci->channels)
7114                                         plci->channels--;
7115                                 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
7116                                         if (plci->State == SUSPENDING) {
7117                                                 sendf(plci->appl,
7118                                                       _FACILITY_I,
7119                                                       Id & 0xffffL,
7120                                                       0,
7121                                                       "ws", (word)3, "\x03\x04\x00\x00");
7122                                                 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7123                                         }
7124                                         plci_remove(plci);
7125                                         plci->State = IDLE;
7126                                 }
7127                         }
7128                 }
7129                 else if (plci->channels)
7130                 {
7131                         sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7132                         plci->ncpi_state = 0;
7133                         if ((ncci_state == OUTG_REJ_PENDING)
7134                             && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7135                         {
7136                                 sig_req(plci, HANGUP, 0);
7137                                 send_req(plci);
7138                                 plci->State = OUTG_DIS_PENDING;
7139                         }
7140                 }
7141                 break;
7142         case N_RESET:
7143                 a->ncci_state[ncci] = INC_RES_PENDING;
7144                 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7145                 break;
7146         case N_RESET_ACK:
7147                 a->ncci_state[ncci] = CONNECTED;
7148                 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7149                 break;
7150
7151         case N_UDATA:
7152                 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7153                 {
7154                         plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7155                         plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7156                         plci->NL.R = plci->RData;
7157                         plci->NL.RNum = 1;
7158                         return;
7159                 }
7160         case N_BDATA:
7161         case N_DATA:
7162                 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7163                     || (a->ncci_state[ncci] == IDLE)
7164                     || (a->ncci_state[ncci] == INC_DIS_PENDING))
7165                 {
7166                         plci->NL.RNR = 2;
7167                         break;
7168                 }
7169                 if ((a->ncci_state[ncci] != CONNECTED)
7170                     && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7171                     && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7172                 {
7173                         dbug(1, dprintf("flow control"));
7174                         plci->NL.RNR = 1; /* flow control  */
7175                         channel_x_off(plci, ch, 0);
7176                         break;
7177                 }
7178
7179                 NCCIcode = ncci | (((word)a->Id) << 8);
7180
7181                 /* count all buffers within the Application pool    */
7182                 /* belonging to the same NCCI. If this is below the */
7183                 /* number of buffers available per NCCI we accept   */
7184                 /* this packet, otherwise we reject it              */
7185                 count = 0;
7186                 Num = 0xffff;
7187                 for (i = 0; i < APPLptr->MaxBuffer; i++) {
7188                         if (NCCIcode == APPLptr->DataNCCI[i]) count++;
7189                         if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
7190                 }
7191
7192                 if (count >= APPLptr->MaxNCCIData || Num == 0xffff)
7193                 {
7194                         dbug(3, dprintf("Flow-Control"));
7195                         plci->NL.RNR = 1;
7196                         if (++(APPLptr->NCCIDataFlowCtrlTimer) >=
7197                             (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7198                         {
7199                                 plci->NL.RNR = 2;
7200                                 dbug(3, dprintf("DiscardData"));
7201                         } else {
7202                                 channel_x_off(plci, ch, 0);
7203                         }
7204                         break;
7205                 }
7206                 else
7207                 {
7208                         APPLptr->NCCIDataFlowCtrlTimer = 0;
7209                 }
7210
7211                 plci->RData[0].P = ReceiveBufferGet(APPLptr, Num);
7212                 if (!plci->RData[0].P) {
7213                         plci->NL.RNR = 1;
7214                         channel_x_off(plci, ch, 0);
7215                         break;
7216                 }
7217
7218                 APPLptr->DataNCCI[Num] = NCCIcode;
7219                 APPLptr->DataFlags[Num] = (plci->Id << 8) | (plci->NL.Ind >> 4);
7220                 dbug(3, dprintf("Buffer(%d), Max = %d", Num, APPLptr->MaxBuffer));
7221
7222                 plci->RNum = Num;
7223                 plci->RFlags = plci->NL.Ind >> 4;
7224                 plci->RData[0].PLength = APPLptr->MaxDataLength;
7225                 plci->NL.R = plci->RData;
7226                 if ((plci->NL.RLength != 0)
7227                     && ((plci->B2_prot == B2_V120_ASYNC)
7228                         || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7229                         || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7230                 {
7231                         plci->RData[1].P = plci->RData[0].P;
7232                         plci->RData[1].PLength = plci->RData[0].PLength;
7233                         plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7234                         if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7235                                 plci->RData[0].PLength = 1;
7236                         else
7237                                 plci->RData[0].PLength = 2;
7238                         if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7239                                 plci->RFlags |= 0x0010;
7240                         if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7241                                 plci->RFlags |= 0x8000;
7242                         plci->NL.RNum = 2;
7243                 }
7244                 else
7245                 {
7246                         if ((plci->NL.Ind & 0x0f) == N_UDATA)
7247                                 plci->RFlags |= 0x0010;
7248
7249                         else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7250                                 plci->RFlags |= 0x0001;
7251
7252                         plci->NL.RNum = 1;
7253                 }
7254                 break;
7255         case N_DATA_ACK:
7256                 data_ack(plci, ch);
7257                 break;
7258         default:
7259                 plci->NL.RNR = 2;
7260                 break;
7261         }
7262 }
7263
7264 /*------------------------------------------------------------------*/
7265 /* find a free PLCI */
7266 /*------------------------------------------------------------------*/
7267
7268 static word get_plci(DIVA_CAPI_ADAPTER *a)
7269 {
7270         word i, j;
7271         PLCI *plci;
7272
7273         dump_plcis(a);
7274         for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
7275         if (i == a->max_plci) {
7276                 dbug(1, dprintf("get_plci: out of PLCIs"));
7277                 return 0;
7278         }
7279         plci = &a->plci[i];
7280         plci->Id = (byte)(i + 1);
7281
7282         plci->Sig.Id = 0;
7283         plci->NL.Id = 0;
7284         plci->sig_req = 0;
7285         plci->nl_req = 0;
7286
7287         plci->appl = NULL;
7288         plci->relatedPTYPLCI = NULL;
7289         plci->State = IDLE;
7290         plci->SuppState = IDLE;
7291         plci->channels = 0;
7292         plci->tel = 0;
7293         plci->B1_resource = 0;
7294         plci->B2_prot = 0;
7295         plci->B3_prot = 0;
7296
7297         plci->command = 0;
7298         plci->m_command = 0;
7299         init_internal_command_queue(plci);
7300         plci->number = 0;
7301         plci->req_in_start = 0;
7302         plci->req_in = 0;
7303         plci->req_out = 0;
7304         plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7305         plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7306         plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7307
7308         plci->data_sent = false;
7309         plci->send_disc = 0;
7310         plci->sig_global_req = 0;
7311         plci->sig_remove_id = 0;
7312         plci->nl_global_req = 0;
7313         plci->nl_remove_id = 0;
7314         plci->adv_nl = 0;
7315         plci->manufacturer = false;
7316         plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7317         plci->spoofed_msg = 0;
7318         plci->ptyState = 0;
7319         plci->cr_enquiry = false;
7320         plci->hangup_flow_ctrl_timer = 0;
7321
7322         plci->ncci_ring_list = 0;
7323         for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
7324         clear_c_ind_mask(plci);
7325         set_group_ind_mask(plci);
7326         plci->fax_connect_info_length = 0;
7327         plci->nsf_control_bits = 0;
7328         plci->ncpi_state = 0x00;
7329         plci->ncpi_buffer[0] = 0;
7330
7331         plci->requested_options_conn = 0;
7332         plci->requested_options = 0;
7333         plci->notifiedcall = 0;
7334         plci->vswitchstate = 0;
7335         plci->vsprot = 0;
7336         plci->vsprotdialect = 0;
7337         init_b1_config(plci);
7338         dbug(1, dprintf("get_plci(%x)", plci->Id));
7339         return i + 1;
7340 }
7341
7342 /*------------------------------------------------------------------*/
7343 /* put a parameter in the parameter buffer                          */
7344 /*------------------------------------------------------------------*/
7345
7346 static void add_p(PLCI *plci, byte code, byte *p)
7347 {
7348         word p_length;
7349
7350         p_length = 0;
7351         if (p) p_length = p[0];
7352         add_ie(plci, code, p, p_length);
7353 }
7354
7355 /*------------------------------------------------------------------*/
7356 /* put a structure in the parameter buffer                          */
7357 /*------------------------------------------------------------------*/
7358 static void add_s(PLCI *plci, byte code, API_PARSE *p)
7359 {
7360         if (p) add_ie(plci, code, p->info, (word)p->length);
7361 }
7362
7363 /*------------------------------------------------------------------*/
7364 /* put multiple structures in the parameter buffer                  */
7365 /*------------------------------------------------------------------*/
7366 static void add_ss(PLCI *plci, byte code, API_PARSE *p)
7367 {
7368         byte i;
7369
7370         if (p) {
7371                 dbug(1, dprintf("add_ss(%x,len=%d)", code, p->length));
7372                 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7373                         dbug(1, dprintf("add_ss_ie(%x,len=%d)", p->info[i - 1], p->info[i]));
7374                         add_ie(plci, p->info[i - 1], (byte *)&(p->info[i]), (word)p->info[i]);
7375                 }
7376         }
7377 }
7378
7379 /*------------------------------------------------------------------*/
7380 /* return the channel number sent by the application in a esc_chi   */
7381 /*------------------------------------------------------------------*/
7382 static byte getChannel(API_PARSE *p)
7383 {
7384         byte i;
7385
7386         if (p) {
7387                 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7388                         if (p->info[i] == 2) {
7389                                 if (p->info[i - 1] == ESC && p->info[i + 1] == CHI) return (p->info[i + 2]);
7390                         }
7391                 }
7392         }
7393         return 0;
7394 }
7395
7396
7397 /*------------------------------------------------------------------*/
7398 /* put an information element in the parameter buffer               */
7399 /*------------------------------------------------------------------*/
7400
7401 static void add_ie(PLCI *plci, byte code, byte *p, word p_length)
7402 {
7403         word i;
7404
7405         if (!(code & 0x80) && !p_length) return;
7406
7407         if (plci->req_in == plci->req_in_start) {
7408                 plci->req_in += 2;
7409         }
7410         else {
7411                 plci->req_in--;
7412         }
7413         plci->RBuffer[plci->req_in++] = code;
7414
7415         if (p) {
7416                 plci->RBuffer[plci->req_in++] = (byte)p_length;
7417                 for (i = 0; i < p_length; i++) plci->RBuffer[plci->req_in++] = p[1 + i];
7418         }
7419
7420         plci->RBuffer[plci->req_in++] = 0;
7421 }
7422
7423 /*------------------------------------------------------------------*/
7424 /* put a unstructured data into the buffer                          */
7425 /*------------------------------------------------------------------*/
7426
7427 static void add_d(PLCI *plci, word length, byte *p)
7428 {
7429         word i;
7430
7431         if (plci->req_in == plci->req_in_start) {
7432                 plci->req_in += 2;
7433         }
7434         else {
7435                 plci->req_in--;
7436         }
7437         for (i = 0; i < length; i++) plci->RBuffer[plci->req_in++] = p[i];
7438 }
7439
7440 /*------------------------------------------------------------------*/
7441 /* put parameters from the Additional Info parameter in the         */
7442 /* parameter buffer                                                 */
7443 /*------------------------------------------------------------------*/
7444
7445 static void add_ai(PLCI *plci, API_PARSE *ai)
7446 {
7447         word i;
7448         API_PARSE ai_parms[5];
7449
7450         for (i = 0; i < 5; i++) ai_parms[i].length = 0;
7451
7452         if (!ai->length)
7453                 return;
7454         if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7455                 return;
7456
7457         add_s(plci, KEY, &ai_parms[1]);
7458         add_s(plci, UUI, &ai_parms[2]);
7459         add_ss(plci, FTY, &ai_parms[3]);
7460 }
7461
7462 /*------------------------------------------------------------------*/
7463 /* put parameter for b1 protocol in the parameter buffer            */
7464 /*------------------------------------------------------------------*/
7465
7466 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7467                    word b1_facilities)
7468 {
7469         API_PARSE bp_parms[8];
7470         API_PARSE mdm_cfg[9];
7471         API_PARSE global_config[2];
7472         byte cai[256];
7473         byte resource[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7474         byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7475         word i;
7476
7477         API_PARSE mdm_cfg_v18[4];
7478         word j, n, w;
7479         dword d;
7480
7481
7482         for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7483         for (i = 0; i < 2; i++) global_config[i].length = 0;
7484
7485         dbug(1, dprintf("add_b1"));
7486         api_save_msg(bp, "s", &plci->B_protocol);
7487
7488         if (b_channel_info == 2) {
7489                 plci->B1_resource = 0;
7490                 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7491                 add_p(plci, CAI, "\x01\x00");
7492                 dbug(1, dprintf("Cai=1,0 (no resource)"));
7493                 return 0;
7494         }
7495
7496         if (plci->tel == CODEC_PERMANENT) return 0;
7497         else if (plci->tel == CODEC) {
7498                 plci->B1_resource = 1;
7499                 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7500                 add_p(plci, CAI, "\x01\x01");
7501                 dbug(1, dprintf("Cai=1,1 (Codec)"));
7502                 return 0;
7503         }
7504         else if (plci->tel == ADV_VOICE) {
7505                 plci->B1_resource = add_b1_facilities(plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7506                 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7507                 voice_cai[1] = plci->B1_resource;
7508                 PUT_WORD(&voice_cai[5], plci->appl->MaxDataLength);
7509                 add_p(plci, CAI, voice_cai);
7510                 dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai[1]));
7511                 return 0;
7512         }
7513         plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7514         if (plci->call_dir & CALL_DIR_OUT)
7515                 plci->call_dir |= CALL_DIR_ORIGINATE;
7516         else if (plci->call_dir & CALL_DIR_IN)
7517                 plci->call_dir |= CALL_DIR_ANSWER;
7518
7519         if (!bp->length) {
7520                 plci->B1_resource = 0x5;
7521                 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7522                 add_p(plci, CAI, "\x01\x05");
7523                 return 0;
7524         }
7525
7526         dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7527         if (bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7528         if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7529         {
7530                 bp_parms[6].length = 0;
7531                 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7532                 {
7533                         dbug(1, dprintf("b-form.!"));
7534                         return _WRONG_MESSAGE_FORMAT;
7535                 }
7536         }
7537         else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7538         {
7539                 dbug(1, dprintf("b-form.!"));
7540                 return _WRONG_MESSAGE_FORMAT;
7541         }
7542
7543         if (bp_parms[6].length)
7544         {
7545                 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7546                 {
7547                         return _WRONG_MESSAGE_FORMAT;
7548                 }
7549                 switch (GET_WORD(global_config[0].info))
7550                 {
7551                 case 1:
7552                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7553                         break;
7554                 case 2:
7555                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7556                         break;
7557                 }
7558         }
7559         dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7560
7561
7562         if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7563             && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7564         {
7565                 plci->B1_resource = add_b1_facilities(plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7566                 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7567                 cai[1] = plci->B1_resource;
7568                 cai[2] = 0;
7569                 cai[3] = 0;
7570                 cai[4] = 0;
7571                 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7572                 for (i = 0; i < bp_parms[3].length; i++)
7573                         cai[7 + i] = bp_parms[3].info[1 + i];
7574                 cai[0] = 6 + bp_parms[3].length;
7575                 add_p(plci, CAI, cai);
7576                 return 0;
7577         }
7578
7579
7580         if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7581             && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7582         {
7583                 plci->B1_resource = add_b1_facilities(plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7584                 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7585                 cai[1] = plci->B1_resource;
7586                 cai[2] = 0;
7587                 cai[3] = 0;
7588                 cai[4] = 0;
7589                 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7590                 cai[0] = 6;
7591                 add_p(plci, CAI, cai);
7592                 return 0;
7593         }
7594
7595
7596         if ((GET_WORD(bp_parms[0].info) >= 32)
7597             || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7598                 && ((GET_WORD(bp_parms[0].info) != 3)
7599                     || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7600                     || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7601         {
7602                 return _B1_NOT_SUPPORTED;
7603         }
7604         plci->B1_resource = add_b1_facilities(plci, resource[GET_WORD(bp_parms[0].info)],
7605                                               (word)(b1_facilities & ~B1_FACILITY_VOICE));
7606         adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7607         cai[0] = 6;
7608         cai[1] = plci->B1_resource;
7609         for (i = 2; i < sizeof(cai); i++) cai[i] = 0;
7610
7611         if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7612             || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7613             || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7614         { /* B1 - modem */
7615                 for (i = 0; i < 7; i++) mdm_cfg[i].length = 0;
7616
7617                 if (bp_parms[3].length)
7618                 {
7619                         if (api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwww", mdm_cfg))
7620                         {
7621                                 return (_WRONG_MESSAGE_FORMAT);
7622                         }
7623
7624                         cai[2] = 0; /* Bit rate for adaptation */
7625
7626                         dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7627
7628                         PUT_WORD(&cai[13], 0);                          /* Min Tx speed */
7629                         PUT_WORD(&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7630                         PUT_WORD(&cai[17], 0);                          /* Min Rx speed */
7631                         PUT_WORD(&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7632
7633                         cai[3] = 0; /* Async framing parameters */
7634                         switch (GET_WORD(mdm_cfg[2].info))
7635                         {       /* Parity     */
7636                         case 1: /* odd parity */
7637                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7638                                 dbug(1, dprintf("MDM: odd parity"));
7639                                 break;
7640
7641                         case 2: /* even parity */
7642                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7643                                 dbug(1, dprintf("MDM: even parity"));
7644                                 break;
7645
7646                         default:
7647                                 dbug(1, dprintf("MDM: no parity"));
7648                                 break;
7649                         }
7650
7651                         switch (GET_WORD(mdm_cfg[3].info))
7652                         {       /* stop bits   */
7653                         case 1: /* 2 stop bits */
7654                                 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7655                                 dbug(1, dprintf("MDM: 2 stop bits"));
7656                                 break;
7657
7658                         default:
7659                                 dbug(1, dprintf("MDM: 1 stop bit"));
7660                                 break;
7661                         }
7662
7663                         switch (GET_WORD(mdm_cfg[1].info))
7664                         {     /* char length */
7665                         case 5:
7666                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7667                                 dbug(1, dprintf("MDM: 5 bits"));
7668                                 break;
7669
7670                         case 6:
7671                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7672                                 dbug(1, dprintf("MDM: 6 bits"));
7673                                 break;
7674
7675                         case 7:
7676                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7677                                 dbug(1, dprintf("MDM: 7 bits"));
7678                                 break;
7679
7680                         default:
7681                                 dbug(1, dprintf("MDM: 8 bits"));
7682                                 break;
7683                         }
7684
7685                         cai[7] = 0; /* Line taking options */
7686                         cai[8] = 0; /* Modulation negotiation options */
7687                         cai[9] = 0; /* Modulation options */
7688
7689                         if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7690                         {
7691                                 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7692                                 dbug(1, dprintf("MDM: Reverse direction"));
7693                         }
7694
7695                         if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7696                         {
7697                                 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7698                                 dbug(1, dprintf("MDM: Disable retrain"));
7699                         }
7700
7701                         if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7702                         {
7703                                 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7704                                 dbug(1, dprintf("MDM: Disable ring tone"));
7705                         }
7706
7707                         if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7708                         {
7709                                 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7710                                 dbug(1, dprintf("MDM: 1800 guard tone"));
7711                         }
7712                         else if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_550)
7713                         {
7714                                 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7715                                 dbug(1, dprintf("MDM: 550 guard tone"));
7716                         }
7717
7718                         if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7719                         {
7720                                 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7721                                 dbug(1, dprintf("MDM: V100"));
7722                         }
7723                         else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7724                         {
7725                                 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7726                                 dbug(1, dprintf("MDM: IN CLASS"));
7727                         }
7728                         else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7729                         {
7730                                 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7731                                 dbug(1, dprintf("MDM: DISABLED"));
7732                         }
7733                         cai[0] = 20;
7734
7735                         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7736                             && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7737                         {
7738                                 plci->requested_options |= 1L << PRIVATE_V18;
7739                         }
7740                         if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7741                                 plci->requested_options |= 1L << PRIVATE_VOWN;
7742
7743                         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
7744                             & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7745                         {
7746                                 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwws", mdm_cfg))
7747                                 {
7748                                         i = 27;
7749                                         if (mdm_cfg[6].length >= 4)
7750                                         {
7751                                                 d = GET_DWORD(&mdm_cfg[6].info[1]);
7752                                                 cai[7] |= (byte) d;          /* line taking options */
7753                                                 cai[9] |= (byte)(d >> 8);    /* modulation options */
7754                                                 cai[++i] = (byte)(d >> 16);  /* vown modulation options */
7755                                                 cai[++i] = (byte)(d >> 24);
7756                                                 if (mdm_cfg[6].length >= 8)
7757                                                 {
7758                                                         d = GET_DWORD(&mdm_cfg[6].info[5]);
7759                                                         cai[10] |= (byte) d;        /* disabled modulations mask */
7760                                                         cai[11] |= (byte)(d >> 8);
7761                                                         if (mdm_cfg[6].length >= 12)
7762                                                         {
7763                                                                 d = GET_DWORD(&mdm_cfg[6].info[9]);
7764                                                                 cai[12] = (byte) d;          /* enabled modulations mask */
7765                                                                 cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */
7766                                                                 cai[++i] = (byte)(d >> 16);
7767                                                                 cai[++i] = (byte)(d >> 24);
7768                                                                 cai[++i] = 0;
7769                                                                 if (mdm_cfg[6].length >= 14)
7770                                                                 {
7771                                                                         w = GET_WORD(&mdm_cfg[6].info[13]);
7772                                                                         if (w != 0)
7773                                                                                 PUT_WORD(&cai[13], w);  /* min tx speed */
7774                                                                         if (mdm_cfg[6].length >= 16)
7775                                                                         {
7776                                                                                 w = GET_WORD(&mdm_cfg[6].info[15]);
7777                                                                                 if (w != 0)
7778                                                                                         PUT_WORD(&cai[15], w);  /* max tx speed */
7779                                                                                 if (mdm_cfg[6].length >= 18)
7780                                                                                 {
7781                                                                                         w = GET_WORD(&mdm_cfg[6].info[17]);
7782                                                                                         if (w != 0)
7783                                                                                                 PUT_WORD(&cai[17], w);  /* min rx speed */
7784                                                                                         if (mdm_cfg[6].length >= 20)
7785                                                                                         {
7786                                                                                                 w = GET_WORD(&mdm_cfg[6].info[19]);
7787                                                                                                 if (w != 0)
7788                                                                                                         PUT_WORD(&cai[19], w);  /* max rx speed */
7789                                                                                                 if (mdm_cfg[6].length >= 22)
7790                                                                                                 {
7791                                                                                                         w = GET_WORD(&mdm_cfg[6].info[21]);
7792                                                                                                         cai[23] = (byte)(-((short) w));  /* transmit level */
7793                                                                                                         if (mdm_cfg[6].length >= 24)
7794                                                                                                         {
7795                                                                                                                 w = GET_WORD(&mdm_cfg[6].info[23]);
7796                                                                                                                 cai[22] |= (byte) w;        /* info options mask */
7797                                                                                                                 cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */
7798                                                                                                         }
7799                                                                                                 }
7800                                                                                         }
7801                                                                                 }
7802                                                                         }
7803                                                                 }
7804                                                         }
7805                                                 }
7806                                         }
7807                                         cai[27] = i - 27;
7808                                         i++;
7809                                         if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwwss", mdm_cfg))
7810                                         {
7811                                                 if (!api_parse(&mdm_cfg[7].info[1], (word)mdm_cfg[7].length, "sss", mdm_cfg_v18))
7812                                                 {
7813                                                         for (n = 0; n < 3; n++)
7814                                                         {
7815                                                                 cai[i] = (byte)(mdm_cfg_v18[n].length);
7816                                                                 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7817                                                                         cai[i + j] = mdm_cfg_v18[n].info[j];
7818                                                                 i += cai[i] + 1;
7819                                                         }
7820                                                 }
7821                                         }
7822                                         cai[0] = (byte)(i - 1);
7823                                 }
7824                         }
7825
7826                 }
7827         }
7828         if (GET_WORD(bp_parms[0].info) == 2 ||                         /* V.110 async */
7829             GET_WORD(bp_parms[0].info) == 3)                           /* V.110 sync */
7830         {
7831                 if (bp_parms[3].length) {
7832                         dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms[3].info[1])));
7833                         switch (GET_WORD(&bp_parms[3].info[1])) {                 /* Rate */
7834                         case 0:
7835                         case 56000:
7836                                 if (GET_WORD(bp_parms[0].info) == 3) {                  /* V.110 sync 56k */
7837                                         dbug(1, dprintf("56k sync HSCX"));
7838                                         cai[1] = 8;
7839                                         cai[2] = 0;
7840                                         cai[3] = 0;
7841                                 }
7842                                 else if (GET_WORD(bp_parms[0].info) == 2) {
7843                                         dbug(1, dprintf("56k async DSP"));
7844                                         cai[2] = 9;
7845                                 }
7846                                 break;
7847                         case 50:     cai[2] = 1;  break;
7848                         case 75:     cai[2] = 1;  break;
7849                         case 110:    cai[2] = 1;  break;
7850                         case 150:    cai[2] = 1;  break;
7851                         case 200:    cai[2] = 1;  break;
7852                         case 300:    cai[2] = 1;  break;
7853                         case 600:    cai[2] = 1;  break;
7854                         case 1200:   cai[2] = 2;  break;
7855                         case 2400:   cai[2] = 3;  break;
7856                         case 4800:   cai[2] = 4;  break;
7857                         case 7200:   cai[2] = 10; break;
7858                         case 9600:   cai[2] = 5;  break;
7859                         case 12000:  cai[2] = 13; break;
7860                         case 24000:  cai[2] = 0;  break;
7861                         case 14400:  cai[2] = 11; break;
7862                         case 19200:  cai[2] = 6;  break;
7863                         case 28800:  cai[2] = 12; break;
7864                         case 38400:  cai[2] = 7;  break;
7865                         case 48000:  cai[2] = 8;  break;
7866                         case 76:     cai[2] = 15; break;  /* 75/1200     */
7867                         case 1201:   cai[2] = 14; break;  /* 1200/75     */
7868                         case 56001:  cai[2] = 9;  break;  /* V.110 56000 */
7869
7870                         default:
7871                                 return _B1_PARM_NOT_SUPPORTED;
7872                         }
7873                         cai[3] = 0;
7874                         if (cai[1] == 13)                                        /* v.110 async */
7875                         {
7876                                 if (bp_parms[3].length >= 8)
7877                                 {
7878                                         switch (GET_WORD(&bp_parms[3].info[3]))
7879                                         {       /* char length */
7880                                         case 5:
7881                                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7882                                                 break;
7883                                         case 6:
7884                                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7885                                                 break;
7886                                         case 7:
7887                                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7888                                                 break;
7889                                         }
7890                                         switch (GET_WORD(&bp_parms[3].info[5]))
7891                                         {       /* Parity     */
7892                                         case 1: /* odd parity */
7893                                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7894                                                 break;
7895                                         case 2: /* even parity */
7896                                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7897                                                 break;
7898                                         }
7899                                         switch (GET_WORD(&bp_parms[3].info[7]))
7900                                         {       /* stop bits   */
7901                                         case 1: /* 2 stop bits */
7902                                                 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7903                                                 break;
7904                                         }
7905                                 }
7906                         }
7907                 }
7908                 else if (cai[1] == 8 || GET_WORD(bp_parms[0].info) == 3) {
7909                         dbug(1, dprintf("V.110 default 56k sync"));
7910                         cai[1] = 8;
7911                         cai[2] = 0;
7912                         cai[3] = 0;
7913                 }
7914                 else {
7915                         dbug(1, dprintf("V.110 default 9600 async"));
7916                         cai[2] = 5;
7917                 }
7918         }
7919         PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7920         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]));
7921 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7922
7923         add_p(plci, CAI, cai);
7924         return 0;
7925 }
7926
7927 /*------------------------------------------------------------------*/
7928 /* put parameter for b2 and B3  protocol in the parameter buffer    */
7929 /*------------------------------------------------------------------*/
7930
7931 static word add_b23(PLCI *plci, API_PARSE *bp)
7932 {
7933         word i, fax_control_bits;
7934         byte pos, len;
7935         byte SAPI = 0x40;  /* default SAPI 16 for x.31 */
7936         API_PARSE bp_parms[8];
7937         API_PARSE *b1_config;
7938         API_PARSE *b2_config;
7939         API_PARSE b2_config_parms[8];
7940         API_PARSE *b3_config;
7941         API_PARSE b3_config_parms[6];
7942         API_PARSE global_config[2];
7943
7944         static byte llc[3] = {2,0,0};
7945         static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7946         static byte nlc[256];
7947         static byte lli[12] = {1,1};
7948
7949         const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7950         const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7951
7952         const byte llc3[] = {4,3,2,2,6,6,0};
7953         const byte header[] = {0,2,3,3,0,0,0};
7954
7955         for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7956         for (i = 0; i < 6; i++) b2_config_parms[i].length = 0;
7957         for (i = 0; i < 5; i++) b3_config_parms[i].length = 0;
7958
7959         lli[0] = 1;
7960         lli[1] = 1;
7961         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7962                 lli[1] |= 2;
7963         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7964                 lli[1] |= 4;
7965
7966         if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7967                 lli[1] |= 0x10;
7968                 if (plci->rx_dma_descriptor <= 0) {
7969                         plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
7970                         if (plci->rx_dma_descriptor >= 0)
7971                                 plci->rx_dma_descriptor++;
7972                 }
7973                 if (plci->rx_dma_descriptor > 0) {
7974                         lli[0] = 6;
7975                         lli[1] |= 0x40;
7976                         lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7977                         lli[3] = (byte)plci->rx_dma_magic;
7978                         lli[4] = (byte)(plci->rx_dma_magic >>  8);
7979                         lli[5] = (byte)(plci->rx_dma_magic >> 16);
7980                         lli[6] = (byte)(plci->rx_dma_magic >> 24);
7981                 }
7982         }
7983
7984         if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7985                 lli[1] |= 0x20;
7986         }
7987
7988         dbug(1, dprintf("add_b23"));
7989         api_save_msg(bp, "s", &plci->B_protocol);
7990
7991         if (!bp->length && plci->tel)
7992         {
7993                 plci->adv_nl = true;
7994                 dbug(1, dprintf("Default adv.Nl"));
7995                 add_p(plci, LLI, lli);
7996                 plci->B2_prot = 1 /*XPARENT*/;
7997                 plci->B3_prot = 0 /*XPARENT*/;
7998                 llc[1] = 2;
7999                 llc[2] = 4;
8000                 add_p(plci, LLC, llc);
8001                 dlc[0] = 2;
8002                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8003                 add_p(plci, DLC, dlc);
8004                 return 0;
8005         }
8006
8007         if (!bp->length) /*default*/
8008         {
8009                 dbug(1, dprintf("ret default"));
8010                 add_p(plci, LLI, lli);
8011                 plci->B2_prot = 0 /*X.75   */;
8012                 plci->B3_prot = 0 /*XPARENT*/;
8013                 llc[1] = 1;
8014                 llc[2] = 4;
8015                 add_p(plci, LLC, llc);
8016                 dlc[0] = 2;
8017                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8018                 add_p(plci, DLC, dlc);
8019                 return 0;
8020         }
8021         dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
8022         if ((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT;
8023
8024         if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8025         {
8026                 bp_parms[6].length = 0;
8027                 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8028                 {
8029                         dbug(1, dprintf("b-form.!"));
8030                         return _WRONG_MESSAGE_FORMAT;
8031                 }
8032         }
8033         else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8034         {
8035                 dbug(1, dprintf("b-form.!"));
8036                 return _WRONG_MESSAGE_FORMAT;
8037         }
8038
8039         if (plci->tel == ADV_VOICE) /* transparent B on advanced voice */
8040         {
8041                 if (GET_WORD(bp_parms[1].info) != 1
8042                     || GET_WORD(bp_parms[2].info) != 0) return _B2_NOT_SUPPORTED;
8043                 plci->adv_nl = true;
8044         }
8045         else if (plci->tel) return _B2_NOT_SUPPORTED;
8046
8047
8048         if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8049             && (GET_WORD(bp_parms[2].info) == B3_RTP)
8050             && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8051         {
8052                 add_p(plci, LLI, lli);
8053                 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8054                 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8055                 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8056                 llc[2] = 4;
8057                 add_p(plci, LLC, llc);
8058                 dlc[0] = 2;
8059                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8060                 dlc[3] = 3; /* Addr A */
8061                 dlc[4] = 1; /* Addr B */
8062                 dlc[5] = 7; /* modulo mode */
8063                 dlc[6] = 7; /* window size */
8064                 dlc[7] = 0; /* XID len Lo  */
8065                 dlc[8] = 0; /* XID len Hi  */
8066                 for (i = 0; i < bp_parms[4].length; i++)
8067                         dlc[9 + i] = bp_parms[4].info[1 + i];
8068                 dlc[0] = (byte)(8 + bp_parms[4].length);
8069                 add_p(plci, DLC, dlc);
8070                 for (i = 0; i < bp_parms[5].length; i++)
8071                         nlc[1 + i] = bp_parms[5].info[1 + i];
8072                 nlc[0] = (byte)(bp_parms[5].length);
8073                 add_p(plci, NLC, nlc);
8074                 return 0;
8075         }
8076
8077
8078
8079         if ((GET_WORD(bp_parms[1].info) >= 32)
8080             || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8081                 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8082                     || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8083
8084         {
8085                 return _B2_NOT_SUPPORTED;
8086         }
8087         if ((GET_WORD(bp_parms[2].info) >= 32)
8088             || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8089         {
8090                 return _B3_NOT_SUPPORTED;
8091         }
8092         if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8093             && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8094                 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8095                 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8096         {
8097                 return (add_modem_b23(plci, bp_parms));
8098         }
8099
8100         add_p(plci, LLI, lli);
8101
8102         plci->B2_prot = (byte)GET_WORD(bp_parms[1].info);
8103         plci->B3_prot = (byte)GET_WORD(bp_parms[2].info);
8104         if (plci->B2_prot == 12) SAPI = 0; /* default SAPI D-channel */
8105
8106         if (bp_parms[6].length)
8107         {
8108                 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8109                 {
8110                         return _WRONG_MESSAGE_FORMAT;
8111                 }
8112                 switch (GET_WORD(global_config[0].info))
8113                 {
8114                 case 1:
8115                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8116                         break;
8117                 case 2:
8118                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8119                         break;
8120                 }
8121         }
8122         dbug(1, dprintf("call_dir=%04x", plci->call_dir));
8123
8124
8125         if (plci->B2_prot == B2_PIAFS)
8126                 llc[1] = PIAFS_CRC;
8127         else
8128 /* IMPLEMENT_PIAFS */
8129         {
8130                 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8131                         llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8132         }
8133         llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8134
8135         add_p(plci, LLC, llc);
8136
8137         dlc[0] = 2;
8138         PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8139                  header[GET_WORD(bp_parms[2].info)]);
8140
8141         b1_config = &bp_parms[3];
8142         nlc[0] = 0;
8143         if (plci->B3_prot == 4
8144             || plci->B3_prot == 5)
8145         {
8146                 for (i = 0; i < sizeof(T30_INFO); i++) nlc[i] = 0;
8147                 nlc[0] = sizeof(T30_INFO);
8148                 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8149                         ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8150                 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8151                 if (b1_config->length >= 2)
8152                 {
8153                         ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1]) / 2400);
8154                 }
8155         }
8156         b2_config = &bp_parms[4];
8157
8158
8159         if (llc[1] == PIAFS_CRC)
8160         {
8161                 if (plci->B3_prot != B3_TRANSPARENT)
8162                 {
8163                         return _B_STACK_NOT_SUPPORTED;
8164                 }
8165                 if (b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8166                         return _WRONG_MESSAGE_FORMAT;
8167                 }
8168                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8169                 dlc[3] = 0; /* Addr A */
8170                 dlc[4] = 0; /* Addr B */
8171                 dlc[5] = 0; /* modulo mode */
8172                 dlc[6] = 0; /* window size */
8173                 if (b2_config->length >= 7) {
8174                         dlc[7] = 7;
8175                         dlc[8] = 0;
8176                         dlc[9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8177                         dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8178                         dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8179                         dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8180                         dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8181                         dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8182                         dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8183                         dlc[0] = 15;
8184                         if (b2_config->length >= 8) { /* PIAFS control abilities */
8185                                 dlc[7] = 10;
8186                                 dlc[16] = 2; /* Length of PIAFS extension */
8187                                 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8188                                 dlc[18] = b2_config_parms[4].info[0]; /* value */
8189                                 dlc[0] = 18;
8190                         }
8191                 }
8192                 else /* default values, 64K, variable, no compression */
8193                 {
8194                         dlc[7] = 7;
8195                         dlc[8] = 0;
8196                         dlc[9] = 0x03; /* PIAFS protocol Speed configuration */
8197                         dlc[10] = 0x03; /* V.42bis P0 */
8198                         dlc[11] = 0;    /* V.42bis P0 */
8199                         dlc[12] = 0;    /* V.42bis P1 */
8200                         dlc[13] = 0;    /* V.42bis P1 */
8201                         dlc[14] = 0;    /* V.42bis P2 */
8202                         dlc[15] = 0;    /* V.42bis P2 */
8203                         dlc[0] = 15;
8204                 }
8205                 add_p(plci, DLC, dlc);
8206         }
8207         else
8208
8209                 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8210                 {
8211                         if (plci->B3_prot != B3_TRANSPARENT)
8212                                 return _B_STACK_NOT_SUPPORTED;
8213
8214                         dlc[0] = 6;
8215                         PUT_WORD(&dlc[1], GET_WORD(&dlc[1]) + 2);
8216                         dlc[3] = 0x08;
8217                         dlc[4] = 0x01;
8218                         dlc[5] = 127;
8219                         dlc[6] = 7;
8220                         if (b2_config->length != 0)
8221                         {
8222                                 if ((llc[1] == V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8223                                         return _WRONG_MESSAGE_FORMAT;
8224                                 }
8225                                 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8226                                 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8227                                 if (b2_config->info[3] != 128)
8228                                 {
8229                                         dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8230                                         return _B2_PARM_NOT_SUPPORTED;
8231                                 }
8232                                 dlc[5] = (byte)(b2_config->info[3] - 1);
8233                                 dlc[6] = b2_config->info[4];
8234                                 if (llc[1] == V120_V42BIS) {
8235                                         if (b2_config->length >= 10) {
8236                                                 dlc[7] = 6;
8237                                                 dlc[8] = 0;
8238                                                 dlc[9] = b2_config_parms[4].info[0];
8239                                                 dlc[10] = b2_config_parms[4].info[1];
8240                                                 dlc[11] = b2_config_parms[5].info[0];
8241                                                 dlc[12] = b2_config_parms[5].info[1];
8242                                                 dlc[13] = b2_config_parms[6].info[0];
8243                                                 dlc[14] = b2_config_parms[6].info[1];
8244                                                 dlc[0] = 14;
8245                                                 dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8246                                                 dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8247                                                 dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8248                                         }
8249                                         else {
8250                                                 dlc[6] = 14;
8251                                         }
8252                                 }
8253                         }
8254                 }
8255                 else
8256                 {
8257                         if (b2_config->length)
8258                         {
8259                                 dbug(1, dprintf("B2-Config"));
8260                                 if (llc[1] == X75_V42BIS) {
8261                                         if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8262                                         {
8263                                                 return _WRONG_MESSAGE_FORMAT;
8264                                         }
8265                                 }
8266                                 else {
8267                                         if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8268                                         {
8269                                                 return _WRONG_MESSAGE_FORMAT;
8270                                         }
8271                                 }
8272                                 /* if B2 Protocol is LAPD, b2_config structure is different */
8273                                 if (llc[1] == 6)
8274                                 {
8275                                         dlc[0] = 4;
8276                                         if (b2_config->length >= 1) dlc[2] = b2_config->info[1];      /* TEI */
8277                                         else dlc[2] = 0x01;
8278                                         if ((b2_config->length >= 2) && (plci->B2_prot == 12))
8279                                         {
8280                                                 SAPI = b2_config->info[2];    /* SAPI */
8281                                         }
8282                                         dlc[1] = SAPI;
8283                                         if ((b2_config->length >= 3) && (b2_config->info[3] == 128))
8284                                         {
8285                                                 dlc[3] = 127;      /* Mode */
8286                                         }
8287                                         else
8288                                         {
8289                                                 dlc[3] = 7;        /* Mode */
8290                                         }
8291
8292                                         if (b2_config->length >= 4) dlc[4] = b2_config->info[4];      /* Window */
8293                                         else dlc[4] = 1;
8294                                         dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8295                                         if (b2_config->length > 5) return _B2_PARM_NOT_SUPPORTED;
8296                                 }
8297                                 else
8298                                 {
8299                                         dlc[0] = (byte)(b2_config_parms[4].length + 6);
8300                                         dlc[3] = b2_config->info[1];
8301                                         dlc[4] = b2_config->info[2];
8302                                         if (b2_config->info[3] != 8 && b2_config->info[3] != 128) {
8303                                                 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8304                                                 return _B2_PARM_NOT_SUPPORTED;
8305                                         }
8306
8307                                         dlc[5] = (byte)(b2_config->info[3] - 1);
8308                                         dlc[6] = b2_config->info[4];
8309                                         if (dlc[6] > dlc[5]) {
8310                                                 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]));
8311                                                 return _B2_PARM_NOT_SUPPORTED;
8312                                         }
8313
8314                                         if (llc[1] == X75_V42BIS) {
8315                                                 if (b2_config->length >= 10) {
8316                                                         dlc[7] = 6;
8317                                                         dlc[8] = 0;
8318                                                         dlc[9] = b2_config_parms[4].info[0];
8319                                                         dlc[10] = b2_config_parms[4].info[1];
8320                                                         dlc[11] = b2_config_parms[5].info[0];
8321                                                         dlc[12] = b2_config_parms[5].info[1];
8322                                                         dlc[13] = b2_config_parms[6].info[0];
8323                                                         dlc[14] = b2_config_parms[6].info[1];
8324                                                         dlc[0] = 14;
8325                                                         dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8326                                                         dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8327                                                         dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8328                                                 }
8329                                                 else {
8330                                                         dlc[6] = 14;
8331                                                 }
8332
8333                                         }
8334                                         else {
8335                                                 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8336                                                 for (i = 0; i < b2_config_parms[4].length; i++)
8337                                                         dlc[11 + i] = b2_config_parms[4].info[1 + i];
8338                                         }
8339                                 }
8340                         }
8341                 }
8342         add_p(plci, DLC, dlc);
8343
8344         b3_config = &bp_parms[5];
8345         if (b3_config->length)
8346         {
8347                 if (plci->B3_prot == 4
8348                     || plci->B3_prot == 5)
8349                 {
8350                         if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8351                         {
8352                                 return _WRONG_MESSAGE_FORMAT;
8353                         }
8354                         i = GET_WORD((byte *)(b3_config_parms[0].info));
8355                         ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8356                                                                     ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8357                         ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8358                         fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8359                         if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8360                                 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8361                         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8362                         {
8363
8364                                 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8365                                     & (1L << PRIVATE_FAX_PAPER_FORMATS))
8366                                 {
8367                                         ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8368                                                 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8369                                                 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8370                                 }
8371
8372                                 ((T30_INFO *)&nlc[1])->recording_properties =
8373                                         T30_RECORDING_WIDTH_ISO_A3 |
8374                                         (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8375                                         (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8376                         }
8377                         if (plci->B3_prot == 5)
8378                         {
8379                                 if (i & 0x0002) /* Accept incoming fax-polling requests */
8380                                         fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8381                                 if (i & 0x2000) /* Do not use MR compression */
8382                                         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8383                                 if (i & 0x4000) /* Do not use MMR compression */
8384                                         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8385                                 if (i & 0x8000) /* Do not use ECM */
8386                                         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8387                                 if (plci->fax_connect_info_length != 0)
8388                                 {
8389                                         ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8390                                         ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8391                                         ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8392                                         fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8393                                                 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8394                                 }
8395                         }
8396                         /* copy station id to NLC */
8397                         for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
8398                         {
8399                                 if (i < b3_config_parms[2].length)
8400                                 {
8401                                         ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1 + i];
8402                                 }
8403                                 else
8404                                 {
8405                                         ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8406                                 }
8407                         }
8408                         ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8409                         /* copy head line to NLC */
8410                         if (b3_config_parms[3].length)
8411                         {
8412
8413                                 pos = (byte)(fax_head_line_time(&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8414                                 if (pos != 0)
8415                                 {
8416                                         if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8417                                                 pos = 0;
8418                                         else
8419                                         {
8420                                                 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8421                                                 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8422                                                 len = (byte)b3_config_parms[2].length;
8423                                                 if (len > 20)
8424                                                         len = 20;
8425                                                 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8426                                                 {
8427                                                         for (i = 0; i < len; i++)
8428                                                                 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1 + i];
8429                                                         nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8430                                                         nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8431                                                 }
8432                                         }
8433                                 }
8434
8435                                 len = (byte)b3_config_parms[3].length;
8436                                 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8437                                         len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8438                                 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8439                                 nlc[0] += (byte)(pos + len);
8440                                 for (i = 0; i < len; i++)
8441                                         nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] =  ((byte *)b3_config_parms[3].info)[1 + i];
8442                         } else
8443                                 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8444
8445                         plci->nsf_control_bits = 0;
8446                         if (plci->B3_prot == 5)
8447                         {
8448                                 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8449                                     && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8450                                 {
8451                                         plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8452                                 }
8453                                 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8454                                     && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8455                                 {
8456                                         plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8457                                 }
8458                                 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8459                                     & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8460                                 {
8461                                         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8462                                             & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8463                                         {
8464                                                 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8465                                                 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8466                                                         fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8467                                         }
8468                                         len = nlc[0];
8469                                         pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8470                                         if (pos < plci->fax_connect_info_length)
8471                                         {
8472                                                 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8473                                                         nlc[++len] = plci->fax_connect_info_buffer[pos++];
8474                                         }
8475                                         else
8476                                                 nlc[++len] = 0;
8477                                         if (pos < plci->fax_connect_info_length)
8478                                         {
8479                                                 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8480                                                         nlc[++len] = plci->fax_connect_info_buffer[pos++];
8481                                         }
8482                                         else
8483                                                 nlc[++len] = 0;
8484                                         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8485                                             & (1L << PRIVATE_FAX_NONSTANDARD))
8486                                         {
8487                                                 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8488                                                 {
8489                                                         if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos + 1] >= 2))
8490                                                                 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos + 2]);
8491                                                         for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8492                                                                 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8493                                                 }
8494                                                 else
8495                                                 {
8496                                                         if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8497                                                         {
8498                                                                 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8499                                                                 nlc[++len] = 0;
8500                                                         }
8501                                                         else
8502                                                         {
8503                                                                 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8504                                                                         plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8505                                                                 nlc[++len] = (byte)(b3_config_parms[4].length);
8506                                                                 for (i = 0; i < b3_config_parms[4].length; i++)
8507                                                                         nlc[++len] = b3_config_parms[4].info[1 + i];
8508                                                         }
8509                                                 }
8510                                         }
8511                                         nlc[0] = len;
8512                                         if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8513                                             && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8514                                         {
8515                                                 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8516                                         }
8517                                 }
8518                         }
8519
8520                         PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8521                         len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8522                         for (i = 0; i < len; i++)
8523                                 plci->fax_connect_info_buffer[i] = nlc[1 + i];
8524                         ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8525                         i += ((T30_INFO *)&nlc[1])->head_line_len;
8526                         while (i < nlc[0])
8527                                 plci->fax_connect_info_buffer[len++] = nlc[++i];
8528                         plci->fax_connect_info_length = len;
8529                 }
8530                 else
8531                 {
8532                         nlc[0] = 14;
8533                         if (b3_config->length != 16)
8534                                 return _B3_PARM_NOT_SUPPORTED;
8535                         for (i = 0; i < 12; i++) nlc[1 + i] = b3_config->info[1 + i];
8536                         if (GET_WORD(&b3_config->info[13]) != 8 && GET_WORD(&b3_config->info[13]) != 128)
8537                                 return _B3_PARM_NOT_SUPPORTED;
8538                         nlc[13] = b3_config->info[13];
8539                         if (GET_WORD(&b3_config->info[15]) >= nlc[13])
8540                                 return _B3_PARM_NOT_SUPPORTED;
8541                         nlc[14] = b3_config->info[15];
8542                 }
8543         }
8544         else
8545         {
8546                 if (plci->B3_prot == 4
8547                     || plci->B3_prot == 5 /*T.30 - FAX*/) return _B3_PARM_NOT_SUPPORTED;
8548         }
8549         add_p(plci, NLC, nlc);
8550         return 0;
8551 }
8552
8553 /*----------------------------------------------------------------*/
8554 /*      make the same as add_b23, but only for the modem related  */
8555 /*      L2 and L3 B-Chan protocol.                                */
8556 /*                                                                */
8557 /*      Enabled L2 and L3 Configurations:                         */
8558 /*        If L1 == Modem all negotiation                          */
8559 /*          only L2 == Modem with full negotiation is allowed     */
8560 /*        If L1 == Modem async or sync                            */
8561 /*          only L2 == Transparent is allowed                     */
8562 /*        L3 == Modem or L3 == Transparent are allowed            */
8563 /*      B2 Configuration for modem:                               */
8564 /*          word : enable/disable compression, bitoptions         */
8565 /*      B3 Configuration for modem:                               */
8566 /*          empty                                                 */
8567 /*----------------------------------------------------------------*/
8568 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms)
8569 {
8570         static byte lli[12] = {1,1};
8571         static byte llc[3] = {2,0,0};
8572         static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8573         API_PARSE mdm_config[2];
8574         word i;
8575         word b2_config = 0;
8576
8577         for (i = 0; i < 2; i++) mdm_config[i].length = 0;
8578         for (i = 0; i < sizeof(dlc); i++) dlc[i] = 0;
8579
8580         if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8581              && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8582             || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8583                 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8584         {
8585                 return (_B_STACK_NOT_SUPPORTED);
8586         }
8587         if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8588             && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8589         {
8590                 return (_B_STACK_NOT_SUPPORTED);
8591         }
8592
8593         plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8594         plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8595
8596         if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8597         {
8598                 if (api_parse(&bp_parms[4].info[1],
8599                               (word)bp_parms[4].length, "w",
8600                               mdm_config))
8601                 {
8602                         return (_WRONG_MESSAGE_FORMAT);
8603                 }
8604                 b2_config = GET_WORD(mdm_config[0].info);
8605         }
8606
8607         /* OK, L2 is modem */
8608
8609         lli[0] = 1;
8610         lli[1] = 1;
8611         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8612                 lli[1] |= 2;
8613         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8614                 lli[1] |= 4;
8615
8616         if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8617                 lli[1] |= 0x10;
8618                 if (plci->rx_dma_descriptor <= 0) {
8619                         plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
8620                         if (plci->rx_dma_descriptor >= 0)
8621                                 plci->rx_dma_descriptor++;
8622                 }
8623                 if (plci->rx_dma_descriptor > 0) {
8624                         lli[1] |= 0x40;
8625                         lli[0] = 6;
8626                         lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8627                         lli[3] = (byte)plci->rx_dma_magic;
8628                         lli[4] = (byte)(plci->rx_dma_magic >>  8);
8629                         lli[5] = (byte)(plci->rx_dma_magic >> 16);
8630                         lli[6] = (byte)(plci->rx_dma_magic >> 24);
8631                 }
8632         }
8633
8634         if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8635                 lli[1] |= 0x20;
8636         }
8637
8638         llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8639                 /*V42*/ 10 : /*V42_IN*/ 9;
8640         llc[2] = 4;                      /* pass L3 always transparent */
8641         add_p(plci, LLI, lli);
8642         add_p(plci, LLC, llc);
8643         i =  1;
8644         PUT_WORD(&dlc[i], plci->appl->MaxDataLength);
8645         i += 2;
8646         if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8647         {
8648                 if (bp_parms[4].length)
8649                 {
8650                         dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8651                         dlc[i++] = 3; /* Addr A */
8652                         dlc[i++] = 1; /* Addr B */
8653                         dlc[i++] = 7; /* modulo mode */
8654                         dlc[i++] = 7; /* window size */
8655                         dlc[i++] = 0; /* XID len Lo  */
8656                         dlc[i++] = 0; /* XID len Hi  */
8657
8658                         if (b2_config & MDM_B2_DISABLE_V42bis)
8659                         {
8660                                 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8661                         }
8662                         if (b2_config & MDM_B2_DISABLE_MNP)
8663                         {
8664                                 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8665                         }
8666                         if (b2_config & MDM_B2_DISABLE_TRANS)
8667                         {
8668                                 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8669                         }
8670                         if (b2_config & MDM_B2_DISABLE_V42)
8671                         {
8672                                 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8673                         }
8674                         if (b2_config & MDM_B2_DISABLE_COMP)
8675                         {
8676                                 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8677                         }
8678                         i++;
8679                 }
8680         }
8681         else
8682         {
8683                 dlc[i++] = 3; /* Addr A */
8684                 dlc[i++] = 1; /* Addr B */
8685                 dlc[i++] = 7; /* modulo mode */
8686                 dlc[i++] = 7; /* window size */
8687                 dlc[i++] = 0; /* XID len Lo  */
8688                 dlc[i++] = 0; /* XID len Hi  */
8689                 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8690                         DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8691                         DLC_MODEMPROT_DISABLE_V42_DETECT |
8692                         DLC_MODEMPROT_DISABLE_COMPRESSION;
8693         }
8694         dlc[0] = (byte)(i - 1);
8695 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8696         add_p(plci, DLC, dlc);
8697         return (0);
8698 }
8699
8700
8701 /*------------------------------------------------------------------*/
8702 /* send a request for the signaling entity                          */
8703 /*------------------------------------------------------------------*/
8704
8705 static void sig_req(PLCI *plci, byte req, byte Id)
8706 {
8707         if (!plci) return;
8708         if (plci->adapter->adapter_disabled) return;
8709         dbug(1, dprintf("sig_req(%x)", req));
8710         if (req == REMOVE)
8711                 plci->sig_remove_id = plci->Sig.Id;
8712         if (plci->req_in == plci->req_in_start) {
8713                 plci->req_in += 2;
8714                 plci->RBuffer[plci->req_in++] = 0;
8715         }
8716         PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8717         plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
8718         plci->RBuffer[plci->req_in++] = req;  /* request */
8719         plci->RBuffer[plci->req_in++] = 0;    /* channel */
8720         plci->req_in_start = plci->req_in;
8721 }
8722
8723 /*------------------------------------------------------------------*/
8724 /* send a request for the network layer entity                      */
8725 /*------------------------------------------------------------------*/
8726
8727 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8728 {
8729         if (!plci) return;
8730         if (plci->adapter->adapter_disabled) return;
8731         dbug(1, dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8732         if (req == REMOVE)
8733         {
8734                 plci->nl_remove_id = plci->NL.Id;
8735                 ncci_remove(plci, 0, (byte)(ncci != 0));
8736                 ncci = 0;
8737         }
8738         if (plci->req_in == plci->req_in_start) {
8739                 plci->req_in += 2;
8740                 plci->RBuffer[plci->req_in++] = 0;
8741         }
8742         PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8743         plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */
8744         plci->RBuffer[plci->req_in++] = req;  /* request */
8745         plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
8746         plci->req_in_start = plci->req_in;
8747 }
8748
8749 static void send_req(PLCI *plci)
8750 {
8751         ENTITY *e;
8752         word l;
8753 /*  word i; */
8754
8755         if (!plci) return;
8756         if (plci->adapter->adapter_disabled) return;
8757         channel_xmit_xon(plci);
8758
8759         /* if nothing to do, return */
8760         if (plci->req_in == plci->req_out) return;
8761         dbug(1, dprintf("send_req(in=%d,out=%d)", plci->req_in, plci->req_out));
8762
8763         if (plci->nl_req || plci->sig_req) return;
8764
8765         l = GET_WORD(&plci->RBuffer[plci->req_out]);
8766         plci->req_out += 2;
8767         plci->XData[0].P = &plci->RBuffer[plci->req_out];
8768         plci->req_out += l;
8769         if (plci->RBuffer[plci->req_out] == 1)
8770         {
8771                 e = &plci->NL;
8772                 plci->req_out++;
8773                 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8774                 e->ReqCh = plci->RBuffer[plci->req_out++];
8775                 if (!(e->Id & 0x1f))
8776                 {
8777                         e->Id = NL_ID;
8778                         plci->RBuffer[plci->req_out - 4] = CAI;
8779                         plci->RBuffer[plci->req_out - 3] = 1;
8780                         plci->RBuffer[plci->req_out - 2] = (plci->Sig.Id == 0xff) ? 0 : plci->Sig.Id;
8781                         plci->RBuffer[plci->req_out - 1] = 0;
8782                         l += 3;
8783                         plci->nl_global_req = plci->nl_req;
8784                 }
8785                 dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8786         }
8787         else
8788         {
8789                 e = &plci->Sig;
8790                 if (plci->RBuffer[plci->req_out])
8791                         e->Id = plci->RBuffer[plci->req_out];
8792                 plci->req_out++;
8793                 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8794                 e->ReqCh = plci->RBuffer[plci->req_out++];
8795                 if (!(e->Id & 0x1f))
8796                         plci->sig_global_req = plci->sig_req;
8797                 dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8798         }
8799         plci->XData[0].PLength = l;
8800         e->X = plci->XData;
8801         plci->adapter->request(e);
8802         dbug(1, dprintf("send_ok"));
8803 }
8804
8805 static void send_data(PLCI *plci)
8806 {
8807         DIVA_CAPI_ADAPTER *a;
8808         DATA_B3_DESC *data;
8809         NCCI   *ncci_ptr;
8810         word ncci;
8811
8812         if (!plci->nl_req && plci->ncci_ring_list)
8813         {
8814                 a = plci->adapter;
8815                 ncci = plci->ncci_ring_list;
8816                 do
8817                 {
8818                         ncci = a->ncci_next[ncci];
8819                         ncci_ptr = &(a->ncci[ncci]);
8820                         if (!(a->ncci_ch[ncci]
8821                               && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8822                         {
8823                                 if (ncci_ptr->data_pending)
8824                                 {
8825                                         if ((a->ncci_state[ncci] == CONNECTED)
8826                                             || (a->ncci_state[ncci] == INC_ACT_PENDING)
8827                                             || (plci->send_disc == ncci))
8828                                         {
8829                                                 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8830                                                 if ((plci->B2_prot == B2_V120_ASYNC)
8831                                                     || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8832                                                     || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8833                                                 {
8834                                                         plci->NData[1].P = TransmitBufferGet(plci->appl, data->P);
8835                                                         plci->NData[1].PLength = data->Length;
8836                                                         if (data->Flags & 0x10)
8837                                                                 plci->NData[0].P = v120_break_header;
8838                                                         else
8839                                                                 plci->NData[0].P = v120_default_header;
8840                                                         plci->NData[0].PLength = 1;
8841                                                         plci->NL.XNum = 2;
8842                                                         plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8843                                                 }
8844                                                 else
8845                                                 {
8846                                                         plci->NData[0].P = TransmitBufferGet(plci->appl, data->P);
8847                                                         plci->NData[0].PLength = data->Length;
8848                                                         if (data->Flags & 0x10)
8849                                                                 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8850
8851                                                         else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8852                                                                 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8853
8854                                                         else
8855                                                                 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8856                                                 }
8857                                                 plci->NL.X = plci->NData;
8858                                                 plci->NL.ReqCh = a->ncci_ch[ncci];
8859                                                 dbug(1, dprintf("%x:DREQ(%x:%x)", a->Id, plci->NL.Id, plci->NL.Req));
8860                                                 plci->data_sent = true;
8861                                                 plci->data_sent_ptr = data->P;
8862                                                 a->request(&plci->NL);
8863                                         }
8864                                         else {
8865                                                 cleanup_ncci_data(plci, ncci);
8866                                         }
8867                                 }
8868                                 else if (plci->send_disc == ncci)
8869                                 {
8870                                         /* dprintf("N_DISC"); */
8871                                         plci->NData[0].PLength = 0;
8872                                         plci->NL.ReqCh = a->ncci_ch[ncci];
8873                                         plci->NL.Req = plci->nl_req = N_DISC;
8874                                         a->request(&plci->NL);
8875                                         plci->command = _DISCONNECT_B3_R;
8876                                         plci->send_disc = 0;
8877                                 }
8878                         }
8879                 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8880                 plci->ncci_ring_list = ncci;
8881         }
8882 }
8883
8884 static void listen_check(DIVA_CAPI_ADAPTER *a)
8885 {
8886         word i, j;
8887         PLCI *plci;
8888         byte activnotifiedcalls = 0;
8889
8890         dbug(1, dprintf("listen_check(%d,%d)", a->listen_active, a->max_listen));
8891         if (!remove_started && !a->adapter_disabled)
8892         {
8893                 for (i = 0; i < a->max_plci; i++)
8894                 {
8895                         plci = &(a->plci[i]);
8896                         if (plci->notifiedcall) activnotifiedcalls++;
8897                 }
8898                 dbug(1, dprintf("listen_check(%d)", activnotifiedcalls));
8899
8900                 for (i = a->listen_active; i < ((word)(a->max_listen + activnotifiedcalls)); i++) {
8901                         if ((j = get_plci(a))) {
8902                                 a->listen_active++;
8903                                 plci = &a->plci[j - 1];
8904                                 plci->State = LISTENING;
8905
8906                                 add_p(plci, OAD, "\x01\xfd");
8907
8908                                 add_p(plci, KEY, "\x04\x43\x41\x32\x30");
8909
8910                                 add_p(plci, CAI, "\x01\xc0");
8911                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
8912                                 add_p(plci, LLI, "\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */
8913                                 add_p(plci, SHIFT | 6, NULL);
8914                                 add_p(plci, SIN, "\x02\x00\x00");
8915                                 plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
8916                                 sig_req(plci, ASSIGN, DSIG_ID);
8917                                 send_req(plci);
8918                         }
8919                 }
8920         }
8921 }
8922
8923 /*------------------------------------------------------------------*/
8924 /* functions for all parameters sent in INDs                        */
8925 /*------------------------------------------------------------------*/
8926
8927 static void IndParse(PLCI *plci, const word *parms_id, byte **parms, byte multiIEsize)
8928 {
8929         word ploc;            /* points to current location within packet */
8930         byte w;
8931         byte wlen;
8932         byte codeset, lock;
8933         byte *in;
8934         word i;
8935         word code;
8936         word mIEindex = 0;
8937         ploc = 0;
8938         codeset = 0;
8939         lock = 0;
8940
8941         in = plci->Sig.RBuffer->P;
8942         for (i = 0; i < parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
8943         {                            /* element but parms array is larger      */
8944                 parms[i] = (byte *)"";
8945         }
8946         for (i = 0; i < multiIEsize; i++)
8947         {
8948                 parms[i] = (byte *)"";
8949         }
8950
8951         while (ploc < plci->Sig.RBuffer->length - 1) {
8952
8953                 /* read information element id and length                   */
8954                 w = in[ploc];
8955
8956                 if (w & 0x80) {
8957 /*    w &=0xf0; removed, cannot detect congestion levels */
8958 /*    upper 4 bit masked with w==SHIFT now               */
8959                         wlen = 0;
8960                 }
8961                 else {
8962                         wlen = (byte)(in[ploc + 1] + 1);
8963                 }
8964                 /* check if length valid (not exceeding end of packet)      */
8965                 if ((ploc + wlen) > 270) return;
8966                 if (lock & 0x80) lock &= 0x7f;
8967                 else codeset = lock;
8968
8969                 if ((w & 0xf0) == SHIFT) {
8970                         codeset = in[ploc];
8971                         if (!(codeset & 0x08)) lock = (byte)(codeset & 7);
8972                         codeset &= 7;
8973                         lock |= 0x80;
8974                 }
8975                 else {
8976                         if (w == ESC && wlen >= 3) code = in[ploc + 2] | 0x800;
8977                         else code = w;
8978                         code |= (codeset << 8);
8979
8980                         for (i = 1; i < parms_id[0] + 1 && parms_id[i] != code; i++);
8981
8982                         if (i < parms_id[0] + 1) {
8983                                 if (!multiIEsize) { /* with multiIEs use next field index,          */
8984                                         mIEindex = i - 1;    /* with normal IEs use same index like parms_id */
8985                                 }
8986
8987                                 parms[mIEindex] = &in[ploc + 1];
8988                                 dbug(1, dprintf("mIE[%d]=0x%x", *parms[mIEindex], in[ploc]));
8989                                 if (parms_id[i] == OAD
8990                                     || parms_id[i] == CONN_NR
8991                                     || parms_id[i] == CAD) {
8992                                         if (in[ploc + 2] & 0x80) {
8993                                                 in[ploc + 0] = (byte)(in[ploc + 1] + 1);
8994                                                 in[ploc + 1] = (byte)(in[ploc + 2] & 0x7f);
8995                                                 in[ploc + 2] = 0x80;
8996                                                 parms[mIEindex] = &in[ploc];
8997                                         }
8998                                 }
8999                                 mIEindex++;       /* effects multiIEs only */
9000                         }
9001                 }
9002
9003                 ploc += (wlen + 1);
9004         }
9005         return;
9006 }
9007
9008 /*------------------------------------------------------------------*/
9009 /* try to match a cip from received BC and HLC                      */
9010 /*------------------------------------------------------------------*/
9011
9012 static byte ie_compare(byte *ie1, byte *ie2)
9013 {
9014         word i;
9015         if (!ie1 || !ie2) return false;
9016         if (!ie1[0]) return false;
9017         for (i = 0; i < (word)(ie1[0] + 1); i++) if (ie1[i] != ie2[i]) return false;
9018         return true;
9019 }
9020
9021 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
9022 {
9023         word i;
9024         word j;
9025
9026         for (i = 9; i && !ie_compare(bc, cip_bc[i][a->u_law]); i--);
9027
9028         for (j = 16; j < 29 &&
9029                      (!ie_compare(bc, cip_bc[j][a->u_law]) || !ie_compare(hlc, cip_hlc[j])); j++);
9030         if (j == 29) return i;
9031         return j;
9032 }
9033
9034
9035 static byte AddInfo(byte **add_i,
9036                     byte **fty_i,
9037                     byte *esc_chi,
9038                     byte *facility)
9039 {
9040         byte i;
9041         byte j;
9042         byte k;
9043         byte flen;
9044         byte len = 0;
9045         /* facility is a nested structure */
9046         /* FTY can be more than once      */
9047
9048         if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
9049         {
9050                 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9051         }
9052
9053         else
9054         {
9055                 add_i[0] = (byte *)"";
9056         }
9057         if (!fty_i[0][0])
9058         {
9059                 add_i[3] = (byte *)"";
9060         }
9061         else
9062         {    /* facility array found  */
9063                 for (i = 0, j = 1; i < MAX_MULTI_IE && fty_i[i][0]; i++)
9064                 {
9065                         dbug(1, dprintf("AddIFac[%d]", fty_i[i][0]));
9066                         len += fty_i[i][0];
9067                         len += 2;
9068                         flen = fty_i[i][0];
9069                         facility[j++] = 0x1c; /* copy fac IE */
9070                         for (k = 0; k <= flen; k++, j++)
9071                         {
9072                                 facility[j] = fty_i[i][k];
9073 /*      dbug(1, dprintf("%x ",facility[j])); */
9074                         }
9075                 }
9076                 facility[0] = len;
9077                 add_i[3] = facility;
9078         }
9079 /*  dbug(1, dprintf("FacArrLen=%d ",len)); */
9080         len = add_i[0][0] + add_i[1][0] + add_i[2][0] + add_i[3][0];
9081         len += 4;                          /* calculate length of all */
9082         return (len);
9083 }
9084
9085 /*------------------------------------------------------------------*/
9086 /* voice and codec features                                         */
9087 /*------------------------------------------------------------------*/
9088
9089 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
9090 {
9091         byte voice_chi[] = "\x02\x18\x01";
9092         byte channel;
9093
9094         channel = chi[chi[0]] & 0x3;
9095         dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel));
9096         voice_chi[2] = (channel) ? channel : 1;
9097         add_p(plci, FTY, "\x02\x01\x07");             /* B On, default on 1 */
9098         add_p(plci, ESC, voice_chi);                  /* Channel */
9099         sig_req(plci, TEL_CTRL, 0);
9100         send_req(plci);
9101         if (a->AdvSignalPLCI)
9102         {
9103                 adv_voice_write_coefs(a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9104         }
9105 }
9106
9107 static void VoiceChannelOff(PLCI *plci)
9108 {
9109         dbug(1, dprintf("ExtDevOFF"));
9110         add_p(plci, FTY, "\x02\x01\x08");             /* B Off */
9111         sig_req(plci, TEL_CTRL, 0);
9112         send_req(plci);
9113         if (plci->adapter->AdvSignalPLCI)
9114         {
9115                 adv_voice_clear_config(plci->adapter->AdvSignalPLCI);
9116         }
9117 }
9118
9119
9120 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9121                             byte hook_listen)
9122 {
9123         word j;
9124         PLCI *splci;
9125
9126         /* check if hardware supports handset with hook states (adv.codec) */
9127         /* or if just a on board codec is supported                        */
9128         /* the advanced codec plci is just for internal use                */
9129
9130         /* diva Pro with on-board codec:                                   */
9131         if (a->profile.Global_Options & HANDSET)
9132         {
9133                 /* new call, but hook states are already signalled */
9134                 if (a->AdvCodecFLAG)
9135                 {
9136                         if (a->AdvSignalAppl != appl || a->AdvSignalPLCI)
9137                         {
9138                                 dbug(1, dprintf("AdvSigPlci=0x%x", a->AdvSignalPLCI));
9139                                 return 0x2001; /* codec in use by another application */
9140                         }
9141                         if (plci != NULL)
9142                         {
9143                                 a->AdvSignalPLCI = plci;
9144                                 plci->tel = ADV_VOICE;
9145                         }
9146                         return 0;                      /* adv codec still used */
9147                 }
9148                 if ((j = get_plci(a)))
9149                 {
9150                         splci = &a->plci[j - 1];
9151                         splci->tel = CODEC_PERMANENT;
9152                         /* hook_listen indicates if a facility_req with handset/hook support */
9153                         /* was sent. Otherwise if just a call on an external device was made */
9154                         /* the codec will be used but the hook info will be discarded (just  */
9155                         /* the external controller is in use                                 */
9156                         if (hook_listen) splci->State = ADVANCED_VOICE_SIG;
9157                         else
9158                         {
9159                                 splci->State = ADVANCED_VOICE_NOSIG;
9160                                 if (plci)
9161                                 {
9162                                         plci->spoofed_msg = SPOOFING_REQUIRED;
9163                                 }
9164                                 /* indicate D-ch connect if  */
9165                         }                                        /* codec is connected OK     */
9166                         if (plci != NULL)
9167                         {
9168                                 a->AdvSignalPLCI = plci;
9169                                 plci->tel = ADV_VOICE;
9170                         }
9171                         a->AdvSignalAppl = appl;
9172                         a->AdvCodecFLAG = true;
9173                         a->AdvCodecPLCI = splci;
9174                         add_p(splci, CAI, "\x01\x15");
9175                         add_p(splci, LLI, "\x01\x00");
9176                         add_p(splci, ESC, "\x02\x18\x00");
9177                         add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9178                         splci->internal_command = PERM_COD_ASSIGN;
9179                         dbug(1, dprintf("Codec Assign"));
9180                         sig_req(splci, ASSIGN, DSIG_ID);
9181                         send_req(splci);
9182                 }
9183                 else
9184                 {
9185                         return 0x2001; /* wrong state, no more plcis */
9186                 }
9187         }
9188         else if (a->profile.Global_Options & ON_BOARD_CODEC)
9189         {
9190                 if (hook_listen) return 0x300B;               /* Facility not supported */
9191                 /* no hook with SCOM      */
9192                 if (plci != NULL) plci->tel = CODEC;
9193                 dbug(1, dprintf("S/SCOM codec"));
9194                 /* first time we use the scom-s codec we must shut down the internal   */
9195                 /* handset application of the card. This can be done by an assign with */
9196                 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9197                 if (!a->scom_appl_disable) {
9198                         if ((j = get_plci(a))) {
9199                                 splci = &a->plci[j - 1];
9200                                 add_p(splci, CAI, "\x01\x80");
9201                                 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9202                                 sig_req(splci, ASSIGN, 0xC0);  /* 0xc0 is the TEL_ID */
9203                                 send_req(splci);
9204                                 a->scom_appl_disable = true;
9205                         }
9206                         else{
9207                                 return 0x2001; /* wrong state, no more plcis */
9208                         }
9209                 }
9210         }
9211         else return 0x300B;               /* Facility not supported */
9212
9213         return 0;
9214 }
9215
9216
9217 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9218 {
9219
9220         dbug(1, dprintf("CodecIdCheck"));
9221
9222         if (a->AdvSignalPLCI == plci)
9223         {
9224                 dbug(1, dprintf("PLCI owns codec"));
9225                 VoiceChannelOff(a->AdvCodecPLCI);
9226                 if (a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9227                 {
9228                         dbug(1, dprintf("remove temp codec PLCI"));
9229                         plci_remove(a->AdvCodecPLCI);
9230                         a->AdvCodecFLAG  = 0;
9231                         a->AdvCodecPLCI  = NULL;
9232                         a->AdvSignalAppl = NULL;
9233                 }
9234                 a->AdvSignalPLCI = NULL;
9235         }
9236 }
9237
9238 /* -------------------------------------------------------------------
9239    Ask for physical address of card on PCI bus
9240    ------------------------------------------------------------------- */
9241 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *a,
9242                                        IDI_SYNC_REQ *preq) {
9243         a->sdram_bar = 0;
9244         if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9245                 ENTITY *e = (ENTITY *)preq;
9246
9247                 e->user[0] = a->Id - 1;
9248                 preq->xdi_sdram_bar.info.bar    = 0;
9249                 preq->xdi_sdram_bar.Req         = 0;
9250                 preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9251
9252                 (*(a->request))(e);
9253
9254                 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9255                 dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9256         }
9257 }
9258
9259 /* -------------------------------------------------------------------
9260    Ask XDI about extended features
9261    ------------------------------------------------------------------- */
9262 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a) {
9263         IDI_SYNC_REQ *preq;
9264         char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
9265
9266         char features[4];
9267         preq = (IDI_SYNC_REQ *)&buffer[0];
9268
9269         if (!diva_xdi_extended_features) {
9270                 ENTITY *e = (ENTITY *)preq;
9271                 diva_xdi_extended_features |= 0x80000000;
9272
9273                 e->user[0] = a->Id - 1;
9274                 preq->xdi_extended_features.Req = 0;
9275                 preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9276                 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9277                 preq->xdi_extended_features.info.features = &features[0];
9278
9279                 (*(a->request))(e);
9280
9281                 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9282                         /*
9283                           Check features located in the byte '0'
9284                         */
9285                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9286                                 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9287                         }
9288                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9289                                 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9290                                 dbug(1, dprintf("XDI provides RxDMA"));
9291                         }
9292                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9293                                 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9294                         }
9295                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9296                                 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9297                                 dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9298                         }
9299
9300                 }
9301         }
9302
9303         diva_ask_for_xdi_sdram_bar(a, preq);
9304 }
9305
9306 /*------------------------------------------------------------------*/
9307 /* automatic law                                                    */
9308 /*------------------------------------------------------------------*/
9309 /* called from OS specific part after init time to get the Law              */
9310 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9311 void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9312 {
9313         word j;
9314         PLCI *splci;
9315
9316         if (a->automatic_law) {
9317                 return;
9318         }
9319         if ((j = get_plci(a))) {
9320                 diva_get_extended_adapter_features(a);
9321                 splci = &a->plci[j - 1];
9322                 a->automatic_lawPLCI = splci;
9323                 a->automatic_law = 1;
9324                 add_p(splci, CAI, "\x01\x80");
9325                 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9326                 splci->internal_command = USELAW_REQ;
9327                 splci->command = 0;
9328                 splci->number = 0;
9329                 sig_req(splci, ASSIGN, DSIG_ID);
9330                 send_req(splci);
9331         }
9332 }
9333
9334 /* called from OS specific part if an application sends an Capi20Release */
9335 word CapiRelease(word Id)
9336 {
9337         word i, j, appls_found;
9338         PLCI *plci;
9339         APPL   *this;
9340         DIVA_CAPI_ADAPTER *a;
9341
9342         if (!Id)
9343         {
9344                 dbug(0, dprintf("A: CapiRelease(Id==0)"));
9345                 return (_WRONG_APPL_ID);
9346         }
9347
9348         this = &application[Id - 1];               /* get application pointer */
9349
9350         for (i = 0, appls_found = 0; i < max_appl; i++)
9351         {
9352                 if (application[i].Id)       /* an application has been found        */
9353                 {
9354                         appls_found++;
9355                 }
9356         }
9357
9358         for (i = 0; i < max_adapter; i++)             /* scan all adapters...    */
9359         {
9360                 a = &adapter[i];
9361                 if (a->request)
9362                 {
9363                         a->Info_Mask[Id - 1] = 0;
9364                         a->CIP_Mask[Id - 1] = 0;
9365                         a->Notification_Mask[Id - 1] = 0;
9366                         a->codec_listen[Id - 1] = NULL;
9367                         a->requested_options_table[Id - 1] = 0;
9368                         for (j = 0; j < a->max_plci; j++)           /* and all PLCIs connected */
9369                         {                                      /* with this application   */
9370                                 plci = &a->plci[j];
9371                                 if (plci->Id)                         /* if plci owns no application */
9372                                 {                                    /* it may be not jet connected */
9373                                         if (plci->State == INC_CON_PENDING
9374                                             || plci->State == INC_CON_ALERT)
9375                                         {
9376                                                 if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9377                                                 {
9378                                                         clear_c_ind_mask_bit(plci, (word)(Id - 1));
9379                                                         if (c_ind_mask_empty(plci))
9380                                                         {
9381                                                                 sig_req(plci, HANGUP, 0);
9382                                                                 send_req(plci);
9383                                                                 plci->State = OUTG_DIS_PENDING;
9384                                                         }
9385                                                 }
9386                                         }
9387                                         if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9388                                         {
9389                                                 clear_c_ind_mask_bit(plci, (word)(Id - 1));
9390                                                 if (c_ind_mask_empty(plci))
9391                                                 {
9392                                                         if (!plci->appl)
9393                                                         {
9394                                                                 plci_remove(plci);
9395                                                                 plci->State = IDLE;
9396                                                         }
9397                                                 }
9398                                         }
9399                                         if (plci->appl == this)
9400                                         {
9401                                                 plci->appl = NULL;
9402                                                 plci_remove(plci);
9403                                                 plci->State = IDLE;
9404                                         }
9405                                 }
9406                         }
9407                         listen_check(a);
9408
9409                         if (a->flag_dynamic_l1_down)
9410                         {
9411                                 if (appls_found == 1)            /* last application does a capi release */
9412                                 {
9413                                         if ((j = get_plci(a)))
9414                                         {
9415                                                 plci = &a->plci[j - 1];
9416                                                 plci->command = 0;
9417                                                 add_p(plci, OAD, "\x01\xfd");
9418                                                 add_p(plci, CAI, "\x01\x80");
9419                                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9420                                                 add_p(plci, SHIFT | 6, NULL);
9421                                                 add_p(plci, SIN, "\x02\x00\x00");
9422                                                 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9423                                                 sig_req(plci, ASSIGN, DSIG_ID);
9424                                                 add_p(plci, FTY, "\x02\xff\x06"); /* l1 down */
9425                                                 sig_req(plci, SIG_CTRL, 0);
9426                                                 send_req(plci);
9427                                         }
9428                                 }
9429                         }
9430                         if (a->AdvSignalAppl == this)
9431                         {
9432                                 this->NullCREnable = false;
9433                                 if (a->AdvCodecPLCI)
9434                                 {
9435                                         plci_remove(a->AdvCodecPLCI);
9436                                         a->AdvCodecPLCI->tel = 0;
9437                                         a->AdvCodecPLCI->adv_nl = 0;
9438                                 }
9439                                 a->AdvSignalAppl = NULL;
9440                                 a->AdvSignalPLCI = NULL;
9441                                 a->AdvCodecFLAG = 0;
9442                                 a->AdvCodecPLCI = NULL;
9443                         }
9444                 }
9445         }
9446
9447         this->Id = 0;
9448
9449         return GOOD;
9450 }
9451
9452 static word plci_remove_check(PLCI *plci)
9453 {
9454         if (!plci) return true;
9455         if (!plci->NL.Id && c_ind_mask_empty(plci))
9456         {
9457                 if (plci->Sig.Id == 0xff)
9458                         plci->Sig.Id = 0;
9459                 if (!plci->Sig.Id)
9460                 {
9461                         dbug(1, dprintf("plci_remove_complete(%x)", plci->Id));
9462                         dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci->tel, plci->Sig.Id));
9463                         if (plci->Id)
9464                         {
9465                                 CodecIdCheck(plci->adapter, plci);
9466                                 clear_b1_config(plci);
9467                                 ncci_remove(plci, 0, false);
9468                                 plci_free_msg_in_queue(plci);
9469                                 channel_flow_control_remove(plci);
9470                                 plci->Id = 0;
9471                                 plci->State = IDLE;
9472                                 plci->channels = 0;
9473                                 plci->appl = NULL;
9474                                 plci->notifiedcall = 0;
9475                         }
9476                         listen_check(plci->adapter);
9477                         return true;
9478                 }
9479         }
9480         return false;
9481 }
9482
9483
9484 /*------------------------------------------------------------------*/
9485
9486 static byte plci_nl_busy(PLCI *plci)
9487 {
9488         /* only applicable for non-multiplexed protocols */
9489         return (plci->nl_req
9490                 || (plci->ncci_ring_list
9491                     && plci->adapter->ncci_ch[plci->ncci_ring_list]
9492                     && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9493 }
9494
9495
9496 /*------------------------------------------------------------------*/
9497 /* DTMF facilities                                                  */
9498 /*------------------------------------------------------------------*/
9499
9500
9501 static struct
9502 {
9503         byte send_mask;
9504         byte listen_mask;
9505         byte character;
9506         byte code;
9507 } dtmf_digit_map[] =
9508 {
9509         { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9510         { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9511         { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9512         { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9513         { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9514         { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9515         { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9516         { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9517         { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9518         { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9519         { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9520         { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9521         { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9522         { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9523         { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9524         { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9525         { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9526         { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9527         { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9528         { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9529
9530         { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9531         { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9532         { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9533         { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9534         { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9535         { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9536         { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9537         { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9538         { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9539         { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9540         { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9541         { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9542         { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9543         { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9544         { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9545         { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9546         { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9547         { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9548         { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9549         { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9550         { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9551         { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9552         { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9553         { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9554         { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9555         { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9556         { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9557         { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9558         { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9559         { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9560         { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9561         { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9562         { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9563         { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9564         { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9565         { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9566         { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9567         { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9568         { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9569         { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9570         { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9571         { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9572         { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9573         { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9574         { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9575         { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9576         { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9577         { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9578         { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9579         { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9580         { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9581         { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9582
9583 };
9584
9585 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9586
9587
9588 static void dtmf_enable_receiver(PLCI *plci, byte enable_mask)
9589 {
9590         word min_digit_duration, min_gap_duration;
9591
9592         dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9593                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9594                         (char *)(FILE_), __LINE__, enable_mask));
9595
9596         if (enable_mask != 0)
9597         {
9598                 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9599                 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9600                 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9601                 PUT_WORD(&plci->internal_req_buffer[1], min_digit_duration);
9602                 PUT_WORD(&plci->internal_req_buffer[3], min_gap_duration);
9603                 plci->NData[0].PLength = 5;
9604
9605                 PUT_WORD(&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9606                 plci->NData[0].PLength += 2;
9607                 capidtmf_recv_enable(&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9608
9609         }
9610         else
9611         {
9612                 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9613                 plci->NData[0].PLength = 1;
9614
9615                 capidtmf_recv_disable(&(plci->capidtmf_state));
9616
9617         }
9618         plci->NData[0].P = plci->internal_req_buffer;
9619         plci->NL.X = plci->NData;
9620         plci->NL.ReqCh = 0;
9621         plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9622         plci->adapter->request(&plci->NL);
9623 }
9624
9625
9626 static void dtmf_send_digits(PLCI *plci, byte *digit_buffer, word digit_count)
9627 {
9628         word w, i;
9629
9630         dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9631                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9632                         (char *)(FILE_), __LINE__, digit_count));
9633
9634         plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9635         w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9636         PUT_WORD(&plci->internal_req_buffer[1], w);
9637         w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9638         PUT_WORD(&plci->internal_req_buffer[3], w);
9639         for (i = 0; i < digit_count; i++)
9640         {
9641                 w = 0;
9642                 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9643                        && (digit_buffer[i] != dtmf_digit_map[w].character))
9644                 {
9645                         w++;
9646                 }
9647                 plci->internal_req_buffer[5 + i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9648                         dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9649         }
9650         plci->NData[0].PLength = 5 + digit_count;
9651         plci->NData[0].P = plci->internal_req_buffer;
9652         plci->NL.X = plci->NData;
9653         plci->NL.ReqCh = 0;
9654         plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9655         plci->adapter->request(&plci->NL);
9656 }
9657
9658
9659 static void dtmf_rec_clear_config(PLCI *plci)
9660 {
9661
9662         dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9663                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9664                         (char *)(FILE_), __LINE__));
9665
9666         plci->dtmf_rec_active = 0;
9667         plci->dtmf_rec_pulse_ms = 0;
9668         plci->dtmf_rec_pause_ms = 0;
9669
9670         capidtmf_init(&(plci->capidtmf_state), plci->adapter->u_law);
9671
9672 }
9673
9674
9675 static void dtmf_send_clear_config(PLCI *plci)
9676 {
9677
9678         dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9679                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9680                         (char *)(FILE_), __LINE__));
9681
9682         plci->dtmf_send_requests = 0;
9683         plci->dtmf_send_pulse_ms = 0;
9684         plci->dtmf_send_pause_ms = 0;
9685 }
9686
9687
9688 static void dtmf_prepare_switch(dword Id, PLCI *plci)
9689 {
9690
9691         dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9692                         UnMapId(Id), (char *)(FILE_), __LINE__));
9693
9694         while (plci->dtmf_send_requests != 0)
9695                 dtmf_confirmation(Id, plci);
9696 }
9697
9698
9699 static word dtmf_save_config(dword Id, PLCI *plci, byte Rc)
9700 {
9701
9702         dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9703                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9704
9705         return (GOOD);
9706 }
9707
9708
9709 static word dtmf_restore_config(dword Id, PLCI *plci, byte Rc)
9710 {
9711         word Info;
9712
9713         dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9714                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9715
9716         Info = GOOD;
9717         if (plci->B1_facilities & B1_FACILITY_DTMFR)
9718         {
9719                 switch (plci->adjust_b_state)
9720                 {
9721                 case ADJUST_B_RESTORE_DTMF_1:
9722                         plci->internal_command = plci->adjust_b_command;
9723                         if (plci_nl_busy(plci))
9724                         {
9725                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9726                                 break;
9727                         }
9728                         dtmf_enable_receiver(plci, plci->dtmf_rec_active);
9729                         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9730                         break;
9731                 case ADJUST_B_RESTORE_DTMF_2:
9732                         if ((Rc != OK) && (Rc != OK_FC))
9733                         {
9734                                 dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9735                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9736                                 Info = _WRONG_STATE;
9737                                 break;
9738                         }
9739                         break;
9740                 }
9741         }
9742         return (Info);
9743 }
9744
9745
9746 static void dtmf_command(dword Id, PLCI *plci, byte Rc)
9747 {
9748         word internal_command, Info;
9749         byte mask;
9750         byte result[4];
9751
9752         dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9753                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9754                         plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9755                         plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9756
9757         Info = GOOD;
9758         result[0] = 2;
9759         PUT_WORD(&result[1], DTMF_SUCCESS);
9760         internal_command = plci->internal_command;
9761         plci->internal_command = 0;
9762         mask = 0x01;
9763         switch (plci->dtmf_cmd)
9764         {
9765
9766         case DTMF_LISTEN_TONE_START:
9767                 mask <<= 1;
9768         case DTMF_LISTEN_MF_START:
9769                 mask <<= 1;
9770
9771         case DTMF_LISTEN_START:
9772                 switch (internal_command)
9773                 {
9774                 default:
9775                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9776                                                                   B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9777                 case DTMF_COMMAND_1:
9778                         if (adjust_b_process(Id, plci, Rc) != GOOD)
9779                         {
9780                                 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9781                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9782                                 Info = _FACILITY_NOT_SUPPORTED;
9783                                 break;
9784                         }
9785                         if (plci->internal_command)
9786                                 return;
9787                 case DTMF_COMMAND_2:
9788                         if (plci_nl_busy(plci))
9789                         {
9790                                 plci->internal_command = DTMF_COMMAND_2;
9791                                 return;
9792                         }
9793                         plci->internal_command = DTMF_COMMAND_3;
9794                         dtmf_enable_receiver(plci, (byte)(plci->dtmf_rec_active | mask));
9795                         return;
9796                 case DTMF_COMMAND_3:
9797                         if ((Rc != OK) && (Rc != OK_FC))
9798                         {
9799                                 dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9800                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9801                                 Info = _FACILITY_NOT_SUPPORTED;
9802                                 break;
9803                         }
9804
9805                         plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9806
9807                         plci->dtmf_rec_active |= mask;
9808                         break;
9809                 }
9810                 break;
9811
9812
9813         case DTMF_LISTEN_TONE_STOP:
9814                 mask <<= 1;
9815         case DTMF_LISTEN_MF_STOP:
9816                 mask <<= 1;
9817
9818         case DTMF_LISTEN_STOP:
9819                 switch (internal_command)
9820                 {
9821                 default:
9822                         plci->dtmf_rec_active &= ~mask;
9823                         if (plci->dtmf_rec_active)
9824                                 break;
9825 /*
9826   case DTMF_COMMAND_1:
9827   if (plci->dtmf_rec_active)
9828   {
9829   if (plci_nl_busy (plci))
9830   {
9831   plci->internal_command = DTMF_COMMAND_1;
9832   return;
9833   }
9834   plci->dtmf_rec_active &= ~mask;
9835   plci->internal_command = DTMF_COMMAND_2;
9836   dtmf_enable_receiver (plci, false);
9837   return;
9838   }
9839   Rc = OK;
9840   case DTMF_COMMAND_2:
9841   if ((Rc != OK) && (Rc != OK_FC))
9842   {
9843   dbug (1, dprintf("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9844   UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9845   Info = _FACILITY_NOT_SUPPORTED;
9846   break;
9847   }
9848 */
9849                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
9850                                                                   ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9851                 case DTMF_COMMAND_3:
9852                         if (adjust_b_process(Id, plci, Rc) != GOOD)
9853                         {
9854                                 dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9855                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9856                                 Info = _FACILITY_NOT_SUPPORTED;
9857                                 break;
9858                         }
9859                         if (plci->internal_command)
9860                                 return;
9861                         break;
9862                 }
9863                 break;
9864
9865
9866         case DTMF_SEND_TONE:
9867                 mask <<= 1;
9868         case DTMF_SEND_MF:
9869                 mask <<= 1;
9870
9871         case DTMF_DIGITS_SEND:
9872                 switch (internal_command)
9873                 {
9874                 default:
9875                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9876                                                                   ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9877                                            DTMF_COMMAND_1);
9878                 case DTMF_COMMAND_1:
9879                         if (adjust_b_process(Id, plci, Rc) != GOOD)
9880                         {
9881                                 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9882                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9883                                 Info = _FACILITY_NOT_SUPPORTED;
9884                                 break;
9885                         }
9886                         if (plci->internal_command)
9887                                 return;
9888                 case DTMF_COMMAND_2:
9889                         if (plci_nl_busy(plci))
9890                         {
9891                                 plci->internal_command = DTMF_COMMAND_2;
9892                                 return;
9893                         }
9894                         plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9895                         plci->internal_command = DTMF_COMMAND_3;
9896                         dtmf_send_digits(plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9897                         return;
9898                 case DTMF_COMMAND_3:
9899                         if ((Rc != OK) && (Rc != OK_FC))
9900                         {
9901                                 dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9902                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9903                                 if (plci->dtmf_send_requests != 0)
9904                                         (plci->dtmf_send_requests)--;
9905                                 Info = _FACILITY_NOT_SUPPORTED;
9906                                 break;
9907                         }
9908                         return;
9909                 }
9910                 break;
9911         }
9912         sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9913               "wws", Info, SELECTOR_DTMF, result);
9914 }
9915
9916
9917 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
9918 {
9919         word Info;
9920         word i, j;
9921         byte mask;
9922         API_PARSE dtmf_parms[5];
9923         byte result[40];
9924
9925         dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9926                         UnMapId(Id), (char *)(FILE_), __LINE__));
9927
9928         Info = GOOD;
9929         result[0] = 2;
9930         PUT_WORD(&result[1], DTMF_SUCCESS);
9931         if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9932         {
9933                 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9934                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9935                 Info = _FACILITY_NOT_SUPPORTED;
9936         }
9937         else if (api_parse(&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9938         {
9939                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9940                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9941                 Info = _WRONG_MESSAGE_FORMAT;
9942         }
9943
9944         else if ((GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9945                  || (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9946         {
9947                 if (!((a->requested_options_table[appl->Id - 1])
9948                       & (1L << PRIVATE_DTMF_TONE)))
9949                 {
9950                         dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9951                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9952                         PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9953                 }
9954                 else
9955                 {
9956                         for (i = 0; i < 32; i++)
9957                                 result[4 + i] = 0;
9958                         if (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9959                         {
9960                                 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9961                                 {
9962                                         if (dtmf_digit_map[i].listen_mask != 0)
9963                                                 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9964                                 }
9965                         }
9966                         else
9967                         {
9968                                 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9969                                 {
9970                                         if (dtmf_digit_map[i].send_mask != 0)
9971                                                 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9972                                 }
9973                         }
9974                         result[0] = 3 + 32;
9975                         result[3] = 32;
9976                 }
9977         }
9978
9979         else if (plci == NULL)
9980         {
9981                 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9982                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9983                 Info = _WRONG_IDENTIFIER;
9984         }
9985         else
9986         {
9987                 if (!plci->State
9988                     || !plci->NL.Id || plci->nl_remove_id)
9989                 {
9990                         dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9991                                         UnMapId(Id), (char *)(FILE_), __LINE__));
9992                         Info = _WRONG_STATE;
9993                 }
9994                 else
9995                 {
9996                         plci->command = 0;
9997                         plci->dtmf_cmd = GET_WORD(dtmf_parms[0].info);
9998                         mask = 0x01;
9999                         switch (plci->dtmf_cmd)
10000                         {
10001
10002                         case DTMF_LISTEN_TONE_START:
10003                         case DTMF_LISTEN_TONE_STOP:
10004                                 mask <<= 1;
10005                         case DTMF_LISTEN_MF_START:
10006                         case DTMF_LISTEN_MF_STOP:
10007                                 mask <<= 1;
10008                                 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10009                                       & (1L << PRIVATE_DTMF_TONE)))
10010                                 {
10011                                         dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10012                                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10013                                         PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10014                                         break;
10015                                 }
10016
10017                         case DTMF_LISTEN_START:
10018                         case DTMF_LISTEN_STOP:
10019                                 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10020                                     && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10021                                 {
10022                                         dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
10023                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
10024                                         Info = _FACILITY_NOT_SUPPORTED;
10025                                         break;
10026                                 }
10027                                 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10028                                 {
10029                                         if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10030                                         {
10031                                                 plci->dtmf_rec_pulse_ms = 0;
10032                                                 plci->dtmf_rec_pause_ms = 0;
10033                                         }
10034                                         else
10035                                         {
10036                                                 plci->dtmf_rec_pulse_ms = GET_WORD(dtmf_parms[1].info);
10037                                                 plci->dtmf_rec_pause_ms = GET_WORD(dtmf_parms[2].info);
10038                                         }
10039                                 }
10040                                 start_internal_command(Id, plci, dtmf_command);
10041                                 return (false);
10042
10043
10044                         case DTMF_SEND_TONE:
10045                                 mask <<= 1;
10046                         case DTMF_SEND_MF:
10047                                 mask <<= 1;
10048                                 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10049                                       & (1L << PRIVATE_DTMF_TONE)))
10050                                 {
10051                                         dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10052                                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10053                                         PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10054                                         break;
10055                                 }
10056
10057                         case DTMF_DIGITS_SEND:
10058                                 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10059                                 {
10060                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
10061                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
10062                                         Info = _WRONG_MESSAGE_FORMAT;
10063                                         break;
10064                                 }
10065                                 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10066                                 {
10067                                         plci->dtmf_send_pulse_ms = GET_WORD(dtmf_parms[1].info);
10068                                         plci->dtmf_send_pause_ms = GET_WORD(dtmf_parms[2].info);
10069                                 }
10070                                 i = 0;
10071                                 j = 0;
10072                                 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10073                                 {
10074                                         j = 0;
10075                                         while ((j < DTMF_DIGIT_MAP_ENTRIES)
10076                                                && ((dtmf_parms[3].info[i + 1] != dtmf_digit_map[j].character)
10077                                                    || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10078                                         {
10079                                                 j++;
10080                                         }
10081                                         i++;
10082                                 }
10083                                 if (j == DTMF_DIGIT_MAP_ENTRIES)
10084                                 {
10085                                         dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10086                                                         UnMapId(Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10087                                         PUT_WORD(&result[1], DTMF_INCORRECT_DIGIT);
10088                                         break;
10089                                 }
10090                                 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10091                                 {
10092                                         dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
10093                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
10094                                         Info = _WRONG_STATE;
10095                                         break;
10096                                 }
10097                                 api_save_msg(dtmf_parms, "wwws", &plci->saved_msg);
10098                                 start_internal_command(Id, plci, dtmf_command);
10099                                 return (false);
10100
10101                         default:
10102                                 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10103                                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10104                                 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10105                         }
10106                 }
10107         }
10108         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10109               "wws", Info, SELECTOR_DTMF, result);
10110         return (false);
10111 }
10112
10113
10114 static void dtmf_confirmation(dword Id, PLCI *plci)
10115 {
10116         word i;
10117         byte result[4];
10118
10119         dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
10120                         UnMapId(Id), (char *)(FILE_), __LINE__));
10121
10122         result[0] = 2;
10123         PUT_WORD(&result[1], DTMF_SUCCESS);
10124         if (plci->dtmf_send_requests != 0)
10125         {
10126                 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10127                       "wws", GOOD, SELECTOR_DTMF, result);
10128                 (plci->dtmf_send_requests)--;
10129                 for (i = 0; i < plci->dtmf_send_requests; i++)
10130                         plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i + 1];
10131         }
10132 }
10133
10134
10135 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length)
10136 {
10137         word i, j, n;
10138
10139         dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10140                         UnMapId(Id), (char *)(FILE_), __LINE__));
10141
10142         n = 0;
10143         for (i = 1; i < length; i++)
10144         {
10145                 j = 0;
10146                 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10147                        && ((msg[i] != dtmf_digit_map[j].code)
10148                            || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10149                 {
10150                         j++;
10151                 }
10152                 if (j < DTMF_DIGIT_MAP_ENTRIES)
10153                 {
10154
10155                         if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10156                             && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10157                             && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10158                         {
10159                                 if (n + 1 == i)
10160                                 {
10161                                         for (i = length; i > n + 1; i--)
10162                                                 msg[i] = msg[i - 1];
10163                                         length++;
10164                                         i++;
10165                                 }
10166                                 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10167                         }
10168                         plci->tone_last_indication_code = dtmf_digit_map[j].character;
10169
10170                         msg[++n] = dtmf_digit_map[j].character;
10171                 }
10172         }
10173         if (n != 0)
10174         {
10175                 msg[0] = (byte) n;
10176                 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10177         }
10178 }
10179
10180
10181 /*------------------------------------------------------------------*/
10182 /* DTMF parameters                                                  */
10183 /*------------------------------------------------------------------*/
10184
10185 static void dtmf_parameter_write(PLCI *plci)
10186 {
10187         word i;
10188         byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10189
10190         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10191                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10192                         (char *)(FILE_), __LINE__));
10193
10194         parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10195         parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10196         for (i = 0; i < plci->dtmf_parameter_length; i++)
10197                 parameter_buffer[2 + i] = plci->dtmf_parameter_buffer[i];
10198         add_p(plci, FTY, parameter_buffer);
10199         sig_req(plci, TEL_CTRL, 0);
10200         send_req(plci);
10201 }
10202
10203
10204 static void dtmf_parameter_clear_config(PLCI *plci)
10205 {
10206
10207         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10208                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10209                         (char *)(FILE_), __LINE__));
10210
10211         plci->dtmf_parameter_length = 0;
10212 }
10213
10214
10215 static void dtmf_parameter_prepare_switch(dword Id, PLCI *plci)
10216 {
10217
10218         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10219                         UnMapId(Id), (char *)(FILE_), __LINE__));
10220
10221 }
10222
10223
10224 static word dtmf_parameter_save_config(dword Id, PLCI *plci, byte Rc)
10225 {
10226
10227         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10228                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10229
10230         return (GOOD);
10231 }
10232
10233
10234 static word dtmf_parameter_restore_config(dword Id, PLCI *plci, byte Rc)
10235 {
10236         word Info;
10237
10238         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10239                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10240
10241         Info = GOOD;
10242         if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10243             && (plci->dtmf_parameter_length != 0))
10244         {
10245                 switch (plci->adjust_b_state)
10246                 {
10247                 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10248                         plci->internal_command = plci->adjust_b_command;
10249                         if (plci->sig_req)
10250                         {
10251                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10252                                 break;
10253                         }
10254                         dtmf_parameter_write(plci);
10255                         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10256                         break;
10257                 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10258                         if ((Rc != OK) && (Rc != OK_FC))
10259                         {
10260                                 dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10261                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10262                                 Info = _WRONG_STATE;
10263                                 break;
10264                         }
10265                         break;
10266                 }
10267         }
10268         return (Info);
10269 }
10270
10271
10272 /*------------------------------------------------------------------*/
10273 /* Line interconnect facilities                                     */
10274 /*------------------------------------------------------------------*/
10275
10276
10277 LI_CONFIG   *li_config_table;
10278 word li_total_channels;
10279
10280
10281 /*------------------------------------------------------------------*/
10282 /* translate a CHI information element to a channel number          */
10283 /* returns 0xff - any channel                                       */
10284 /*         0xfe - chi wrong coding                                  */
10285 /*         0xfd - D-channel                                         */
10286 /*         0x00 - no channel                                        */
10287 /*         else channel number / PRI: timeslot                      */
10288 /* if channels is provided we accept more than one channel.         */
10289 /*------------------------------------------------------------------*/
10290
10291 static byte chi_to_channel(byte *chi, dword *pchannelmap)
10292 {
10293         int p;
10294         int i;
10295         dword map;
10296         byte excl;
10297         byte ofs;
10298         byte ch;
10299
10300         if (pchannelmap) *pchannelmap = 0;
10301         if (!chi[0]) return 0xff;
10302         excl = 0;
10303
10304         if (chi[1] & 0x20) {
10305                 if (chi[0] == 1 && chi[1] == 0xac) return 0xfd; /* exclusive d-channel */
10306                 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10307                 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10308                 if ((chi[1] | 0xc8) != 0xe9) return 0xfe;
10309                 if (chi[1] & 0x08) excl = 0x40;
10310
10311                 /* int. id present */
10312                 if (chi[1] & 0x40) {
10313                         p = i + 1;
10314                         for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10315                         if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10316                 }
10317
10318                 /* coding standard, Number/Map, Channel Type */
10319                 p = i + 1;
10320                 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10321                 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10322                 if ((chi[p] | 0xd0) != 0xd3) return 0xfe;
10323
10324                 /* Number/Map */
10325                 if (chi[p] & 0x10) {
10326
10327                         /* map */
10328                         if ((chi[0] - p) == 4) ofs = 0;
10329                         else if ((chi[0] - p) == 3) ofs = 1;
10330                         else return 0xfe;
10331                         ch = 0;
10332                         map = 0;
10333                         for (i = 0; i < 4 && p < chi[0]; i++) {
10334                                 p++;
10335                                 ch += 8;
10336                                 map <<= 8;
10337                                 if (chi[p]) {
10338                                         for (ch = 0; !(chi[p] & (1 << ch)); ch++);
10339                                         map |= chi[p];
10340                                 }
10341                         }
10342                         ch += ofs;
10343                         map <<= ofs;
10344                 }
10345                 else {
10346
10347                         /* number */
10348                         p = i + 1;
10349                         ch = chi[p] & 0x3f;
10350                         if (pchannelmap) {
10351                                 if ((byte)(chi[0] - p) > 30) return 0xfe;
10352                                 map = 0;
10353                                 for (i = p; i <= chi[0]; i++) {
10354                                         if ((chi[i] & 0x7f) > 31) return 0xfe;
10355                                         map |= (1L << (chi[i] & 0x7f));
10356                                 }
10357                         }
10358                         else {
10359                                 if (p != chi[0]) return 0xfe;
10360                                 if (ch > 31) return 0xfe;
10361                                 map = (1L << ch);
10362                         }
10363                         if (chi[p] & 0x40) return 0xfe;
10364                 }
10365                 if (pchannelmap) *pchannelmap = map;
10366                 else if (map != ((dword)(1L << ch))) return 0xfe;
10367                 return (byte)(excl | ch);
10368         }
10369         else {  /* not PRI */
10370                 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10371                 if (i != chi[0] || !(chi[i] & 0x80)) return 0xfe;
10372                 if (chi[1] & 0x08) excl = 0x40;
10373
10374                 switch (chi[1] | 0x98) {
10375                 case 0x98: return 0;
10376                 case 0x99:
10377                         if (pchannelmap) *pchannelmap = 2;
10378                         return excl | 1;
10379                 case 0x9a:
10380                         if (pchannelmap) *pchannelmap = 4;
10381                         return excl | 2;
10382                 case 0x9b: return 0xff;
10383                 case 0x9c: return 0xfd; /* d-ch */
10384                 default: return 0xfe;
10385                 }
10386         }
10387 }
10388
10389
10390 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id)
10391 {
10392         DIVA_CAPI_ADAPTER *a;
10393         PLCI *splci;
10394         byte old_id;
10395
10396         a = plci->adapter;
10397         old_id = plci->li_bchannel_id;
10398         if (a->li_pri)
10399         {
10400                 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10401                         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10402                 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10403                 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10404                         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10405         }
10406         else
10407         {
10408                 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10409                 {
10410                         if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10411                                 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10412                         plci->li_bchannel_id = bchannel_id & 0x03;
10413                         if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10414                         {
10415                                 splci = a->AdvSignalPLCI;
10416                                 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10417                                 {
10418                                         if ((splci->li_bchannel_id != 0)
10419                                             && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10420                                         {
10421                                                 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10422                                         }
10423                                         splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10424                                         li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10425                                         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10426                                                         (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10427                                                         (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10428                                 }
10429                         }
10430                         if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10431                                 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10432                 }
10433         }
10434         if ((old_id == 0) && (plci->li_bchannel_id != 0)
10435             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10436         {
10437                 mixer_clear_config(plci);
10438         }
10439         dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10440                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10441                         (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10442 }
10443
10444
10445 static void mixer_set_bchannel_id(PLCI *plci, byte *chi)
10446 {
10447         DIVA_CAPI_ADAPTER *a;
10448         PLCI *splci;
10449         byte ch, old_id;
10450
10451         a = plci->adapter;
10452         old_id = plci->li_bchannel_id;
10453         ch = chi_to_channel(chi, NULL);
10454         if (!(ch & 0x80))
10455         {
10456                 if (a->li_pri)
10457                 {
10458                         if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10459                                 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10460                         plci->li_bchannel_id = (ch & 0x1f) + 1;
10461                         if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10462                                 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10463                 }
10464                 else
10465                 {
10466                         if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10467                         {
10468                                 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10469                                         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10470                                 plci->li_bchannel_id = ch & 0x1f;
10471                                 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10472                                 {
10473                                         splci = a->AdvSignalPLCI;
10474                                         if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10475                                         {
10476                                                 if ((splci->li_bchannel_id != 0)
10477                                                     && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10478                                                 {
10479                                                         li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10480                                                 }
10481                                                 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10482                                                 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10483                                                 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10484                                                                 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10485                                                                 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10486                                         }
10487                                 }
10488                                 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10489                                         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10490                         }
10491                 }
10492         }
10493         if ((old_id == 0) && (plci->li_bchannel_id != 0)
10494             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10495         {
10496                 mixer_clear_config(plci);
10497         }
10498         dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10499                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10500                         (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10501 }
10502
10503
10504 #define MIXER_MAX_DUMP_CHANNELS 34
10505
10506 static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER *a)
10507 {
10508         word n, i, j;
10509         char *p;
10510         char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10511
10512         dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10513                         (dword)(UnMapController(a->Id)), (char *)(FILE_), __LINE__));
10514
10515         for (i = 0; i < li_total_channels; i++)
10516         {
10517                 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10518                 if (li_config_table[i].chflags != 0)
10519                         li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10520                 else
10521                 {
10522                         for (j = 0; j < li_total_channels; j++)
10523                         {
10524                                 if (((li_config_table[i].flag_table[j]) != 0)
10525                                     || ((li_config_table[j].flag_table[i]) != 0))
10526                                 {
10527                                         li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10528                                 }
10529                                 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10530                                     || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10531                                 {
10532                                         li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10533                                 }
10534                         }
10535                 }
10536         }
10537         for (i = 0; i < li_total_channels; i++)
10538         {
10539                 for (j = 0; j < li_total_channels; j++)
10540                 {
10541                         li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10542                         if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10543                                 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10544                 }
10545         }
10546         for (n = 0; n < li_total_channels; n++)
10547         {
10548                 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10549                 {
10550                         for (i = 0; i < li_total_channels; i++)
10551                         {
10552                                 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10553                                 {
10554                                         for (j = 0; j < li_total_channels; j++)
10555                                         {
10556                                                 li_config_table[i].coef_table[j] |=
10557                                                         li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10558                                         }
10559                                 }
10560                         }
10561                 }
10562         }
10563         for (i = 0; i < li_total_channels; i++)
10564         {
10565                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10566                 {
10567                         li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10568                         for (j = 0; j < li_total_channels; j++)
10569                         {
10570                                 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10571                                         li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10572                         }
10573                         if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10574                                 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10575                 }
10576         }
10577         for (i = 0; i < li_total_channels; i++)
10578         {
10579                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10580                 {
10581                         for (j = 0; j < li_total_channels; j++)
10582                         {
10583                                 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10584                                         li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10585                                 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10586                                         li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10587                                 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10588                                         li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10589                                 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10590                                         li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10591                         }
10592                         if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10593                         {
10594                                 for (j = 0; j < li_total_channels; j++)
10595                                 {
10596                                         if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10597                                         {
10598                                                 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10599                                                 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10600                                                         li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10601                                         }
10602                                 }
10603                         }
10604                         if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10605                         {
10606                                 for (j = 0; j < li_total_channels; j++)
10607                                 {
10608                                         if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10609                                                 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10610                                 }
10611                         }
10612                         if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10613                         {
10614                                 for (j = 0; j < li_total_channels; j++)
10615                                 {
10616                                         if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10617                                         {
10618                                                 for (n = 0; n < li_total_channels; n++)
10619                                                 {
10620                                                         if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10621                                                         {
10622                                                                 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10623                                                                 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10624                                                                 {
10625                                                                         li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10626                                                                         if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10627                                                                                 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10628                                                                 }
10629                                                                 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10630                                                                         li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10631                                                         }
10632                                                 }
10633                                         }
10634                                 }
10635                         }
10636                 }
10637         }
10638         for (i = 0; i < li_total_channels; i++)
10639         {
10640                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10641                 {
10642                         if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10643                                 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10644                         if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10645                                 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10646                         if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10647                                 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10648                         for (j = 0; j < li_total_channels; j++)
10649                         {
10650                                 if ((li_config_table[i].flag_table[j] &
10651                                      (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10652                                     || (li_config_table[j].flag_table[i] &
10653                                         (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10654                                 {
10655                                         li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10656                                 }
10657                                 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10658                                         li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10659                                 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10660                                         li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10661                         }
10662                         if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10663                         {
10664                                 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10665                                 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10666                         }
10667                 }
10668         }
10669         for (i = 0; i < li_total_channels; i++)
10670         {
10671                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10672                 {
10673                         j = 0;
10674                         while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10675                                 j++;
10676                         if (j < li_total_channels)
10677                         {
10678                                 for (j = 0; j < li_total_channels; j++)
10679                                 {
10680                                         li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10681                                         if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10682                                                 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10683                                 }
10684                         }
10685                 }
10686         }
10687         n = li_total_channels;
10688         if (n > MIXER_MAX_DUMP_CHANNELS)
10689                 n = MIXER_MAX_DUMP_CHANNELS;
10690
10691         p = hex_line;
10692         for (j = 0; j < n; j++)
10693         {
10694                 if ((j & 0x7) == 0)
10695                         *(p++) = ' ';
10696                 p = hex_byte_pack(p, li_config_table[j].curchnl);
10697         }
10698         *p = '\0';
10699         dbug(1, dprintf("[%06lx] CURRENT %s",
10700                         (dword)(UnMapController(a->Id)), (char *)hex_line));
10701         p = hex_line;
10702         for (j = 0; j < n; j++)
10703         {
10704                 if ((j & 0x7) == 0)
10705                         *(p++) = ' ';
10706                 p = hex_byte_pack(p, li_config_table[j].channel);
10707         }
10708         *p = '\0';
10709         dbug(1, dprintf("[%06lx] CHANNEL %s",
10710                         (dword)(UnMapController(a->Id)), (char *)hex_line));
10711         p = hex_line;
10712         for (j = 0; j < n; j++)
10713         {
10714                 if ((j & 0x7) == 0)
10715                         *(p++) = ' ';
10716                 p = hex_byte_pack(p, li_config_table[j].chflags);
10717         }
10718         *p = '\0';
10719         dbug(1, dprintf("[%06lx] CHFLAG  %s",
10720                         (dword)(UnMapController(a->Id)), (char *)hex_line));
10721         for (i = 0; i < n; i++)
10722         {
10723                 p = hex_line;
10724                 for (j = 0; j < n; j++)
10725                 {
10726                         if ((j & 0x7) == 0)
10727                                 *(p++) = ' ';
10728                         p = hex_byte_pack(p, li_config_table[i].flag_table[j]);
10729                 }
10730                 *p = '\0';
10731                 dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10732                                 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10733         }
10734         for (i = 0; i < n; i++)
10735         {
10736                 p = hex_line;
10737                 for (j = 0; j < n; j++)
10738                 {
10739                         if ((j & 0x7) == 0)
10740                                 *(p++) = ' ';
10741                         p = hex_byte_pack(p, li_config_table[i].coef_table[j]);
10742                 }
10743                 *p = '\0';
10744                 dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10745                                 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10746         }
10747 }
10748
10749
10750 static struct
10751 {
10752         byte mask;
10753         byte line_flags;
10754 } mixer_write_prog_pri[] =
10755 {
10756         { LI_COEF_CH_CH, 0 },
10757         { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10758         { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10759         { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10760 };
10761
10762 static struct
10763 {
10764         byte from_ch;
10765         byte to_ch;
10766         byte mask;
10767         byte xconnect_override;
10768 } mixer_write_prog_bri[] =
10769 {
10770         { 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10771         { 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10772         { 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10773         { 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10774         { 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10775         { 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10776         { 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10777         { 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10778         { 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10779         { 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10780         { 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10781         { 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10782         { 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10783         { 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10784         { 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10785         { 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10786         { 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10787         { 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10788         { 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10789         { 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10790         { 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10791         { 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10792         { 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10793         { 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10794         { 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10795         { 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10796         { 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10797         { 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10798         { 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10799         { 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10800         { 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10801         { 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10802         { 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10803         { 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10804         { 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10805         { 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10806 };
10807
10808 static byte mixer_swapped_index_bri[] =
10809 {
10810         18,  /* B      to B      */
10811         19,  /* Alt B  to B      */
10812         20,  /* PC     to B      */
10813         21,  /* Alt PC to B      */
10814         22,  /* IC     to B      */
10815         23,  /* Alt IC to B      */
10816         24,  /* B      to PC     */
10817         25,  /* Alt B  to PC     */
10818         26,  /* PC     to PC     */
10819         27,  /* Alt PC to PC     */
10820         28,  /* IC     to PC     */
10821         29,  /* Alt IC to PC     */
10822         30,  /* B      to IC     */
10823         31,  /* Alt B  to IC     */
10824         32,  /* PC     to IC     */
10825         33,  /* Alt PC to IC     */
10826         34,  /* IC     to IC     */
10827         35,  /* Alt IC to IC     */
10828         0,   /* Alt B  to Alt B  */
10829         1,   /* B      to Alt B  */
10830         2,   /* Alt PC to Alt B  */
10831         3,   /* PC     to Alt B  */
10832         4,   /* Alt IC to Alt B  */
10833         5,   /* IC     to Alt B  */
10834         6,   /* Alt B  to Alt PC */
10835         7,   /* B      to Alt PC */
10836         8,   /* Alt PC to Alt PC */
10837         9,   /* PC     to Alt PC */
10838         10,  /* Alt IC to Alt PC */
10839         11,  /* IC     to Alt PC */
10840         12,  /* Alt B  to Alt IC */
10841         13,  /* B      to Alt IC */
10842         14,  /* Alt PC to Alt IC */
10843         15,  /* PC     to Alt IC */
10844         16,  /* Alt IC to Alt IC */
10845         17   /* IC     to Alt IC */
10846 };
10847
10848 static struct
10849 {
10850         byte mask;
10851         byte from_pc;
10852         byte to_pc;
10853 } xconnect_write_prog[] =
10854 {
10855         { LI_COEF_CH_CH, false, false },
10856         { LI_COEF_CH_PC, false, true },
10857         { LI_COEF_PC_CH, true, false },
10858         { LI_COEF_PC_PC, true, true }
10859 };
10860
10861
10862 static void xconnect_query_addresses(PLCI *plci)
10863 {
10864         DIVA_CAPI_ADAPTER *a;
10865         word w, ch;
10866         byte *p;
10867
10868         dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10869                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10870                         (char *)(FILE_), __LINE__));
10871
10872         a = plci->adapter;
10873         if (a->li_pri && ((plci->li_bchannel_id == 0)
10874                           || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10875         {
10876                 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10877                                 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10878                                 (char *)(FILE_), __LINE__));
10879                 return;
10880         }
10881         p = plci->internal_req_buffer;
10882         ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10883         *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10884         w = ch;
10885         *(p++) = (byte) w;
10886         *(p++) = (byte)(w >> 8);
10887         w = ch | XCONNECT_CHANNEL_PORT_PC;
10888         *(p++) = (byte) w;
10889         *(p++) = (byte)(w >> 8);
10890         plci->NData[0].P = plci->internal_req_buffer;
10891         plci->NData[0].PLength = p - plci->internal_req_buffer;
10892         plci->NL.X = plci->NData;
10893         plci->NL.ReqCh = 0;
10894         plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10895         plci->adapter->request(&plci->NL);
10896 }
10897
10898
10899 static void xconnect_write_coefs(PLCI *plci, word internal_command)
10900 {
10901
10902         dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10903                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10904                         (char *)(FILE_), __LINE__, internal_command));
10905
10906         plci->li_write_command = internal_command;
10907         plci->li_write_channel = 0;
10908 }
10909
10910
10911 static byte xconnect_write_coefs_process(dword Id, PLCI *plci, byte Rc)
10912 {
10913         DIVA_CAPI_ADAPTER *a;
10914         word w, n, i, j, r, s, to_ch;
10915         dword d;
10916         byte *p;
10917         struct xconnect_transfer_address_s   *transfer_address;
10918         byte ch_map[MIXER_CHANNELS_BRI];
10919
10920         dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10921                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10922
10923         a = plci->adapter;
10924         if ((plci->li_bchannel_id == 0)
10925             || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10926         {
10927                 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10928                                 UnMapId(Id), (char *)(FILE_), __LINE__));
10929                 return (true);
10930         }
10931         i = a->li_base + (plci->li_bchannel_id - 1);
10932         j = plci->li_write_channel;
10933         p = plci->internal_req_buffer;
10934         if (j != 0)
10935         {
10936                 if ((Rc != OK) && (Rc != OK_FC))
10937                 {
10938                         dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10939                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10940                         return (false);
10941                 }
10942         }
10943         if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10944         {
10945                 r = 0;
10946                 s = 0;
10947                 if (j < li_total_channels)
10948                 {
10949                         if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10950                         {
10951                                 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10952                                      (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10953                                         ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10954                                          (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10955                         }
10956                         r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10957                         while ((j < li_total_channels)
10958                                && ((r == 0)
10959                                    || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10960                                    || (!li_config_table[j].adapter->li_pri
10961                                        && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10962                                    || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10963                                         || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10964                                        && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10965                                            || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10966                                    || ((li_config_table[j].adapter->li_base != a->li_base)
10967                                        && !(r & s &
10968                                             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10969                                              (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10970                                             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10971                                              (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10972                         {
10973                                 j++;
10974                                 if (j < li_total_channels)
10975                                         r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10976                         }
10977                 }
10978                 if (j < li_total_channels)
10979                 {
10980                         plci->internal_command = plci->li_write_command;
10981                         if (plci_nl_busy(plci))
10982                                 return (true);
10983                         to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10984                         *(p++) = UDATA_REQUEST_XCONNECT_TO;
10985                         do
10986                         {
10987                                 if (li_config_table[j].adapter->li_base != a->li_base)
10988                                 {
10989                                         r &= s &
10990                                                 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10991                                                  (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10992                                                 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10993                                                  (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10994                                 }
10995                                 n = 0;
10996                                 do
10997                                 {
10998                                         if (r & xconnect_write_prog[n].mask)
10999                                         {
11000                                                 if (xconnect_write_prog[n].from_pc)
11001                                                         transfer_address = &(li_config_table[j].send_pc);
11002                                                 else
11003                                                         transfer_address = &(li_config_table[j].send_b);
11004                                                 d = transfer_address->card_address.low;
11005                                                 *(p++) = (byte) d;
11006                                                 *(p++) = (byte)(d >> 8);
11007                                                 *(p++) = (byte)(d >> 16);
11008                                                 *(p++) = (byte)(d >> 24);
11009                                                 d = transfer_address->card_address.high;
11010                                                 *(p++) = (byte) d;
11011                                                 *(p++) = (byte)(d >> 8);
11012                                                 *(p++) = (byte)(d >> 16);
11013                                                 *(p++) = (byte)(d >> 24);
11014                                                 d = transfer_address->offset;
11015                                                 *(p++) = (byte) d;
11016                                                 *(p++) = (byte)(d >> 8);
11017                                                 *(p++) = (byte)(d >> 16);
11018                                                 *(p++) = (byte)(d >> 24);
11019                                                 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11020                                                 *(p++) = (byte) w;
11021                                                 *(p++) = (byte)(w >> 8);
11022                                                 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11023                                                         (li_config_table[i].adapter->u_law ?
11024                                                          (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11025                                                          (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11026                                                 *(p++) = (byte) w;
11027                                                 *(p++) = (byte) 0;
11028                                                 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11029                                         }
11030                                         n++;
11031                                 } while ((n < ARRAY_SIZE(xconnect_write_prog))
11032                                          && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11033                                 if (n == ARRAY_SIZE(xconnect_write_prog))
11034                                 {
11035                                         do
11036                                         {
11037                                                 j++;
11038                                                 if (j < li_total_channels)
11039                                                         r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11040                                         } while ((j < li_total_channels)
11041                                                  && ((r == 0)
11042                                                      || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11043                                                      || (!li_config_table[j].adapter->li_pri
11044                                                          && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11045                                                      || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11046                                                           || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11047                                                          && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11048                                                              || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11049                                                      || ((li_config_table[j].adapter->li_base != a->li_base)
11050                                                          && !(r & s &
11051                                                               ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11052                                                                (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11053                                                               ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11054                                                                (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11055                                 }
11056                         } while ((j < li_total_channels)
11057                                  && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11058                 }
11059                 else if (j == li_total_channels)
11060                 {
11061                         plci->internal_command = plci->li_write_command;
11062                         if (plci_nl_busy(plci))
11063                                 return (true);
11064                         if (a->li_pri)
11065                         {
11066                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11067                                 w = 0;
11068                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11069                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
11070                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11071                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
11072                                 *(p++) = (byte) w;
11073                                 *(p++) = (byte)(w >> 8);
11074                         }
11075                         else
11076                         {
11077                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11078                                 w = 0;
11079                                 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11080                                     && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11081                                 {
11082                                         w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11083                                 }
11084                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11085                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
11086                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11087                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
11088                                 *(p++) = (byte) w;
11089                                 *(p++) = (byte)(w >> 8);
11090                                 for (j = 0; j < sizeof(ch_map); j += 2)
11091                                 {
11092                                         if (plci->li_bchannel_id == 2)
11093                                         {
11094                                                 ch_map[j] = (byte)(j + 1);
11095                                                 ch_map[j + 1] = (byte) j;
11096                                         }
11097                                         else
11098                                         {
11099                                                 ch_map[j] = (byte) j;
11100                                                 ch_map[j + 1] = (byte)(j + 1);
11101                                         }
11102                                 }
11103                                 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11104                                 {
11105                                         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11106                                         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11107                                         if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11108                                         {
11109                                                 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11110                                                         mixer_write_prog_bri[n].xconnect_override :
11111                                                         ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11112                                                 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11113                                                 {
11114                                                         w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11115                                                         li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11116                                                 }
11117                                         }
11118                                         else
11119                                         {
11120                                                 *p = 0x00;
11121                                                 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11122                                                 {
11123                                                         w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11124                                                         if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11125                                                                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11126                                                 }
11127                                         }
11128                                         p++;
11129                                 }
11130                         }
11131                         j = li_total_channels + 1;
11132                 }
11133         }
11134         else
11135         {
11136                 if (j <= li_total_channels)
11137                 {
11138                         plci->internal_command = plci->li_write_command;
11139                         if (plci_nl_busy(plci))
11140                                 return (true);
11141                         if (j < a->li_base)
11142                                 j = a->li_base;
11143                         if (a->li_pri)
11144                         {
11145                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11146                                 w = 0;
11147                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11148                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
11149                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11150                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
11151                                 *(p++) = (byte) w;
11152                                 *(p++) = (byte)(w >> 8);
11153                                 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11154                                 {
11155                                         *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11156                                         for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11157                                         {
11158                                                 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11159                                                 if (w & mixer_write_prog_pri[n].mask)
11160                                                 {
11161                                                         *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11162                                                         li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11163                                                 }
11164                                                 else
11165                                                         *(p++) = 0x00;
11166                                         }
11167                                         *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11168                                         for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11169                                         {
11170                                                 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11171                                                 if (w & mixer_write_prog_pri[n].mask)
11172                                                 {
11173                                                         *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11174                                                         li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11175                                                 }
11176                                                 else
11177                                                         *(p++) = 0x00;
11178                                         }
11179                                 }
11180                         }
11181                         else
11182                         {
11183                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11184                                 w = 0;
11185                                 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11186                                     && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11187                                 {
11188                                         w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11189                                 }
11190                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11191                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
11192                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11193                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
11194                                 *(p++) = (byte) w;
11195                                 *(p++) = (byte)(w >> 8);
11196                                 for (j = 0; j < sizeof(ch_map); j += 2)
11197                                 {
11198                                         if (plci->li_bchannel_id == 2)
11199                                         {
11200                                                 ch_map[j] = (byte)(j + 1);
11201                                                 ch_map[j + 1] = (byte) j;
11202                                         }
11203                                         else
11204                                         {
11205                                                 ch_map[j] = (byte) j;
11206                                                 ch_map[j + 1] = (byte)(j + 1);
11207                                         }
11208                                 }
11209                                 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11210                                 {
11211                                         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11212                                         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11213                                         if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11214                                         {
11215                                                 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11216                                                 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11217                                                 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11218                                         }
11219                                         else
11220                                         {
11221                                                 *p = 0x00;
11222                                                 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11223                                                 {
11224                                                         w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11225                                                         if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11226                                                                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11227                                                 }
11228                                         }
11229                                         p++;
11230                                 }
11231                         }
11232                         j = li_total_channels + 1;
11233                 }
11234         }
11235         plci->li_write_channel = j;
11236         if (p != plci->internal_req_buffer)
11237         {
11238                 plci->NData[0].P = plci->internal_req_buffer;
11239                 plci->NData[0].PLength = p - plci->internal_req_buffer;
11240                 plci->NL.X = plci->NData;
11241                 plci->NL.ReqCh = 0;
11242                 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11243                 plci->adapter->request(&plci->NL);
11244         }
11245         return (true);
11246 }
11247
11248
11249 static void mixer_notify_update(PLCI *plci, byte others)
11250 {
11251         DIVA_CAPI_ADAPTER *a;
11252         word i, w;
11253         PLCI *notify_plci;
11254         byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11255
11256         dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11257                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11258                         (char *)(FILE_), __LINE__, others));
11259
11260         a = plci->adapter;
11261         if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11262         {
11263                 if (others)
11264                         plci->li_notify_update = true;
11265                 i = 0;
11266                 do
11267                 {
11268                         notify_plci = NULL;
11269                         if (others)
11270                         {
11271                                 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11272                                         i++;
11273                                 if (i < li_total_channels)
11274                                         notify_plci = li_config_table[i++].plci;
11275                         }
11276                         else
11277                         {
11278                                 if ((plci->li_bchannel_id != 0)
11279                                     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11280                                 {
11281                                         notify_plci = plci;
11282                                 }
11283                         }
11284                         if ((notify_plci != NULL)
11285                             && !notify_plci->li_notify_update
11286                             && (notify_plci->appl != NULL)
11287                             && (notify_plci->State)
11288                             && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11289                         {
11290                                 notify_plci->li_notify_update = true;
11291                                 ((CAPI_MSG *) msg)->header.length = 18;
11292                                 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11293                                 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11294                                 ((CAPI_MSG *) msg)->header.number = 0;
11295                                 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11296                                 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11297                                 ((CAPI_MSG *) msg)->header.ncci = 0;
11298                                 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11299                                 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11300                                 ((CAPI_MSG *) msg)->info.facility_req.structs[1] = LI_REQ_SILENT_UPDATE & 0xff;
11301                                 ((CAPI_MSG *) msg)->info.facility_req.structs[2] = LI_REQ_SILENT_UPDATE >> 8;
11302                                 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11303                                 w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11304                                 if (w != _QUEUE_FULL)
11305                                 {
11306                                         if (w != 0)
11307                                         {
11308                                                 dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11309                                                                 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11310                                                                 (char *)(FILE_), __LINE__,
11311                                                                 (dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11312                                         }
11313                                         notify_plci->li_notify_update = false;
11314                                 }
11315                         }
11316                 } while (others && (notify_plci != NULL));
11317                 if (others)
11318                         plci->li_notify_update = false;
11319         }
11320 }
11321
11322
11323 static void mixer_clear_config(PLCI *plci)
11324 {
11325         DIVA_CAPI_ADAPTER *a;
11326         word i, j;
11327
11328         dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11329                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11330                         (char *)(FILE_), __LINE__));
11331
11332         plci->li_notify_update = false;
11333         plci->li_plci_b_write_pos = 0;
11334         plci->li_plci_b_read_pos = 0;
11335         plci->li_plci_b_req_pos = 0;
11336         a = plci->adapter;
11337         if ((plci->li_bchannel_id != 0)
11338             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11339         {
11340                 i = a->li_base + (plci->li_bchannel_id - 1);
11341                 li_config_table[i].curchnl = 0;
11342                 li_config_table[i].channel = 0;
11343                 li_config_table[i].chflags = 0;
11344                 for (j = 0; j < li_total_channels; j++)
11345                 {
11346                         li_config_table[j].flag_table[i] = 0;
11347                         li_config_table[i].flag_table[j] = 0;
11348                         li_config_table[i].coef_table[j] = 0;
11349                         li_config_table[j].coef_table[i] = 0;
11350                 }
11351                 if (!a->li_pri)
11352                 {
11353                         li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11354                         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11355                         {
11356                                 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11357                                 li_config_table[i].curchnl = 0;
11358                                 li_config_table[i].channel = 0;
11359                                 li_config_table[i].chflags = 0;
11360                                 for (j = 0; j < li_total_channels; j++)
11361                                 {
11362                                         li_config_table[i].flag_table[j] = 0;
11363                                         li_config_table[j].flag_table[i] = 0;
11364                                         li_config_table[i].coef_table[j] = 0;
11365                                         li_config_table[j].coef_table[i] = 0;
11366                                 }
11367                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11368                                 {
11369                                         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11370                                         li_config_table[i].curchnl = 0;
11371                                         li_config_table[i].channel = 0;
11372                                         li_config_table[i].chflags = 0;
11373                                         for (j = 0; j < li_total_channels; j++)
11374                                         {
11375                                                 li_config_table[i].flag_table[j] = 0;
11376                                                 li_config_table[j].flag_table[i] = 0;
11377                                                 li_config_table[i].coef_table[j] = 0;
11378                                                 li_config_table[j].coef_table[i] = 0;
11379                                         }
11380                                 }
11381                         }
11382                 }
11383         }
11384 }
11385
11386
11387 static void mixer_prepare_switch(dword Id, PLCI *plci)
11388 {
11389
11390         dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11391                         UnMapId(Id), (char *)(FILE_), __LINE__));
11392
11393         do
11394         {
11395                 mixer_indication_coefs_set(Id, plci);
11396         } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11397 }
11398
11399
11400 static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11401 {
11402         DIVA_CAPI_ADAPTER *a;
11403         word i, j;
11404
11405         dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11406                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11407
11408         a = plci->adapter;
11409         if ((plci->li_bchannel_id != 0)
11410             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11411         {
11412                 i = a->li_base + (plci->li_bchannel_id - 1);
11413                 for (j = 0; j < li_total_channels; j++)
11414                 {
11415                         li_config_table[i].coef_table[j] &= 0xf;
11416                         li_config_table[j].coef_table[i] &= 0xf;
11417                 }
11418                 if (!a->li_pri)
11419                         li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11420         }
11421         return (GOOD);
11422 }
11423
11424
11425 static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11426 {
11427         DIVA_CAPI_ADAPTER *a;
11428         word Info;
11429
11430         dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11431                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11432
11433         Info = GOOD;
11434         a = plci->adapter;
11435         if ((plci->B1_facilities & B1_FACILITY_MIXER)
11436             && (plci->li_bchannel_id != 0)
11437             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11438         {
11439                 switch (plci->adjust_b_state)
11440                 {
11441                 case ADJUST_B_RESTORE_MIXER_1:
11442                         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11443                         {
11444                                 plci->internal_command = plci->adjust_b_command;
11445                                 if (plci_nl_busy(plci))
11446                                 {
11447                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11448                                         break;
11449                                 }
11450                                 xconnect_query_addresses(plci);
11451                                 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11452                                 break;
11453                         }
11454                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11455                         Rc = OK;
11456                 case ADJUST_B_RESTORE_MIXER_2:
11457                 case ADJUST_B_RESTORE_MIXER_3:
11458                 case ADJUST_B_RESTORE_MIXER_4:
11459                         if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11460                         {
11461                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11462                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11463                                 Info = _WRONG_STATE;
11464                                 break;
11465                         }
11466                         if (Rc == OK)
11467                         {
11468                                 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11469                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11470                                 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11471                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11472                         }
11473                         else if (Rc == 0)
11474                         {
11475                                 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11476                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11477                                 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11478                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11479                         }
11480                         if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11481                         {
11482                                 plci->internal_command = plci->adjust_b_command;
11483                                 break;
11484                         }
11485                 case ADJUST_B_RESTORE_MIXER_5:
11486                         xconnect_write_coefs(plci, plci->adjust_b_command);
11487                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11488                         Rc = OK;
11489                 case ADJUST_B_RESTORE_MIXER_6:
11490                         if (!xconnect_write_coefs_process(Id, plci, Rc))
11491                         {
11492                                 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11493                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11494                                 Info = _FACILITY_NOT_SUPPORTED;
11495                                 break;
11496                         }
11497                         if (plci->internal_command)
11498                                 break;
11499                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11500                 case ADJUST_B_RESTORE_MIXER_7:
11501                         break;
11502                 }
11503         }
11504         return (Info);
11505 }
11506
11507
11508 static void mixer_command(dword Id, PLCI *plci, byte Rc)
11509 {
11510         DIVA_CAPI_ADAPTER *a;
11511         word i, internal_command;
11512
11513         dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11514                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11515                         plci->li_cmd));
11516
11517         a = plci->adapter;
11518         internal_command = plci->internal_command;
11519         plci->internal_command = 0;
11520         switch (plci->li_cmd)
11521         {
11522         case LI_REQ_CONNECT:
11523         case LI_REQ_DISCONNECT:
11524         case LI_REQ_SILENT_UPDATE:
11525                 switch (internal_command)
11526                 {
11527                 default:
11528                         if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11529                         {
11530                                 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11531                                                                           B1_FACILITY_MIXER), MIXER_COMMAND_1);
11532                         }
11533                 case MIXER_COMMAND_1:
11534                         if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11535                         {
11536                                 if (adjust_b_process(Id, plci, Rc) != GOOD)
11537                                 {
11538                                         dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11539                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
11540                                         break;
11541                                 }
11542                                 if (plci->internal_command)
11543                                         return;
11544                         }
11545                         plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11546                         if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11547                             || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11548                                 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11549                                                                                       ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11550                         {
11551                                 xconnect_write_coefs(plci, MIXER_COMMAND_2);
11552                         }
11553                         else
11554                         {
11555                                 do
11556                                 {
11557                                         mixer_indication_coefs_set(Id, plci);
11558                                 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11559                         }
11560                 case MIXER_COMMAND_2:
11561                         if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11562                             || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11563                                 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11564                                                                                       ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11565                         {
11566                                 if (!xconnect_write_coefs_process(Id, plci, Rc))
11567                                 {
11568                                         dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11569                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
11570                                         if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11571                                         {
11572                                                 do
11573                                                 {
11574                                                         plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11575                                                                 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11576                                                         i = (plci->li_plci_b_write_pos == 0) ?
11577                                                                 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11578                                                 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11579                                                          && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11580                                         }
11581                                         break;
11582                                 }
11583                                 if (plci->internal_command)
11584                                         return;
11585                         }
11586                         if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11587                         {
11588                                 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11589                                                                           ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11590                         }
11591                 case MIXER_COMMAND_3:
11592                         if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11593                         {
11594                                 if (adjust_b_process(Id, plci, Rc) != GOOD)
11595                                 {
11596                                         dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11597                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
11598                                         break;
11599                                 }
11600                                 if (plci->internal_command)
11601                                         return;
11602                         }
11603                         break;
11604                 }
11605                 break;
11606         }
11607         if ((plci->li_bchannel_id == 0)
11608             || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11609         {
11610                 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11611                                 UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11612         }
11613         else
11614         {
11615                 i = a->li_base + (plci->li_bchannel_id - 1);
11616                 li_config_table[i].curchnl = plci->li_channel_bits;
11617                 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11618                 {
11619                         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11620                         li_config_table[i].curchnl = plci->li_channel_bits;
11621                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11622                         {
11623                                 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11624                                 li_config_table[i].curchnl = plci->li_channel_bits;
11625                         }
11626                 }
11627         }
11628 }
11629
11630
11631 static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11632                               dword plci_b_id, byte connect, dword li_flags)
11633 {
11634         word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11635         PLCI *plci_b;
11636         DIVA_CAPI_ADAPTER *a_b;
11637
11638         a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11639         plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11640         ch_a = a->li_base + (plci->li_bchannel_id - 1);
11641         if (!a->li_pri && (plci->tel == ADV_VOICE)
11642             && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11643         {
11644                 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11645                 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11646                         a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11647         }
11648         else
11649         {
11650                 ch_a_v = ch_a;
11651                 ch_a_s = ch_a;
11652         }
11653         ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11654         if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11655             && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11656         {
11657                 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11658                 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11659                         a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11660         }
11661         else
11662         {
11663                 ch_b_v = ch_b;
11664                 ch_b_s = ch_b;
11665         }
11666         if (connect)
11667         {
11668                 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11669                 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11670                 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11671                 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11672         }
11673         li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11674         li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11675         li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11676         li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11677         if (ch_a_v == ch_b_v)
11678         {
11679                 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11680                 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11681         }
11682         else
11683         {
11684                 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11685                 {
11686                         for (i = 0; i < li_total_channels; i++)
11687                         {
11688                                 if (i != ch_a_v)
11689                                         li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11690                         }
11691                 }
11692                 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11693                 {
11694                         for (i = 0; i < li_total_channels; i++)
11695                         {
11696                                 if (i != ch_a_s)
11697                                         li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11698                         }
11699                 }
11700                 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11701                 {
11702                         for (i = 0; i < li_total_channels; i++)
11703                         {
11704                                 if (i != ch_a_v)
11705                                         li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11706                         }
11707                 }
11708                 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11709                 {
11710                         for (i = 0; i < li_total_channels; i++)
11711                         {
11712                                 if (i != ch_a_s)
11713                                         li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11714                         }
11715                 }
11716         }
11717         if (li_flags & LI_FLAG_CONFERENCE_A_B)
11718         {
11719                 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11720                 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11721                 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11722                 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11723         }
11724         if (li_flags & LI_FLAG_CONFERENCE_B_A)
11725         {
11726                 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11727                 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11728                 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11729                 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11730         }
11731         if (li_flags & LI_FLAG_MONITOR_A)
11732         {
11733                 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11734                 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11735         }
11736         if (li_flags & LI_FLAG_MONITOR_B)
11737         {
11738                 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11739                 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11740         }
11741         if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11742         {
11743                 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11744                 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11745         }
11746         if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11747         {
11748                 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11749                 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11750         }
11751         if (li_flags & LI_FLAG_MIX_A)
11752         {
11753                 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11754                 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11755         }
11756         if (li_flags & LI_FLAG_MIX_B)
11757         {
11758                 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11759                 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11760         }
11761         if (ch_a_v != ch_a_s)
11762         {
11763                 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11764                 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11765         }
11766         if (ch_b_v != ch_b_s)
11767         {
11768                 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11769                 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11770         }
11771 }
11772
11773
11774 static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11775                                dword plci_b_id, byte connect, dword li_flags)
11776 {
11777         word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11778         PLCI *plci_b;
11779         DIVA_CAPI_ADAPTER *a_b;
11780
11781         a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11782         plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11783         ch_a = a->li_base + (plci->li_bchannel_id - 1);
11784         if (!a->li_pri && (plci->tel == ADV_VOICE)
11785             && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11786         {
11787                 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11788                 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11789                         a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11790         }
11791         else
11792         {
11793                 ch_a_v = ch_a;
11794                 ch_a_s = ch_a;
11795         }
11796         ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11797         if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11798             && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11799         {
11800                 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11801                 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11802                         a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11803         }
11804         else
11805         {
11806                 ch_b_v = ch_b;
11807                 ch_b_s = ch_b;
11808         }
11809         if (connect)
11810         {
11811                 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11812                 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11813                 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11814                 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11815                 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11816                 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11817         }
11818         li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11819         li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11820         li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11821         li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11822         li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11823         li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11824         li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11825         li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11826         if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11827         {
11828                 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11829                 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11830                 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11831                 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11832         }
11833         if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11834         {
11835                 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11836                 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11837                 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11838                 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11839         }
11840         if (li_flags & LI2_FLAG_MONITOR_B)
11841         {
11842                 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11843                 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11844         }
11845         if (li_flags & LI2_FLAG_MIX_B)
11846         {
11847                 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11848                 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11849         }
11850         if (li_flags & LI2_FLAG_MONITOR_X)
11851                 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11852         if (li_flags & LI2_FLAG_MIX_X)
11853                 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11854         if (li_flags & LI2_FLAG_LOOP_B)
11855         {
11856                 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11857                 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11858                 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11859                 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11860         }
11861         if (li_flags & LI2_FLAG_LOOP_PC)
11862                 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11863         if (li_flags & LI2_FLAG_LOOP_X)
11864                 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11865         if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11866                 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11867         if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11868                 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11869         if (ch_a_v != ch_a_s)
11870         {
11871                 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11872                 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11873         }
11874         if (ch_b_v != ch_b_s)
11875         {
11876                 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11877                 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11878         }
11879 }
11880
11881
11882 static word li_check_main_plci(dword Id, PLCI *plci)
11883 {
11884         if (plci == NULL)
11885         {
11886                 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11887                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11888                 return (_WRONG_IDENTIFIER);
11889         }
11890         if (!plci->State
11891             || !plci->NL.Id || plci->nl_remove_id
11892             || (plci->li_bchannel_id == 0))
11893         {
11894                 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11895                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11896                 return (_WRONG_STATE);
11897         }
11898         li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11899         return (GOOD);
11900 }
11901
11902
11903 static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11904                              dword plci_b_id, word plci_b_write_pos, byte *p_result)
11905 {
11906         byte ctlr_b;
11907         PLCI *plci_b;
11908
11909         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11910              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11911         {
11912                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11913                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11914                 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11915                 return (NULL);
11916         }
11917         ctlr_b = 0;
11918         if ((plci_b_id & 0x7f) != 0)
11919         {
11920                 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11921                 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11922                         ctlr_b = 0;
11923         }
11924         if ((ctlr_b == 0)
11925             || (((plci_b_id >> 8) & 0xff) == 0)
11926             || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11927         {
11928                 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11929                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11930                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11931                 return (NULL);
11932         }
11933         plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11934         if (!plci_b->State
11935             || !plci_b->NL.Id || plci_b->nl_remove_id
11936             || (plci_b->li_bchannel_id == 0))
11937         {
11938                 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11939                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11940                 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11941                 return (NULL);
11942         }
11943         li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11944         if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11945             ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11946             && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11947                 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11948         {
11949                 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11950                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11951                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11952                 return (NULL);
11953         }
11954         if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11955                                                           (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11956         {
11957                 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11958                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11959                 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11960                 return (NULL);
11961         }
11962         return (plci_b);
11963 }
11964
11965
11966 static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11967                               dword plci_b_id, word plci_b_write_pos, byte *p_result)
11968 {
11969         byte ctlr_b;
11970         PLCI *plci_b;
11971
11972         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11973              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11974         {
11975                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11976                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11977                 PUT_WORD(p_result, _WRONG_STATE);
11978                 return (NULL);
11979         }
11980         ctlr_b = 0;
11981         if ((plci_b_id & 0x7f) != 0)
11982         {
11983                 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11984                 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11985                         ctlr_b = 0;
11986         }
11987         if ((ctlr_b == 0)
11988             || (((plci_b_id >> 8) & 0xff) == 0)
11989             || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11990         {
11991                 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11992                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11993                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11994                 return (NULL);
11995         }
11996         plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11997         if (!plci_b->State
11998             || !plci_b->NL.Id || plci_b->nl_remove_id
11999             || (plci_b->li_bchannel_id == 0)
12000             || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12001         {
12002                 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
12003                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12004                 PUT_WORD(p_result, _WRONG_STATE);
12005                 return (NULL);
12006         }
12007         if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12008             ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
12009             && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12010                 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12011         {
12012                 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
12013                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12014                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
12015                 return (NULL);
12016         }
12017         if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
12018                                                           (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12019         {
12020                 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12021                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12022                 PUT_WORD(p_result, _WRONG_STATE);
12023                 return (NULL);
12024         }
12025         return (plci_b);
12026 }
12027
12028
12029 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
12030 {
12031         word Info;
12032         word i;
12033         dword d, li_flags, plci_b_id;
12034         PLCI *plci_b;
12035         API_PARSE li_parms[3];
12036         API_PARSE li_req_parms[3];
12037         API_PARSE li_participant_struct[2];
12038         API_PARSE li_participant_parms[3];
12039         word participant_parms_pos;
12040         byte result_buffer[32];
12041         byte *result;
12042         word result_pos;
12043         word plci_b_write_pos;
12044
12045         dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
12046                         UnMapId(Id), (char *)(FILE_), __LINE__));
12047
12048         Info = GOOD;
12049         result = result_buffer;
12050         result_buffer[0] = 0;
12051         if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12052         {
12053                 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12054                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12055                 Info = _FACILITY_NOT_SUPPORTED;
12056         }
12057         else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
12058         {
12059                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12060                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12061                 Info = _WRONG_MESSAGE_FORMAT;
12062         }
12063         else
12064         {
12065                 result_buffer[0] = 3;
12066                 PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
12067                 result_buffer[3] = 0;
12068                 switch (GET_WORD(li_parms[0].info))
12069                 {
12070                 case LI_GET_SUPPORTED_SERVICES:
12071                         if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12072                         {
12073                                 result_buffer[0] = 17;
12074                                 result_buffer[3] = 14;
12075                                 PUT_WORD(&result_buffer[4], GOOD);
12076                                 d = 0;
12077                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12078                                         d |= LI_CONFERENCING_SUPPORTED;
12079                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12080                                         d |= LI_MONITORING_SUPPORTED;
12081                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12082                                         d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12083                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12084                                         d |= LI_CROSS_CONTROLLER_SUPPORTED;
12085                                 PUT_DWORD(&result_buffer[6], d);
12086                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12087                                 {
12088                                         d = 0;
12089                                         for (i = 0; i < li_total_channels; i++)
12090                                         {
12091                                                 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12092                                                     && (li_config_table[i].adapter->li_pri
12093                                                         || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12094                                                 {
12095                                                         d++;
12096                                                 }
12097                                         }
12098                                 }
12099                                 else
12100                                 {
12101                                         d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12102                                 }
12103                                 PUT_DWORD(&result_buffer[10], d / 2);
12104                                 PUT_DWORD(&result_buffer[14], d);
12105                         }
12106                         else
12107                         {
12108                                 result_buffer[0] = 25;
12109                                 result_buffer[3] = 22;
12110                                 PUT_WORD(&result_buffer[4], GOOD);
12111                                 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12112                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12113                                         d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12114                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12115                                         d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12116                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12117                                         d |= LI2_PC_LOOPING_SUPPORTED;
12118                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12119                                         d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12120                                 PUT_DWORD(&result_buffer[6], d);
12121                                 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12122                                 PUT_DWORD(&result_buffer[10], d / 2);
12123                                 PUT_DWORD(&result_buffer[14], d - 1);
12124                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12125                                 {
12126                                         d = 0;
12127                                         for (i = 0; i < li_total_channels; i++)
12128                                         {
12129                                                 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12130                                                     && (li_config_table[i].adapter->li_pri
12131                                                         || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12132                                                 {
12133                                                         d++;
12134                                                 }
12135                                         }
12136                                 }
12137                                 PUT_DWORD(&result_buffer[18], d / 2);
12138                                 PUT_DWORD(&result_buffer[22], d - 1);
12139                         }
12140                         break;
12141
12142                 case LI_REQ_CONNECT:
12143                         if (li_parms[1].length == 8)
12144                         {
12145                                 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12146                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12147                                 {
12148                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12149                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12150                                         Info = _WRONG_MESSAGE_FORMAT;
12151                                         break;
12152                                 }
12153                                 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12154                                 li_flags = GET_DWORD(li_req_parms[1].info);
12155                                 Info = li_check_main_plci(Id, plci);
12156                                 result_buffer[0] = 9;
12157                                 result_buffer[3] = 6;
12158                                 PUT_DWORD(&result_buffer[4], plci_b_id);
12159                                 PUT_WORD(&result_buffer[8], GOOD);
12160                                 if (Info != GOOD)
12161                                         break;
12162                                 result = plci->saved_msg.info;
12163                                 for (i = 0; i <= result_buffer[0]; i++)
12164                                         result[i] = result_buffer[i];
12165                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12166                                 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12167                                 if (plci_b == NULL)
12168                                         break;
12169                                 li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12170                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12171                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12172                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12173                         }
12174                         else
12175                         {
12176                                 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12177                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12178                                 {
12179                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12180                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12181                                         Info = _WRONG_MESSAGE_FORMAT;
12182                                         break;
12183                                 }
12184                                 li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
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                                 li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12199                                 while (participant_parms_pos < li_req_parms[1].length)
12200                                 {
12201                                         result[result_pos] = 6;
12202                                         result_pos += 7;
12203                                         PUT_DWORD(&result[result_pos - 6], 0);
12204                                         PUT_WORD(&result[result_pos - 2], GOOD);
12205                                         if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12206                                                       (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12207                                         {
12208                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12209                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12210                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12211                                                 break;
12212                                         }
12213                                         if (api_parse(&li_participant_struct[0].info[1],
12214                                                       li_participant_struct[0].length, "dd", li_participant_parms))
12215                                         {
12216                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12217                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12218                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12219                                                 break;
12220                                         }
12221                                         plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12222                                         li_flags = GET_DWORD(li_participant_parms[1].info);
12223                                         PUT_DWORD(&result[result_pos - 6], plci_b_id);
12224                                         if (sizeof(result) - result_pos < 7)
12225                                         {
12226                                                 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12227                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12228                                                 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12229                                                 break;
12230                                         }
12231                                         plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12232                                         if (plci_b != NULL)
12233                                         {
12234                                                 li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12235                                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12236                                                         ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12237                                                                       LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12238                                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12239                                         }
12240                                         participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12241                                                                        (&li_req_parms[1].info[1]));
12242                                 }
12243                                 result[0] = (byte)(result_pos - 1);
12244                                 result[3] = (byte)(result_pos - 4);
12245                                 result[6] = (byte)(result_pos - 7);
12246                                 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12247                                 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12248                                     || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12249                                 {
12250                                         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12251                                         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12252                                 }
12253                                 else
12254                                         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12255                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12256                         }
12257                         mixer_calculate_coefs(a);
12258                         plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12259                         mixer_notify_update(plci, true);
12260                         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12261                               "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12262                         plci->command = 0;
12263                         plci->li_cmd = GET_WORD(li_parms[0].info);
12264                         start_internal_command(Id, plci, mixer_command);
12265                         return (false);
12266
12267                 case LI_REQ_DISCONNECT:
12268                         if (li_parms[1].length == 4)
12269                         {
12270                                 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12271                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12272                                 {
12273                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12274                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12275                                         Info = _WRONG_MESSAGE_FORMAT;
12276                                         break;
12277                                 }
12278                                 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12279                                 Info = li_check_main_plci(Id, plci);
12280                                 result_buffer[0] = 9;
12281                                 result_buffer[3] = 6;
12282                                 PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12283                                 PUT_WORD(&result_buffer[8], GOOD);
12284                                 if (Info != GOOD)
12285                                         break;
12286                                 result = plci->saved_msg.info;
12287                                 for (i = 0; i <= result_buffer[0]; i++)
12288                                         result[i] = result_buffer[i];
12289                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12290                                 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12291                                 if (plci_b == NULL)
12292                                         break;
12293                                 li_update_connect(Id, a, plci, plci_b_id, false, 0);
12294                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12295                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12296                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12297                         }
12298                         else
12299                         {
12300                                 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12301                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12302                                 {
12303                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12304                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12305                                         Info = _WRONG_MESSAGE_FORMAT;
12306                                         break;
12307                                 }
12308                                 Info = li_check_main_plci(Id, plci);
12309                                 result_buffer[0] = 7;
12310                                 result_buffer[3] = 4;
12311                                 PUT_WORD(&result_buffer[4], Info);
12312                                 result_buffer[6] = 0;
12313                                 if (Info != GOOD)
12314                                         break;
12315                                 result = plci->saved_msg.info;
12316                                 for (i = 0; i <= result_buffer[0]; i++)
12317                                         result[i] = result_buffer[i];
12318                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12319                                 participant_parms_pos = 0;
12320                                 result_pos = 7;
12321                                 while (participant_parms_pos < li_req_parms[0].length)
12322                                 {
12323                                         result[result_pos] = 6;
12324                                         result_pos += 7;
12325                                         PUT_DWORD(&result[result_pos - 6], 0);
12326                                         PUT_WORD(&result[result_pos - 2], GOOD);
12327                                         if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12328                                                       (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12329                                         {
12330                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12331                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12332                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12333                                                 break;
12334                                         }
12335                                         if (api_parse(&li_participant_struct[0].info[1],
12336                                                       li_participant_struct[0].length, "d", li_participant_parms))
12337                                         {
12338                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12339                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12340                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12341                                                 break;
12342                                         }
12343                                         plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12344                                         PUT_DWORD(&result[result_pos - 6], plci_b_id);
12345                                         if (sizeof(result) - result_pos < 7)
12346                                         {
12347                                                 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12348                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12349                                                 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12350                                                 break;
12351                                         }
12352                                         plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12353                                         if (plci_b != NULL)
12354                                         {
12355                                                 li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12356                                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12357                                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12358                                         }
12359                                         participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12360                                                                        (&li_req_parms[0].info[1]));
12361                                 }
12362                                 result[0] = (byte)(result_pos - 1);
12363                                 result[3] = (byte)(result_pos - 4);
12364                                 result[6] = (byte)(result_pos - 7);
12365                                 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12366                                 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12367                                     || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12368                                 {
12369                                         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12370                                         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12371                                 }
12372                                 else
12373                                         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12374                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12375                         }
12376                         mixer_calculate_coefs(a);
12377                         plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12378                         mixer_notify_update(plci, true);
12379                         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12380                               "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12381                         plci->command = 0;
12382                         plci->li_cmd = GET_WORD(li_parms[0].info);
12383                         start_internal_command(Id, plci, mixer_command);
12384                         return (false);
12385
12386                 case LI_REQ_SILENT_UPDATE:
12387                         if (!plci || !plci->State
12388                             || !plci->NL.Id || plci->nl_remove_id
12389                             || (plci->li_bchannel_id == 0)
12390                             || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12391                         {
12392                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12393                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12394                                 return (false);
12395                         }
12396                         plci_b_write_pos = plci->li_plci_b_write_pos;
12397                         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12398                              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12399                         {
12400                                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12401                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12402                                 return (false);
12403                         }
12404                         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12405                         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12406                             || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12407                         {
12408                                 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12409                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12410                         }
12411                         else
12412                                 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12413                         plci->li_plci_b_write_pos = plci_b_write_pos;
12414                         plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12415                         plci->command = 0;
12416                         plci->li_cmd = GET_WORD(li_parms[0].info);
12417                         start_internal_command(Id, plci, mixer_command);
12418                         return (false);
12419
12420                 default:
12421                         dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12422                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12423                         Info = _FACILITY_NOT_SUPPORTED;
12424                 }
12425         }
12426         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12427               "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12428         return (false);
12429 }
12430
12431
12432 static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12433 {
12434         dword d;
12435         byte result[12];
12436
12437         dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12438                         UnMapId(Id), (char *)(FILE_), __LINE__));
12439
12440         if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12441         {
12442                 do
12443                 {
12444                         d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12445                         if (!(d & LI_PLCI_B_SKIP_FLAG))
12446                         {
12447                                 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12448                                 {
12449                                         if (d & LI_PLCI_B_DISC_FLAG)
12450                                         {
12451                                                 result[0] = 5;
12452                                                 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12453                                                 result[3] = 2;
12454                                                 PUT_WORD(&result[4], _LI_USER_INITIATED);
12455                                         }
12456                                         else
12457                                         {
12458                                                 result[0] = 7;
12459                                                 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12460                                                 result[3] = 4;
12461                                                 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12462                                         }
12463                                 }
12464                                 else
12465                                 {
12466                                         if (d & LI_PLCI_B_DISC_FLAG)
12467                                         {
12468                                                 result[0] = 9;
12469                                                 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12470                                                 result[3] = 6;
12471                                                 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12472                                                 PUT_WORD(&result[8], _LI_USER_INITIATED);
12473                                         }
12474                                         else
12475                                         {
12476                                                 result[0] = 7;
12477                                                 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12478                                                 result[3] = 4;
12479                                                 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12480                                         }
12481                                 }
12482                                 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12483                                       "ws", SELECTOR_LINE_INTERCONNECT, result);
12484                         }
12485                         plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12486                                 0 : plci->li_plci_b_read_pos + 1;
12487                 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12488         }
12489 }
12490
12491
12492 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12493 {
12494         word i, j, ch;
12495         struct xconnect_transfer_address_s s,   *p;
12496         DIVA_CAPI_ADAPTER *a;
12497
12498         dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12499                         UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12500
12501         a = plci->adapter;
12502         i = 1;
12503         for (i = 1; i < length; i += 16)
12504         {
12505                 s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12506                 s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12507                 s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12508                 ch = msg[i + 12] | (msg[i + 13] << 8);
12509                 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12510                 if (!a->li_pri && (plci->li_bchannel_id == 2))
12511                         j = 1 - j;
12512                 j += a->li_base;
12513                 if (ch & XCONNECT_CHANNEL_PORT_PC)
12514                         p = &(li_config_table[j].send_pc);
12515                 else
12516                         p = &(li_config_table[j].send_b);
12517                 p->card_address.low = s.card_address.low;
12518                 p->card_address.high = s.card_address.high;
12519                 p->offset = s.offset;
12520                 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12521         }
12522         if (plci->internal_command_queue[0]
12523             && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12524                 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12525                 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12526         {
12527                 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12528                 if (!plci->internal_command)
12529                         next_internal_command(Id, plci);
12530         }
12531         mixer_notify_update(plci, true);
12532 }
12533
12534
12535 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12536 {
12537
12538         dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12539                         UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12540
12541 }
12542
12543
12544 static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12545 {
12546         word plci_b_write_pos;
12547
12548         plci_b_write_pos = plci->li_plci_b_write_pos;
12549         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12550              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12551         {
12552                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12553                                 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12554                                 (char *)(FILE_), __LINE__));
12555                 return (false);
12556         }
12557         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12558         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12559         plci->li_plci_b_write_pos = plci_b_write_pos;
12560         return (true);
12561 }
12562
12563
12564 static void mixer_remove(PLCI *plci)
12565 {
12566         DIVA_CAPI_ADAPTER *a;
12567         PLCI *notify_plci;
12568         dword plci_b_id;
12569         word i, j;
12570
12571         dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12572                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12573                         (char *)(FILE_), __LINE__));
12574
12575         a = plci->adapter;
12576         plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12577         if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12578         {
12579                 if ((plci->li_bchannel_id != 0)
12580                     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12581                 {
12582                         i = a->li_base + (plci->li_bchannel_id - 1);
12583                         if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12584                         {
12585                                 for (j = 0; j < li_total_channels; j++)
12586                                 {
12587                                         if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12588                                             || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12589                                         {
12590                                                 notify_plci = li_config_table[j].plci;
12591                                                 if ((notify_plci != NULL)
12592                                                     && (notify_plci != plci)
12593                                                     && (notify_plci->appl != NULL)
12594                                                     && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12595                                                     && (notify_plci->State)
12596                                                     && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12597                                                 {
12598                                                         mixer_notify_source_removed(notify_plci, plci_b_id);
12599                                                 }
12600                                         }
12601                                 }
12602                                 mixer_clear_config(plci);
12603                                 mixer_calculate_coefs(a);
12604                                 mixer_notify_update(plci, true);
12605                         }
12606                         li_config_table[i].plci = NULL;
12607                         plci->li_bchannel_id = 0;
12608                 }
12609         }
12610 }
12611
12612
12613 /*------------------------------------------------------------------*/
12614 /* Echo canceller facilities                                        */
12615 /*------------------------------------------------------------------*/
12616
12617
12618 static void ec_write_parameters(PLCI *plci)
12619 {
12620         word w;
12621         byte parameter_buffer[6];
12622
12623         dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12624                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12625                         (char *)(FILE_), __LINE__));
12626
12627         parameter_buffer[0] = 5;
12628         parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12629         PUT_WORD(&parameter_buffer[2], plci->ec_idi_options);
12630         plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12631         w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12632         PUT_WORD(&parameter_buffer[4], w);
12633         add_p(plci, FTY, parameter_buffer);
12634         sig_req(plci, TEL_CTRL, 0);
12635         send_req(plci);
12636 }
12637
12638
12639 static void ec_clear_config(PLCI *plci)
12640 {
12641
12642         dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12643                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12644                         (char *)(FILE_), __LINE__));
12645
12646         plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12647                 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12648         plci->ec_tail_length = 0;
12649 }
12650
12651
12652 static void ec_prepare_switch(dword Id, PLCI *plci)
12653 {
12654
12655         dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12656                         UnMapId(Id), (char *)(FILE_), __LINE__));
12657
12658 }
12659
12660
12661 static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12662 {
12663
12664         dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12665                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12666
12667         return (GOOD);
12668 }
12669
12670
12671 static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12672 {
12673         word Info;
12674
12675         dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12676                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12677
12678         Info = GOOD;
12679         if (plci->B1_facilities & B1_FACILITY_EC)
12680         {
12681                 switch (plci->adjust_b_state)
12682                 {
12683                 case ADJUST_B_RESTORE_EC_1:
12684                         plci->internal_command = plci->adjust_b_command;
12685                         if (plci->sig_req)
12686                         {
12687                                 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12688                                 break;
12689                         }
12690                         ec_write_parameters(plci);
12691                         plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12692                         break;
12693                 case ADJUST_B_RESTORE_EC_2:
12694                         if ((Rc != OK) && (Rc != OK_FC))
12695                         {
12696                                 dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12697                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12698                                 Info = _WRONG_STATE;
12699                                 break;
12700                         }
12701                         break;
12702                 }
12703         }
12704         return (Info);
12705 }
12706
12707
12708 static void ec_command(dword Id, PLCI *plci, byte Rc)
12709 {
12710         word internal_command, Info;
12711         byte result[8];
12712
12713         dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12714                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12715                         plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12716
12717         Info = GOOD;
12718         if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12719         {
12720                 result[0] = 2;
12721                 PUT_WORD(&result[1], EC_SUCCESS);
12722         }
12723         else
12724         {
12725                 result[0] = 5;
12726                 PUT_WORD(&result[1], plci->ec_cmd);
12727                 result[3] = 2;
12728                 PUT_WORD(&result[4], GOOD);
12729         }
12730         internal_command = plci->internal_command;
12731         plci->internal_command = 0;
12732         switch (plci->ec_cmd)
12733         {
12734         case EC_ENABLE_OPERATION:
12735         case EC_FREEZE_COEFFICIENTS:
12736         case EC_RESUME_COEFFICIENT_UPDATE:
12737         case EC_RESET_COEFFICIENTS:
12738                 switch (internal_command)
12739                 {
12740                 default:
12741                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12742                                                                   B1_FACILITY_EC), EC_COMMAND_1);
12743                 case EC_COMMAND_1:
12744                         if (adjust_b_process(Id, plci, Rc) != GOOD)
12745                         {
12746                                 dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12747                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12748                                 Info = _FACILITY_NOT_SUPPORTED;
12749                                 break;
12750                         }
12751                         if (plci->internal_command)
12752                                 return;
12753                 case EC_COMMAND_2:
12754                         if (plci->sig_req)
12755                         {
12756                                 plci->internal_command = EC_COMMAND_2;
12757                                 return;
12758                         }
12759                         plci->internal_command = EC_COMMAND_3;
12760                         ec_write_parameters(plci);
12761                         return;
12762                 case EC_COMMAND_3:
12763                         if ((Rc != OK) && (Rc != OK_FC))
12764                         {
12765                                 dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12766                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12767                                 Info = _FACILITY_NOT_SUPPORTED;
12768                                 break;
12769                         }
12770                         break;
12771                 }
12772                 break;
12773
12774         case EC_DISABLE_OPERATION:
12775                 switch (internal_command)
12776                 {
12777                 default:
12778                 case EC_COMMAND_1:
12779                         if (plci->B1_facilities & B1_FACILITY_EC)
12780                         {
12781                                 if (plci->sig_req)
12782                                 {
12783                                         plci->internal_command = EC_COMMAND_1;
12784                                         return;
12785                                 }
12786                                 plci->internal_command = EC_COMMAND_2;
12787                                 ec_write_parameters(plci);
12788                                 return;
12789                         }
12790                         Rc = OK;
12791                 case EC_COMMAND_2:
12792                         if ((Rc != OK) && (Rc != OK_FC))
12793                         {
12794                                 dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12795                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12796                                 Info = _FACILITY_NOT_SUPPORTED;
12797                                 break;
12798                         }
12799                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12800                                                                   ~B1_FACILITY_EC), EC_COMMAND_3);
12801                 case EC_COMMAND_3:
12802                         if (adjust_b_process(Id, plci, Rc) != GOOD)
12803                         {
12804                                 dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12805                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12806                                 Info = _FACILITY_NOT_SUPPORTED;
12807                                 break;
12808                         }
12809                         if (plci->internal_command)
12810                                 return;
12811                         break;
12812                 }
12813                 break;
12814         }
12815         sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12816               "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12817               PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12818 }
12819
12820
12821 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
12822 {
12823         word Info;
12824         word opt;
12825         API_PARSE ec_parms[3];
12826         byte result[16];
12827
12828         dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12829                         UnMapId(Id), (char *)(FILE_), __LINE__));
12830
12831         Info = GOOD;
12832         result[0] = 0;
12833         if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12834         {
12835                 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12836                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12837                 Info = _FACILITY_NOT_SUPPORTED;
12838         }
12839         else
12840         {
12841                 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12842                 {
12843                         if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12844                         {
12845                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12846                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12847                                 Info = _WRONG_MESSAGE_FORMAT;
12848                         }
12849                         else
12850                         {
12851                                 if (plci == NULL)
12852                                 {
12853                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12854                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12855                                         Info = _WRONG_IDENTIFIER;
12856                                 }
12857                                 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12858                                 {
12859                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12860                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12861                                         Info = _WRONG_STATE;
12862                                 }
12863                                 else
12864                                 {
12865                                         plci->command = 0;
12866                                         plci->ec_cmd = GET_WORD(ec_parms[0].info);
12867                                         plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12868                                         result[0] = 2;
12869                                         PUT_WORD(&result[1], EC_SUCCESS);
12870                                         if (msg[1].length >= 4)
12871                                         {
12872                                                 opt = GET_WORD(&ec_parms[0].info[2]);
12873                                                 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12874                                                                           LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12875                                                 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12876                                                         plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12877                                                 if (opt & EC_DETECT_DISABLE_TONE)
12878                                                         plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12879                                                 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12880                                                         plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12881                                                 if (msg[1].length >= 6)
12882                                                 {
12883                                                         plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12884                                                 }
12885                                         }
12886                                         switch (plci->ec_cmd)
12887                                         {
12888                                         case EC_ENABLE_OPERATION:
12889                                                 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12890                                                 start_internal_command(Id, plci, ec_command);
12891                                                 return (false);
12892
12893                                         case EC_DISABLE_OPERATION:
12894                                                 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12895                                                         LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12896                                                         LEC_RESET_COEFFICIENTS;
12897                                                 start_internal_command(Id, plci, ec_command);
12898                                                 return (false);
12899
12900                                         case EC_FREEZE_COEFFICIENTS:
12901                                                 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12902                                                 start_internal_command(Id, plci, ec_command);
12903                                                 return (false);
12904
12905                                         case EC_RESUME_COEFFICIENT_UPDATE:
12906                                                 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12907                                                 start_internal_command(Id, plci, ec_command);
12908                                                 return (false);
12909
12910                                         case EC_RESET_COEFFICIENTS:
12911                                                 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12912                                                 start_internal_command(Id, plci, ec_command);
12913                                                 return (false);
12914
12915                                         default:
12916                                                 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12917                                                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12918                                                 PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12919                                         }
12920                                 }
12921                         }
12922                 }
12923                 else
12924                 {
12925                         if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12926                         {
12927                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12928                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12929                                 Info = _WRONG_MESSAGE_FORMAT;
12930                         }
12931                         else
12932                         {
12933                                 if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12934                                 {
12935                                         result[0] = 11;
12936                                         PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12937                                         result[3] = 8;
12938                                         PUT_WORD(&result[4], GOOD);
12939                                         PUT_WORD(&result[6], 0x0007);
12940                                         PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12941                                         PUT_WORD(&result[10], 0);
12942                                 }
12943                                 else if (plci == NULL)
12944                                 {
12945                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12946                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12947                                         Info = _WRONG_IDENTIFIER;
12948                                 }
12949                                 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12950                                 {
12951                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12952                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12953                                         Info = _WRONG_STATE;
12954                                 }
12955                                 else
12956                                 {
12957                                         plci->command = 0;
12958                                         plci->ec_cmd = GET_WORD(ec_parms[0].info);
12959                                         plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12960                                         result[0] = 5;
12961                                         PUT_WORD(&result[1], plci->ec_cmd);
12962                                         result[3] = 2;
12963                                         PUT_WORD(&result[4], GOOD);
12964                                         plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12965                                                                   LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12966                                         plci->ec_tail_length = 0;
12967                                         if (ec_parms[1].length >= 2)
12968                                         {
12969                                                 opt = GET_WORD(&ec_parms[1].info[1]);
12970                                                 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12971                                                         plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12972                                                 if (opt & EC_DETECT_DISABLE_TONE)
12973                                                         plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12974                                                 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12975                                                         plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12976                                                 if (ec_parms[1].length >= 4)
12977                                                 {
12978                                                         plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12979                                                 }
12980                                         }
12981                                         switch (plci->ec_cmd)
12982                                         {
12983                                         case EC_ENABLE_OPERATION:
12984                                                 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12985                                                 start_internal_command(Id, plci, ec_command);
12986                                                 return (false);
12987
12988                                         case EC_DISABLE_OPERATION:
12989                                                 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12990                                                         LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12991                                                         LEC_RESET_COEFFICIENTS;
12992                                                 start_internal_command(Id, plci, ec_command);
12993                                                 return (false);
12994
12995                                         default:
12996                                                 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12997                                                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12998                                                 PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12999                                         }
13000                                 }
13001                         }
13002                 }
13003         }
13004         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13005               "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13006               PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13007         return (false);
13008 }
13009
13010
13011 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
13012 {
13013         byte result[8];
13014
13015         dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
13016                         UnMapId(Id), (char *)(FILE_), __LINE__));
13017
13018         if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13019         {
13020                 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13021                 {
13022                         result[0] = 2;
13023                         PUT_WORD(&result[1], 0);
13024                         switch (msg[1])
13025                         {
13026                         case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13027                                 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13028                                 break;
13029                         case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13030                                 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13031                                 break;
13032                         case LEC_DISABLE_RELEASED:
13033                                 PUT_WORD(&result[1], EC_BYPASS_RELEASED);
13034                                 break;
13035                         }
13036                 }
13037                 else
13038                 {
13039                         result[0] = 5;
13040                         PUT_WORD(&result[1], EC_BYPASS_INDICATION);
13041                         result[3] = 2;
13042                         PUT_WORD(&result[4], 0);
13043                         switch (msg[1])
13044                         {
13045                         case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13046                                 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13047                                 break;
13048                         case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13049                                 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13050                                 break;
13051                         case LEC_DISABLE_RELEASED:
13052                                 PUT_WORD(&result[4], EC_BYPASS_RELEASED);
13053                                 break;
13054                         }
13055                 }
13056                 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13057                       PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13058         }
13059 }
13060
13061
13062
13063 /*------------------------------------------------------------------*/
13064 /* Advanced voice                                                   */
13065 /*------------------------------------------------------------------*/
13066
13067 static void adv_voice_write_coefs(PLCI *plci, word write_command)
13068 {
13069         DIVA_CAPI_ADAPTER *a;
13070         word i;
13071         byte *p;
13072
13073         word w, n, j, k;
13074         byte ch_map[MIXER_CHANNELS_BRI];
13075
13076         byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13077
13078         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
13079                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13080                         (char *)(FILE_), __LINE__, write_command));
13081
13082         a = plci->adapter;
13083         p = coef_buffer + 1;
13084         *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13085         i = 0;
13086         while (i + sizeof(word) <= a->adv_voice_coef_length)
13087         {
13088                 PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
13089                 p += 2;
13090                 i += 2;
13091         }
13092         while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13093         {
13094                 PUT_WORD(p, 0x8000);
13095                 p += 2;
13096                 i += 2;
13097         }
13098
13099         if (!a->li_pri && (plci->li_bchannel_id == 0))
13100         {
13101                 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13102                 {
13103                         plci->li_bchannel_id = 1;
13104                         li_config_table[a->li_base].plci = plci;
13105                         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13106                                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13107                                         (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13108                 }
13109                 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13110                 {
13111                         plci->li_bchannel_id = 2;
13112                         li_config_table[a->li_base + 1].plci = plci;
13113                         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13114                                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13115                                         (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13116                 }
13117         }
13118         if (!a->li_pri && (plci->li_bchannel_id != 0)
13119             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13120         {
13121                 i = a->li_base + (plci->li_bchannel_id - 1);
13122                 switch (write_command)
13123                 {
13124                 case ADV_VOICE_WRITE_ACTIVATION:
13125                         j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13126                         k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13127                         if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13128                         {
13129                                 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13130                                 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13131                         }
13132                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13133                         {
13134                                 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13135                                 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13136                                 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13137                                 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13138                         }
13139                         mixer_calculate_coefs(a);
13140                         li_config_table[i].curchnl = li_config_table[i].channel;
13141                         li_config_table[j].curchnl = li_config_table[j].channel;
13142                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13143                                 li_config_table[k].curchnl = li_config_table[k].channel;
13144                         break;
13145
13146                 case ADV_VOICE_WRITE_DEACTIVATION:
13147                         for (j = 0; j < li_total_channels; j++)
13148                         {
13149                                 li_config_table[i].flag_table[j] = 0;
13150                                 li_config_table[j].flag_table[i] = 0;
13151                         }
13152                         k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13153                         for (j = 0; j < li_total_channels; j++)
13154                         {
13155                                 li_config_table[k].flag_table[j] = 0;
13156                                 li_config_table[j].flag_table[k] = 0;
13157                         }
13158                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13159                         {
13160                                 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13161                                 for (j = 0; j < li_total_channels; j++)
13162                                 {
13163                                         li_config_table[k].flag_table[j] = 0;
13164                                         li_config_table[j].flag_table[k] = 0;
13165                                 }
13166                         }
13167                         mixer_calculate_coefs(a);
13168                         break;
13169                 }
13170                 if (plci->B1_facilities & B1_FACILITY_MIXER)
13171                 {
13172                         w = 0;
13173                         if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13174                                 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13175                         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13176                                 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13177                         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13178                                 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13179                         *(p++) = (byte) w;
13180                         *(p++) = (byte)(w >> 8);
13181                         for (j = 0; j < sizeof(ch_map); j += 2)
13182                         {
13183                                 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13184                                 ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13185                         }
13186                         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13187                         {
13188                                 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13189                                 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13190                                 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13191                                 {
13192                                         *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13193                                         w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13194                                         li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13195                                 }
13196                                 else
13197                                 {
13198                                         *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13199                                                 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13200                                 }
13201                         }
13202                 }
13203                 else
13204                 {
13205                         for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13206                                 *(p++) = a->adv_voice_coef_buffer[i];
13207                 }
13208         }
13209         else
13210
13211         {
13212                 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13213                         *(p++) = a->adv_voice_coef_buffer[i];
13214         }
13215         coef_buffer[0] = (p - coef_buffer) - 1;
13216         add_p(plci, FTY, coef_buffer);
13217         sig_req(plci, TEL_CTRL, 0);
13218         send_req(plci);
13219 }
13220
13221
13222 static void adv_voice_clear_config(PLCI *plci)
13223 {
13224         DIVA_CAPI_ADAPTER *a;
13225
13226         word i, j;
13227
13228
13229         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13230                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13231                         (char *)(FILE_), __LINE__));
13232
13233         a = plci->adapter;
13234         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13235         {
13236                 a->adv_voice_coef_length = 0;
13237
13238                 if (!a->li_pri && (plci->li_bchannel_id != 0)
13239                     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13240                 {
13241                         i = a->li_base + (plci->li_bchannel_id - 1);
13242                         li_config_table[i].curchnl = 0;
13243                         li_config_table[i].channel = 0;
13244                         li_config_table[i].chflags = 0;
13245                         for (j = 0; j < li_total_channels; j++)
13246                         {
13247                                 li_config_table[i].flag_table[j] = 0;
13248                                 li_config_table[j].flag_table[i] = 0;
13249                                 li_config_table[i].coef_table[j] = 0;
13250                                 li_config_table[j].coef_table[i] = 0;
13251                         }
13252                         li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13253                         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13254                         li_config_table[i].curchnl = 0;
13255                         li_config_table[i].channel = 0;
13256                         li_config_table[i].chflags = 0;
13257                         for (j = 0; j < li_total_channels; j++)
13258                         {
13259                                 li_config_table[i].flag_table[j] = 0;
13260                                 li_config_table[j].flag_table[i] = 0;
13261                                 li_config_table[i].coef_table[j] = 0;
13262                                 li_config_table[j].coef_table[i] = 0;
13263                         }
13264                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13265                         {
13266                                 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13267                                 li_config_table[i].curchnl = 0;
13268                                 li_config_table[i].channel = 0;
13269                                 li_config_table[i].chflags = 0;
13270                                 for (j = 0; j < li_total_channels; j++)
13271                                 {
13272                                         li_config_table[i].flag_table[j] = 0;
13273                                         li_config_table[j].flag_table[i] = 0;
13274                                         li_config_table[i].coef_table[j] = 0;
13275                                         li_config_table[j].coef_table[i] = 0;
13276                                 }
13277                         }
13278                 }
13279
13280         }
13281 }
13282
13283
13284 static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13285 {
13286
13287         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13288                         UnMapId(Id), (char *)(FILE_), __LINE__));
13289
13290 }
13291
13292
13293 static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13294 {
13295
13296         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13297                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13298
13299         return (GOOD);
13300 }
13301
13302
13303 static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13304 {
13305         DIVA_CAPI_ADAPTER *a;
13306         word Info;
13307
13308         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13309                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13310
13311         Info = GOOD;
13312         a = plci->adapter;
13313         if ((plci->B1_facilities & B1_FACILITY_VOICE)
13314             && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13315         {
13316                 switch (plci->adjust_b_state)
13317                 {
13318                 case ADJUST_B_RESTORE_VOICE_1:
13319                         plci->internal_command = plci->adjust_b_command;
13320                         if (plci->sig_req)
13321                         {
13322                                 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13323                                 break;
13324                         }
13325                         adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13326                         plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13327                         break;
13328                 case ADJUST_B_RESTORE_VOICE_2:
13329                         if ((Rc != OK) && (Rc != OK_FC))
13330                         {
13331                                 dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13332                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13333                                 Info = _WRONG_STATE;
13334                                 break;
13335                         }
13336                         break;
13337                 }
13338         }
13339         return (Info);
13340 }
13341
13342
13343
13344
13345 /*------------------------------------------------------------------*/
13346 /* B1 resource switching                                            */
13347 /*------------------------------------------------------------------*/
13348
13349 static byte b1_facilities_table[] =
13350 {
13351         0x00,  /* 0  No bchannel resources      */
13352         0x00,  /* 1  Codec (automatic law)      */
13353         0x00,  /* 2  Codec (A-law)              */
13354         0x00,  /* 3  Codec (y-law)              */
13355         0x00,  /* 4  HDLC for X.21              */
13356         0x00,  /* 5  HDLC                       */
13357         0x00,  /* 6  External Device 0          */
13358         0x00,  /* 7  External Device 1          */
13359         0x00,  /* 8  HDLC 56k                   */
13360         0x00,  /* 9  Transparent                */
13361         0x00,  /* 10 Loopback to network        */
13362         0x00,  /* 11 Test pattern to net        */
13363         0x00,  /* 12 Rate adaptation sync       */
13364         0x00,  /* 13 Rate adaptation async      */
13365         0x00,  /* 14 R-Interface                */
13366         0x00,  /* 15 HDLC 128k leased line      */
13367         0x00,  /* 16 FAX                        */
13368         0x00,  /* 17 Modem async                */
13369         0x00,  /* 18 Modem sync HDLC            */
13370         0x00,  /* 19 V.110 async HDLC           */
13371         0x12,  /* 20 Adv voice (Trans,mixer)    */
13372         0x00,  /* 21 Codec connected to IC      */
13373         0x0c,  /* 22 Trans,DTMF                 */
13374         0x1e,  /* 23 Trans,DTMF+mixer           */
13375         0x1f,  /* 24 Trans,DTMF+mixer+local     */
13376         0x13,  /* 25 Trans,mixer+local          */
13377         0x12,  /* 26 HDLC,mixer                 */
13378         0x12,  /* 27 HDLC 56k,mixer             */
13379         0x2c,  /* 28 Trans,LEC+DTMF             */
13380         0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13381         0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13382         0x2c,  /* 31 RTP,LEC+DTMF               */
13383         0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13384         0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13385         0x00,  /* 34 Signaling task             */
13386         0x00,  /* 35 PIAFS                      */
13387         0x0c,  /* 36 Trans,DTMF+TONE            */
13388         0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13389         0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13390 };
13391
13392
13393 static word get_b1_facilities(PLCI *plci, byte b1_resource)
13394 {
13395         word b1_facilities;
13396
13397         b1_facilities = b1_facilities_table[b1_resource];
13398         if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13399         {
13400
13401                 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13402                       || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13403
13404                 {
13405                         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13406                                 b1_facilities |= B1_FACILITY_DTMFX;
13407                         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13408                                 b1_facilities |= B1_FACILITY_DTMFR;
13409                 }
13410         }
13411         if ((b1_resource == 17) || (b1_resource == 18))
13412         {
13413                 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13414                         b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13415         }
13416 /*
13417   dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13418   (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13419   (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13420 */
13421         return (b1_facilities);
13422 }
13423
13424
13425 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13426 {
13427         byte b;
13428
13429         switch (b1_resource)
13430         {
13431         case 5:
13432         case 26:
13433                 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13434                         b = 26;
13435                 else
13436                         b = 5;
13437                 break;
13438
13439         case 8:
13440         case 27:
13441                 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13442                         b = 27;
13443                 else
13444                         b = 8;
13445                 break;
13446
13447         case 9:
13448         case 20:
13449         case 22:
13450         case 23:
13451         case 24:
13452         case 25:
13453         case 28:
13454         case 29:
13455         case 30:
13456         case 36:
13457         case 37:
13458         case 38:
13459                 if (b1_facilities & B1_FACILITY_EC)
13460                 {
13461                         if (b1_facilities & B1_FACILITY_LOCAL)
13462                                 b = 30;
13463                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13464                                 b = 29;
13465                         else
13466                                 b = 28;
13467                 }
13468
13469                 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13470                          && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13471                              || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13472                 {
13473                         if (b1_facilities & B1_FACILITY_LOCAL)
13474                                 b = 38;
13475                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13476                                 b = 37;
13477                         else
13478                                 b = 36;
13479                 }
13480
13481                 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13482                           && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13483                          || ((b1_facilities & B1_FACILITY_DTMFR)
13484                              && ((b1_facilities & B1_FACILITY_MIXER)
13485                                  || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13486                          || ((b1_facilities & B1_FACILITY_DTMFX)
13487                              && ((b1_facilities & B1_FACILITY_MIXER)
13488                                  || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13489                 {
13490                         if (b1_facilities & B1_FACILITY_LOCAL)
13491                                 b = 24;
13492                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13493                                 b = 23;
13494                         else
13495                                 b = 22;
13496                 }
13497                 else
13498                 {
13499                         if (b1_facilities & B1_FACILITY_LOCAL)
13500                                 b = 25;
13501                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13502                                 b = 20;
13503                         else
13504                                 b = 9;
13505                 }
13506                 break;
13507
13508         case 31:
13509         case 32:
13510         case 33:
13511                 if (b1_facilities & B1_FACILITY_LOCAL)
13512                         b = 33;
13513                 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13514                         b = 32;
13515                 else
13516                         b = 31;
13517                 break;
13518
13519         default:
13520                 b = b1_resource;
13521         }
13522         dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13523                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13524                         (char *)(FILE_), __LINE__,
13525                         b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13526         return (b);
13527 }
13528
13529
13530 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13531 {
13532         word removed_facilities;
13533
13534         dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13535                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13536                         (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13537                         new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13538
13539         new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13540         removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13541
13542         if (removed_facilities & B1_FACILITY_EC)
13543                 ec_clear_config(plci);
13544
13545
13546         if (removed_facilities & B1_FACILITY_DTMFR)
13547         {
13548                 dtmf_rec_clear_config(plci);
13549                 dtmf_parameter_clear_config(plci);
13550         }
13551         if (removed_facilities & B1_FACILITY_DTMFX)
13552                 dtmf_send_clear_config(plci);
13553
13554
13555         if (removed_facilities & B1_FACILITY_MIXER)
13556                 mixer_clear_config(plci);
13557
13558         if (removed_facilities & B1_FACILITY_VOICE)
13559                 adv_voice_clear_config(plci);
13560         plci->B1_facilities = new_b1_facilities;
13561 }
13562
13563
13564 static void adjust_b_clear(PLCI *plci)
13565 {
13566
13567         dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13568                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13569                         (char *)(FILE_), __LINE__));
13570
13571         plci->adjust_b_restore = false;
13572 }
13573
13574
13575 static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13576 {
13577         word Info;
13578         byte b1_resource;
13579         NCCI *ncci_ptr;
13580         API_PARSE bp[2];
13581
13582         dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13583                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13584
13585         Info = GOOD;
13586         switch (plci->adjust_b_state)
13587         {
13588         case ADJUST_B_START:
13589                 if ((plci->adjust_b_parms_msg == NULL)
13590                     && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13591                     && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13592                                                  ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13593                 {
13594                         b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13595                                 0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13596                         if (b1_resource == plci->B1_resource)
13597                         {
13598                                 adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13599                                 break;
13600                         }
13601                         if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13602                         {
13603                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13604                                                 UnMapId(Id), (char *)(FILE_), __LINE__,
13605                                                 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13606                                 Info = _WRONG_STATE;
13607                                 break;
13608                         }
13609                 }
13610                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13611                 {
13612
13613                         mixer_prepare_switch(Id, plci);
13614
13615
13616                         dtmf_prepare_switch(Id, plci);
13617                         dtmf_parameter_prepare_switch(Id, plci);
13618
13619
13620                         ec_prepare_switch(Id, plci);
13621
13622                         adv_voice_prepare_switch(Id, plci);
13623                 }
13624                 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13625                 Rc = OK;
13626         case ADJUST_B_SAVE_MIXER_1:
13627                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13628                 {
13629
13630                         Info = mixer_save_config(Id, plci, Rc);
13631                         if ((Info != GOOD) || plci->internal_command)
13632                                 break;
13633
13634                 }
13635                 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13636                 Rc = OK;
13637         case ADJUST_B_SAVE_DTMF_1:
13638                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13639                 {
13640
13641                         Info = dtmf_save_config(Id, plci, Rc);
13642                         if ((Info != GOOD) || plci->internal_command)
13643                                 break;
13644
13645                 }
13646                 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13647         case ADJUST_B_REMOVE_L23_1:
13648                 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13649                     && plci->NL.Id && !plci->nl_remove_id)
13650                 {
13651                         plci->internal_command = plci->adjust_b_command;
13652                         if (plci->adjust_b_ncci != 0)
13653                         {
13654                                 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13655                                 while (ncci_ptr->data_pending)
13656                                 {
13657                                         plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13658                                         data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13659                                 }
13660                                 while (ncci_ptr->data_ack_pending)
13661                                         data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13662                         }
13663                         nl_req_ncci(plci, REMOVE,
13664                                     (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13665                         send_req(plci);
13666                         plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13667                         break;
13668                 }
13669                 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13670                 Rc = OK;
13671         case ADJUST_B_REMOVE_L23_2:
13672                 if ((Rc != OK) && (Rc != OK_FC))
13673                 {
13674                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13675                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13676                         Info = _WRONG_STATE;
13677                         break;
13678                 }
13679                 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13680                 {
13681                         if (plci_nl_busy(plci))
13682                         {
13683                                 plci->internal_command = plci->adjust_b_command;
13684                                 break;
13685                         }
13686                 }
13687                 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13688                 Rc = OK;
13689         case ADJUST_B_SAVE_EC_1:
13690                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13691                 {
13692
13693                         Info = ec_save_config(Id, plci, Rc);
13694                         if ((Info != GOOD) || plci->internal_command)
13695                                 break;
13696
13697                 }
13698                 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13699                 Rc = OK;
13700         case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13701                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13702                 {
13703
13704                         Info = dtmf_parameter_save_config(Id, plci, Rc);
13705                         if ((Info != GOOD) || plci->internal_command)
13706                                 break;
13707
13708                 }
13709                 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13710                 Rc = OK;
13711         case ADJUST_B_SAVE_VOICE_1:
13712                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13713                 {
13714                         Info = adv_voice_save_config(Id, plci, Rc);
13715                         if ((Info != GOOD) || plci->internal_command)
13716                                 break;
13717                 }
13718                 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13719         case ADJUST_B_SWITCH_L1_1:
13720                 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13721                 {
13722                         if (plci->sig_req)
13723                         {
13724                                 plci->internal_command = plci->adjust_b_command;
13725                                 break;
13726                         }
13727                         if (plci->adjust_b_parms_msg != NULL)
13728                                 api_load_msg(plci->adjust_b_parms_msg, bp);
13729                         else
13730                                 api_load_msg(&plci->B_protocol, bp);
13731                         Info = add_b1(plci, bp,
13732                                       (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13733                                       plci->adjust_b_facilities);
13734                         if (Info != GOOD)
13735                         {
13736                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13737                                                 UnMapId(Id), (char *)(FILE_), __LINE__,
13738                                                 plci->B1_resource, plci->adjust_b_facilities));
13739                                 break;
13740                         }
13741                         plci->internal_command = plci->adjust_b_command;
13742                         sig_req(plci, RESOURCES, 0);
13743                         send_req(plci);
13744                         plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13745                         break;
13746                 }
13747                 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13748                 Rc = OK;
13749         case ADJUST_B_SWITCH_L1_2:
13750                 if ((Rc != OK) && (Rc != OK_FC))
13751                 {
13752                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13753                                         UnMapId(Id), (char *)(FILE_), __LINE__,
13754                                         Rc, plci->B1_resource, plci->adjust_b_facilities));
13755                         Info = _WRONG_STATE;
13756                         break;
13757                 }
13758                 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13759                 Rc = OK;
13760         case ADJUST_B_RESTORE_VOICE_1:
13761         case ADJUST_B_RESTORE_VOICE_2:
13762                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13763                 {
13764                         Info = adv_voice_restore_config(Id, plci, Rc);
13765                         if ((Info != GOOD) || plci->internal_command)
13766                                 break;
13767                 }
13768                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13769                 Rc = OK;
13770         case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13771         case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13772                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13773                 {
13774
13775                         Info = dtmf_parameter_restore_config(Id, plci, Rc);
13776                         if ((Info != GOOD) || plci->internal_command)
13777                                 break;
13778
13779                 }
13780                 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13781                 Rc = OK;
13782         case ADJUST_B_RESTORE_EC_1:
13783         case ADJUST_B_RESTORE_EC_2:
13784                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13785                 {
13786
13787                         Info = ec_restore_config(Id, plci, Rc);
13788                         if ((Info != GOOD) || plci->internal_command)
13789                                 break;
13790
13791                 }
13792                 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13793         case ADJUST_B_ASSIGN_L23_1:
13794                 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13795                 {
13796                         if (plci_nl_busy(plci))
13797                         {
13798                                 plci->internal_command = plci->adjust_b_command;
13799                                 break;
13800                         }
13801                         if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13802                                 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13803                         if (plci->adjust_b_parms_msg != NULL)
13804                                 api_load_msg(plci->adjust_b_parms_msg, bp);
13805                         else
13806                                 api_load_msg(&plci->B_protocol, bp);
13807                         Info = add_b23(plci, bp);
13808                         if (Info != GOOD)
13809                         {
13810                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13811                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13812                                 break;
13813                         }
13814                         plci->internal_command = plci->adjust_b_command;
13815                         nl_req_ncci(plci, ASSIGN, 0);
13816                         send_req(plci);
13817                         plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13818                         break;
13819                 }
13820                 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13821                 Rc = ASSIGN_OK;
13822         case ADJUST_B_ASSIGN_L23_2:
13823                 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13824                 {
13825                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13826                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13827                         Info = _WRONG_STATE;
13828                         break;
13829                 }
13830                 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13831                 {
13832                         if (Rc != ASSIGN_OK)
13833                         {
13834                                 plci->internal_command = plci->adjust_b_command;
13835                                 break;
13836                         }
13837                 }
13838                 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13839                 {
13840                         plci->adjust_b_restore = true;
13841                         break;
13842                 }
13843                 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13844         case ADJUST_B_CONNECT_1:
13845                 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13846                 {
13847                         plci->internal_command = plci->adjust_b_command;
13848                         if (plci_nl_busy(plci))
13849                                 break;
13850                         nl_req_ncci(plci, N_CONNECT, 0);
13851                         send_req(plci);
13852                         plci->adjust_b_state = ADJUST_B_CONNECT_2;
13853                         break;
13854                 }
13855                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13856                 Rc = OK;
13857         case ADJUST_B_CONNECT_2:
13858         case ADJUST_B_CONNECT_3:
13859         case ADJUST_B_CONNECT_4:
13860                 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13861                 {
13862                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13863                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13864                         Info = _WRONG_STATE;
13865                         break;
13866                 }
13867                 if (Rc == OK)
13868                 {
13869                         if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13870                         {
13871                                 get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13872                                 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13873                         }
13874                         if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13875                                 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13876                         else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13877                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13878                 }
13879                 else if (Rc == 0)
13880                 {
13881                         if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13882                                 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13883                         else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13884                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13885                 }
13886                 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13887                 {
13888                         plci->internal_command = plci->adjust_b_command;
13889                         break;
13890                 }
13891                 Rc = OK;
13892         case ADJUST_B_RESTORE_DTMF_1:
13893         case ADJUST_B_RESTORE_DTMF_2:
13894                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13895                 {
13896
13897                         Info = dtmf_restore_config(Id, plci, Rc);
13898                         if ((Info != GOOD) || plci->internal_command)
13899                                 break;
13900
13901                 }
13902                 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13903                 Rc = OK;
13904         case ADJUST_B_RESTORE_MIXER_1:
13905         case ADJUST_B_RESTORE_MIXER_2:
13906         case ADJUST_B_RESTORE_MIXER_3:
13907         case ADJUST_B_RESTORE_MIXER_4:
13908         case ADJUST_B_RESTORE_MIXER_5:
13909         case ADJUST_B_RESTORE_MIXER_6:
13910         case ADJUST_B_RESTORE_MIXER_7:
13911                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13912                 {
13913
13914                         Info = mixer_restore_config(Id, plci, Rc);
13915                         if ((Info != GOOD) || plci->internal_command)
13916                                 break;
13917
13918                 }
13919                 plci->adjust_b_state = ADJUST_B_END;
13920         case ADJUST_B_END:
13921                 break;
13922         }
13923         return (Info);
13924 }
13925
13926
13927 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13928 {
13929
13930         dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13931                         UnMapId(Id), (char *)(FILE_), __LINE__,
13932                         plci->B1_resource, b1_facilities));
13933
13934         plci->adjust_b_parms_msg = bp_msg;
13935         plci->adjust_b_facilities = b1_facilities;
13936         plci->adjust_b_command = internal_command;
13937         plci->adjust_b_ncci = (word)(Id >> 16);
13938         if ((bp_msg == NULL) && (plci->B1_resource == 0))
13939                 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13940         else
13941                 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13942         plci->adjust_b_state = ADJUST_B_START;
13943         dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13944                         UnMapId(Id), (char *)(FILE_), __LINE__,
13945                         plci->B1_resource, b1_facilities));
13946 }
13947
13948
13949 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13950 {
13951         word internal_command;
13952
13953         dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13954                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13955
13956         internal_command = plci->internal_command;
13957         plci->internal_command = 0;
13958         switch (internal_command)
13959         {
13960         default:
13961                 plci->command = 0;
13962                 if (plci->req_in != 0)
13963                 {
13964                         plci->internal_command = ADJUST_B_RESTORE_1;
13965                         break;
13966                 }
13967                 Rc = OK;
13968         case ADJUST_B_RESTORE_1:
13969                 if ((Rc != OK) && (Rc != OK_FC))
13970                 {
13971                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13972                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13973                 }
13974                 plci->adjust_b_parms_msg = NULL;
13975                 plci->adjust_b_facilities = plci->B1_facilities;
13976                 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13977                 plci->adjust_b_ncci = (word)(Id >> 16);
13978                 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13979                 plci->adjust_b_state = ADJUST_B_START;
13980                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13981                                 UnMapId(Id), (char *)(FILE_), __LINE__));
13982         case ADJUST_B_RESTORE_2:
13983                 if (adjust_b_process(Id, plci, Rc) != GOOD)
13984                 {
13985                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13986                                         UnMapId(Id), (char *)(FILE_), __LINE__));
13987                 }
13988                 if (plci->internal_command)
13989                         break;
13990                 break;
13991         }
13992 }
13993
13994
13995 static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
13996 {
13997         word Info;
13998         word internal_command;
13999
14000         dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
14001                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14002
14003         Info = GOOD;
14004         internal_command = plci->internal_command;
14005         plci->internal_command = 0;
14006         switch (internal_command)
14007         {
14008         default:
14009                 plci->command = 0;
14010                 plci->adjust_b_parms_msg = NULL;
14011                 plci->adjust_b_facilities = plci->B1_facilities;
14012                 plci->adjust_b_command = RESET_B3_COMMAND_1;
14013                 plci->adjust_b_ncci = (word)(Id >> 16);
14014                 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14015                 plci->adjust_b_state = ADJUST_B_START;
14016                 dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
14017                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14018         case RESET_B3_COMMAND_1:
14019                 Info = adjust_b_process(Id, plci, Rc);
14020                 if (Info != GOOD)
14021                 {
14022                         dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
14023                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14024                         break;
14025                 }
14026                 if (plci->internal_command)
14027                         return;
14028                 break;
14029         }
14030 /*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14031         sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
14032 }
14033
14034
14035 static void select_b_command(dword Id, PLCI *plci, byte Rc)
14036 {
14037         word Info;
14038         word internal_command;
14039         byte esc_chi[3];
14040
14041         dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
14042                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14043
14044         Info = GOOD;
14045         internal_command = plci->internal_command;
14046         plci->internal_command = 0;
14047         switch (internal_command)
14048         {
14049         default:
14050                 plci->command = 0;
14051                 plci->adjust_b_parms_msg = &plci->saved_msg;
14052                 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14053                         plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14054                 else
14055                         plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14056                 plci->adjust_b_command = SELECT_B_COMMAND_1;
14057                 plci->adjust_b_ncci = (word)(Id >> 16);
14058                 if (plci->saved_msg.parms[0].length == 0)
14059                 {
14060                         plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14061                                 ADJUST_B_MODE_NO_RESOURCE;
14062                 }
14063                 else
14064                 {
14065                         plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14066                                 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14067                 }
14068                 plci->adjust_b_state = ADJUST_B_START;
14069                 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
14070                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14071         case SELECT_B_COMMAND_1:
14072                 Info = adjust_b_process(Id, plci, Rc);
14073                 if (Info != GOOD)
14074                 {
14075                         dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
14076                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14077                         break;
14078                 }
14079                 if (plci->internal_command)
14080                         return;
14081                 if (plci->tel == ADV_VOICE)
14082                 {
14083                         esc_chi[0] = 0x02;
14084                         esc_chi[1] = 0x18;
14085                         esc_chi[2] = plci->b_channel;
14086                         SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14087                 }
14088                 break;
14089         }
14090         sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14091 }
14092
14093
14094 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
14095 {
14096         word internal_command;
14097
14098         dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14099                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14100
14101         internal_command = plci->internal_command;
14102         plci->internal_command = 0;
14103         switch (internal_command)
14104         {
14105         default:
14106                 plci->command = 0;
14107         case FAX_CONNECT_ACK_COMMAND_1:
14108                 if (plci_nl_busy(plci))
14109                 {
14110                         plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14111                         return;
14112                 }
14113                 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14114                 plci->NData[0].P = plci->fax_connect_info_buffer;
14115                 plci->NData[0].PLength = plci->fax_connect_info_length;
14116                 plci->NL.X = plci->NData;
14117                 plci->NL.ReqCh = 0;
14118                 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14119                 plci->adapter->request(&plci->NL);
14120                 return;
14121         case FAX_CONNECT_ACK_COMMAND_2:
14122                 if ((Rc != OK) && (Rc != OK_FC))
14123                 {
14124                         dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14125                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14126                         break;
14127                 }
14128         }
14129         if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14130             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14131         {
14132                 if (plci->B3_prot == 4)
14133                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14134                 else
14135                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
14136                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14137         }
14138 }
14139
14140
14141 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14142 {
14143         word internal_command;
14144
14145         dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14146                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14147
14148         internal_command = plci->internal_command;
14149         plci->internal_command = 0;
14150         switch (internal_command)
14151         {
14152         default:
14153                 plci->command = 0;
14154         case FAX_EDATA_ACK_COMMAND_1:
14155                 if (plci_nl_busy(plci))
14156                 {
14157                         plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14158                         return;
14159                 }
14160                 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14161                 plci->NData[0].P = plci->fax_connect_info_buffer;
14162                 plci->NData[0].PLength = plci->fax_edata_ack_length;
14163                 plci->NL.X = plci->NData;
14164                 plci->NL.ReqCh = 0;
14165                 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14166                 plci->adapter->request(&plci->NL);
14167                 return;
14168         case FAX_EDATA_ACK_COMMAND_2:
14169                 if ((Rc != OK) && (Rc != OK_FC))
14170                 {
14171                         dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14172                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14173                         break;
14174                 }
14175         }
14176 }
14177
14178
14179 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14180 {
14181         word Info;
14182         word internal_command;
14183
14184         dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14185                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14186
14187         Info = GOOD;
14188         internal_command = plci->internal_command;
14189         plci->internal_command = 0;
14190         switch (internal_command)
14191         {
14192         default:
14193                 plci->command = 0;
14194         case FAX_CONNECT_INFO_COMMAND_1:
14195                 if (plci_nl_busy(plci))
14196                 {
14197                         plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14198                         return;
14199                 }
14200                 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14201                 plci->NData[0].P = plci->fax_connect_info_buffer;
14202                 plci->NData[0].PLength = plci->fax_connect_info_length;
14203                 plci->NL.X = plci->NData;
14204                 plci->NL.ReqCh = 0;
14205                 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14206                 plci->adapter->request(&plci->NL);
14207                 return;
14208         case FAX_CONNECT_INFO_COMMAND_2:
14209                 if ((Rc != OK) && (Rc != OK_FC))
14210                 {
14211                         dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14212                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14213                         Info = _WRONG_STATE;
14214                         break;
14215                 }
14216                 if (plci_nl_busy(plci))
14217                 {
14218                         plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14219                         return;
14220                 }
14221                 plci->command = _CONNECT_B3_R;
14222                 nl_req_ncci(plci, N_CONNECT, 0);
14223                 send_req(plci);
14224                 return;
14225         }
14226         sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14227 }
14228
14229
14230 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14231 {
14232         word Info;
14233         word internal_command;
14234
14235         dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14236                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14237
14238         Info = GOOD;
14239         internal_command = plci->internal_command;
14240         plci->internal_command = 0;
14241         switch (internal_command)
14242         {
14243         default:
14244                 plci->command = 0;
14245                 plci->adjust_b_parms_msg = NULL;
14246                 plci->adjust_b_facilities = plci->B1_facilities;
14247                 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14248                 plci->adjust_b_ncci = (word)(Id >> 16);
14249                 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14250                 plci->adjust_b_state = ADJUST_B_START;
14251                 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14252                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14253         case FAX_ADJUST_B23_COMMAND_1:
14254                 Info = adjust_b_process(Id, plci, Rc);
14255                 if (Info != GOOD)
14256                 {
14257                         dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14258                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14259                         break;
14260                 }
14261                 if (plci->internal_command)
14262                         return;
14263         case FAX_ADJUST_B23_COMMAND_2:
14264                 if (plci_nl_busy(plci))
14265                 {
14266                         plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14267                         return;
14268                 }
14269                 plci->command = _CONNECT_B3_R;
14270                 nl_req_ncci(plci, N_CONNECT, 0);
14271                 send_req(plci);
14272                 return;
14273         }
14274         sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14275 }
14276
14277
14278 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14279 {
14280         word internal_command;
14281
14282         dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14283                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14284
14285         internal_command = plci->internal_command;
14286         plci->internal_command = 0;
14287         switch (internal_command)
14288         {
14289         default:
14290                 plci->command = 0;
14291                 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14292                 return;
14293         case FAX_DISCONNECT_COMMAND_1:
14294         case FAX_DISCONNECT_COMMAND_2:
14295         case FAX_DISCONNECT_COMMAND_3:
14296                 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14297                 {
14298                         dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14299                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14300                         break;
14301                 }
14302                 if (Rc == OK)
14303                 {
14304                         if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14305                             || (internal_command == FAX_DISCONNECT_COMMAND_2))
14306                         {
14307                                 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14308                         }
14309                 }
14310                 else if (Rc == 0)
14311                 {
14312                         if (internal_command == FAX_DISCONNECT_COMMAND_1)
14313                                 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14314                 }
14315                 return;
14316         }
14317 }
14318
14319
14320
14321 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14322 {
14323         word Info;
14324         word internal_command;
14325
14326         dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14327                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14328
14329         Info = GOOD;
14330         internal_command = plci->internal_command;
14331         plci->internal_command = 0;
14332         switch (internal_command)
14333         {
14334         default:
14335                 plci->command = 0;
14336         case RTP_CONNECT_B3_REQ_COMMAND_1:
14337                 if (plci_nl_busy(plci))
14338                 {
14339                         plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14340                         return;
14341                 }
14342                 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14343                 nl_req_ncci(plci, N_CONNECT, 0);
14344                 send_req(plci);
14345                 return;
14346         case RTP_CONNECT_B3_REQ_COMMAND_2:
14347                 if ((Rc != OK) && (Rc != OK_FC))
14348                 {
14349                         dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14350                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14351                         Info = _WRONG_STATE;
14352                         break;
14353                 }
14354                 if (plci_nl_busy(plci))
14355                 {
14356                         plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14357                         return;
14358                 }
14359                 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14360                 plci->NData[0].PLength = plci->internal_req_buffer[0];
14361                 plci->NData[0].P = plci->internal_req_buffer + 1;
14362                 plci->NL.X = plci->NData;
14363                 plci->NL.ReqCh = 0;
14364                 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14365                 plci->adapter->request(&plci->NL);
14366                 break;
14367         case RTP_CONNECT_B3_REQ_COMMAND_3:
14368                 return;
14369         }
14370         sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14371 }
14372
14373
14374 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14375 {
14376         word internal_command;
14377
14378         dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14379                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14380
14381         internal_command = plci->internal_command;
14382         plci->internal_command = 0;
14383         switch (internal_command)
14384         {
14385         default:
14386                 plci->command = 0;
14387         case RTP_CONNECT_B3_RES_COMMAND_1:
14388                 if (plci_nl_busy(plci))
14389                 {
14390                         plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14391                         return;
14392                 }
14393                 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14394                 nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14395                 send_req(plci);
14396                 return;
14397         case RTP_CONNECT_B3_RES_COMMAND_2:
14398                 if ((Rc != OK) && (Rc != OK_FC))
14399                 {
14400                         dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14401                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14402                         break;
14403                 }
14404                 if (plci_nl_busy(plci))
14405                 {
14406                         plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14407                         return;
14408                 }
14409                 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14410                 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14411                 plci->NData[0].PLength = plci->internal_req_buffer[0];
14412                 plci->NData[0].P = plci->internal_req_buffer + 1;
14413                 plci->NL.X = plci->NData;
14414                 plci->NL.ReqCh = 0;
14415                 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14416                 plci->adapter->request(&plci->NL);
14417                 return;
14418         case RTP_CONNECT_B3_RES_COMMAND_3:
14419                 return;
14420         }
14421 }
14422
14423
14424
14425 static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14426 {
14427         byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14428         word Info;
14429         word internal_command;
14430
14431         dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14432                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14433
14434         Info = GOOD;
14435         internal_command = plci->internal_command;
14436         plci->internal_command = 0;
14437         switch (internal_command)
14438         {
14439         default:
14440                 if (!plci->NL.Id)
14441                         break;
14442                 plci->command = 0;
14443                 plci->adjust_b_parms_msg = NULL;
14444                 plci->adjust_b_facilities = plci->B1_facilities;
14445                 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14446                 plci->adjust_b_ncci = (word)(Id >> 16);
14447                 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14448                 plci->adjust_b_state = ADJUST_B_START;
14449                 dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14450                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14451         case HOLD_SAVE_COMMAND_1:
14452                 Info = adjust_b_process(Id, plci, Rc);
14453                 if (Info != GOOD)
14454                 {
14455                         dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14456                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14457                         break;
14458                 }
14459                 if (plci->internal_command)
14460                         return;
14461         }
14462         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14463 }
14464
14465
14466 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14467 {
14468         byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14469         word Info;
14470         word internal_command;
14471
14472         dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14473                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14474
14475         Info = GOOD;
14476         internal_command = plci->internal_command;
14477         plci->internal_command = 0;
14478         switch (internal_command)
14479         {
14480         default:
14481                 plci->command = 0;
14482                 plci->adjust_b_parms_msg = NULL;
14483                 plci->adjust_b_facilities = plci->B1_facilities;
14484                 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14485                 plci->adjust_b_ncci = (word)(Id >> 16);
14486                 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14487                 plci->adjust_b_state = ADJUST_B_START;
14488                 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14489                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14490         case RETRIEVE_RESTORE_COMMAND_1:
14491                 Info = adjust_b_process(Id, plci, Rc);
14492                 if (Info != GOOD)
14493                 {
14494                         dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14495                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14496                         break;
14497                 }
14498                 if (plci->internal_command)
14499                         return;
14500         }
14501         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14502 }
14503
14504
14505 static void init_b1_config(PLCI *plci)
14506 {
14507
14508         dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14509                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14510                         (char *)(FILE_), __LINE__));
14511
14512         plci->B1_resource = 0;
14513         plci->B1_facilities = 0;
14514
14515         plci->li_bchannel_id = 0;
14516         mixer_clear_config(plci);
14517
14518
14519         ec_clear_config(plci);
14520
14521
14522         dtmf_rec_clear_config(plci);
14523         dtmf_send_clear_config(plci);
14524         dtmf_parameter_clear_config(plci);
14525
14526         adv_voice_clear_config(plci);
14527         adjust_b_clear(plci);
14528 }
14529
14530
14531 static void clear_b1_config(PLCI *plci)
14532 {
14533
14534         dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14535                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14536                         (char *)(FILE_), __LINE__));
14537
14538         adv_voice_clear_config(plci);
14539         adjust_b_clear(plci);
14540
14541         ec_clear_config(plci);
14542
14543
14544         dtmf_rec_clear_config(plci);
14545         dtmf_send_clear_config(plci);
14546         dtmf_parameter_clear_config(plci);
14547
14548
14549         if ((plci->li_bchannel_id != 0)
14550             && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14551         {
14552                 mixer_clear_config(plci);
14553                 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14554                 plci->li_bchannel_id = 0;
14555         }
14556
14557         plci->B1_resource = 0;
14558         plci->B1_facilities = 0;
14559 }
14560
14561
14562 /* -----------------------------------------------------------------
14563    XON protocol local helpers
14564    ----------------------------------------------------------------- */
14565 static void channel_flow_control_remove(PLCI *plci) {
14566         DIVA_CAPI_ADAPTER *a = plci->adapter;
14567         word i;
14568         for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14569                 if (a->ch_flow_plci[i] == plci->Id) {
14570                         a->ch_flow_plci[i] = 0;
14571                         a->ch_flow_control[i] = 0;
14572                 }
14573         }
14574 }
14575
14576 static void channel_x_on(PLCI *plci, byte ch) {
14577         DIVA_CAPI_ADAPTER *a = plci->adapter;
14578         if (a->ch_flow_control[ch] & N_XON_SENT) {
14579                 a->ch_flow_control[ch] &= ~N_XON_SENT;
14580         }
14581 }
14582
14583 static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14584         DIVA_CAPI_ADAPTER *a = plci->adapter;
14585         if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14586                 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14587                 a->ch_flow_plci[ch] = plci->Id;
14588                 a->ch_flow_control_pending++;
14589         }
14590 }
14591
14592 static void channel_request_xon(PLCI *plci, byte ch) {
14593         DIVA_CAPI_ADAPTER *a = plci->adapter;
14594
14595         if (a->ch_flow_control[ch] & N_CH_XOFF) {
14596                 a->ch_flow_control[ch] |= N_XON_REQ;
14597                 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14598                 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14599         }
14600 }
14601
14602 static void channel_xmit_extended_xon(PLCI *plci) {
14603         DIVA_CAPI_ADAPTER *a;
14604         int max_ch = ARRAY_SIZE(a->ch_flow_control);
14605         int i, one_requested = 0;
14606
14607         if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14608                 return;
14609         }
14610
14611         for (i = 0; i < max_ch; i++) {
14612                 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14613                     (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14614                     (plci->Id == a->ch_flow_plci[i])) {
14615                         channel_request_xon(plci, (byte)i);
14616                         one_requested = 1;
14617                 }
14618         }
14619
14620         if (one_requested) {
14621                 channel_xmit_xon(plci);
14622         }
14623 }
14624
14625 /*
14626   Try to xmit next X_ON
14627 */
14628 static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14629         int max_ch = ARRAY_SIZE(a->ch_flow_control);
14630         int i;
14631
14632         if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14633                 return (0);
14634         }
14635
14636         if (a->last_flow_control_ch >= max_ch) {
14637                 a->last_flow_control_ch = 1;
14638         }
14639         for (i = a->last_flow_control_ch; i < max_ch; i++) {
14640                 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14641                     (plci->Id == a->ch_flow_plci[i])) {
14642                         a->last_flow_control_ch = i + 1;
14643                         return (i);
14644                 }
14645         }
14646
14647         for (i = 1; i < a->last_flow_control_ch; i++) {
14648                 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14649                     (plci->Id == a->ch_flow_plci[i])) {
14650                         a->last_flow_control_ch = i + 1;
14651                         return (i);
14652                 }
14653         }
14654
14655         return (0);
14656 }
14657
14658 static void channel_xmit_xon(PLCI *plci) {
14659         DIVA_CAPI_ADAPTER *a = plci->adapter;
14660         byte ch;
14661
14662         if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14663                 return;
14664         }
14665         if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14666                 return;
14667         }
14668         a->ch_flow_control[ch] &= ~N_XON_REQ;
14669         a->ch_flow_control[ch] |= N_XON_SENT;
14670
14671         plci->NL.Req = plci->nl_req = (byte)N_XON;
14672         plci->NL.ReqCh         = ch;
14673         plci->NL.X             = plci->NData;
14674         plci->NL.XNum          = 1;
14675         plci->NData[0].P       = &plci->RBuffer[0];
14676         plci->NData[0].PLength = 0;
14677
14678         plci->adapter->request(&plci->NL);
14679 }
14680
14681 static int channel_can_xon(PLCI *plci, byte ch) {
14682         APPL *APPLptr;
14683         DIVA_CAPI_ADAPTER *a;
14684         word NCCIcode;
14685         dword count;
14686         word Num;
14687         word i;
14688
14689         APPLptr = plci->appl;
14690         a = plci->adapter;
14691
14692         if (!APPLptr)
14693                 return (0);
14694
14695         NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14696
14697         /* count all buffers within the Application pool    */
14698         /* belonging to the same NCCI. XON if a first is    */
14699         /* used.                                            */
14700         count = 0;
14701         Num = 0xffff;
14702         for (i = 0; i < APPLptr->MaxBuffer; i++) {
14703                 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14704                 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14705         }
14706         if ((count > 2) || (Num == 0xffff)) {
14707                 return (0);
14708         }
14709         return (1);
14710 }
14711
14712
14713 /*------------------------------------------------------------------*/
14714
14715 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14716 {
14717         return 1;
14718 }
14719
14720
14721
14722 /**********************************************************************************/
14723 /* function groups the listening applications according to the CIP mask and the   */
14724 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14725 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14726 /* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14727 /* function must be enabled by setting "a->group_optimization_enabled" from the   */
14728 /* OS specific part (per adapter).                                                */
14729 /**********************************************************************************/
14730 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14731 {
14732         word i, j, k, busy, group_found;
14733         dword info_mask_group[MAX_CIP_TYPES];
14734         dword cip_mask_group[MAX_CIP_TYPES];
14735         word appl_number_group_type[MAX_APPL];
14736         PLCI *auxplci;
14737
14738         set_group_ind_mask(plci); /* all APPLs within this inc. call are allowed to dial in */
14739
14740         if (!a->group_optimization_enabled)
14741         {
14742                 dbug(1, dprintf("No group optimization"));
14743                 return;
14744         }
14745
14746         dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14747
14748         for (i = 0; i < MAX_CIP_TYPES; i++)
14749         {
14750                 info_mask_group[i] = 0;
14751                 cip_mask_group[i] = 0;
14752         }
14753         for (i = 0; i < MAX_APPL; i++)
14754         {
14755                 appl_number_group_type[i] = 0;
14756         }
14757         for (i = 0; i < max_appl; i++) /* check if any multi instance capable application is present */
14758         {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14759                 if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14760                 {
14761                         dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14762                         return; /* allow good application unfiltered access */
14763                 }
14764         }
14765         for (i = 0; i < max_appl; i++) /* Build CIP Groups */
14766         {
14767                 if (application[i].Id && a->CIP_Mask[i])
14768                 {
14769                         for (k = 0, busy = false; k < a->max_plci; k++)
14770                         {
14771                                 if (a->plci[k].Id)
14772                                 {
14773                                         auxplci = &a->plci[k];
14774                                         if (auxplci->appl == &application[i]) /* application has a busy PLCI */
14775                                         {
14776                                                 busy = true;
14777                                                 dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14778                                         }
14779                                         else if (test_c_ind_mask_bit(auxplci, i)) /* application has an incoming call pending */
14780                                         {
14781                                                 busy = true;
14782                                                 dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14783                                         }
14784                                 }
14785                         }
14786
14787                         for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++)     /* build groups with free applications only */
14788                         {
14789                                 if (j == MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14790                                 {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14791                                         appl_number_group_type[i] = MAX_CIP_TYPES;
14792                                         group_found = true;
14793                                         dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14794                                 }
14795                                 else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14796                                 {                                      /* is group already present ?                  */
14797                                         appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14798                                         group_found = true;
14799                                         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]));
14800                                 }
14801                                 else if (!info_mask_group[j])
14802                                 {                                      /* establish a new group                       */
14803                                         appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14804                                         info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14805                                         cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14806                                         group_found = true;
14807                                         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]));
14808                                 }
14809                         }
14810                 }
14811         }
14812
14813         for (i = 0; i < max_appl; i++) /* Build group_optimization_mask_table */
14814         {
14815                 if (appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14816                 {
14817                         if (appl_number_group_type[i] == MAX_CIP_TYPES)
14818                         {
14819                                 dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14820                         }
14821                         else
14822                         {
14823                                 dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14824                                 for (j = i + 1; j < max_appl; j++)   /* search other group members and mark them as busy        */
14825                                 {
14826                                         if (appl_number_group_type[i] == appl_number_group_type[j])
14827                                         {
14828                                                 dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14829                                                 clear_group_ind_mask_bit(plci, j);           /* disable call on other group members */
14830                                                 appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14831                                         }
14832                                 }
14833                         }
14834                 }
14835                 else                                                 /* application should not get a call */
14836                 {
14837                         clear_group_ind_mask_bit(plci, i);
14838                 }
14839         }
14840
14841 }
14842
14843
14844
14845 /* OS notifies the driver about a application Capi_Register */
14846 word CapiRegister(word id)
14847 {
14848         word i, j, appls_found;
14849
14850         PLCI *plci;
14851         DIVA_CAPI_ADAPTER *a;
14852
14853         for (i = 0, appls_found = 0; i < max_appl; i++)
14854         {
14855                 if (application[i].Id && (application[i].Id != id))
14856                 {
14857                         appls_found++;                       /* an application has been found */
14858                 }
14859         }
14860
14861         if (appls_found) return true;
14862         for (i = 0; i < max_adapter; i++)                   /* scan all adapters...    */
14863         {
14864                 a = &adapter[i];
14865                 if (a->request)
14866                 {
14867                         if (a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14868                         {
14869                                 if (!appls_found)           /* first application does a capi register   */
14870                                 {
14871                                         if ((j = get_plci(a)))                    /* activate L1 of all adapters */
14872                                         {
14873                                                 plci = &a->plci[j - 1];
14874                                                 plci->command = 0;
14875                                                 add_p(plci, OAD, "\x01\xfd");
14876                                                 add_p(plci, CAI, "\x01\x80");
14877                                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14878                                                 add_p(plci, SHIFT | 6, NULL);
14879                                                 add_p(plci, SIN, "\x02\x00\x00");
14880                                                 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14881                                                 sig_req(plci, ASSIGN, DSIG_ID);
14882                                                 add_p(plci, FTY, "\x02\xff\x07"); /* l1 start */
14883                                                 sig_req(plci, SIG_CTRL, 0);
14884                                                 send_req(plci);
14885                                         }
14886                                 }
14887                         }
14888                 }
14889         }
14890         return false;
14891 }
14892
14893 /*------------------------------------------------------------------*/
14894
14895 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14896
14897 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14898 {
14899         word i;
14900         /* Format of vswitch_t:
14901            0 byte length
14902            1 byte VSWITCHIE
14903            2 byte VSWITCH_REQ/VSWITCH_IND
14904            3 byte reserved
14905            4 word VSwitchcommand
14906            6 word returnerror
14907            8... Params
14908         */
14909         if (!plci ||
14910             !plci->appl ||
14911             !plci->State ||
14912             plci->Sig.Ind == NCR_FACILITY
14913                 )
14914                 return;
14915
14916         for (i = 0; i < MAX_MULTI_IE; i++)
14917         {
14918                 if (!parms[i][0]) continue;
14919                 if (parms[i][0] < 7)
14920                 {
14921                         parms[i][0] = 0; /* kill it */
14922                         continue;
14923                 }
14924                 dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14925                 switch (parms[i][4])
14926                 {
14927                 case VSJOIN:
14928                         if (!plci->relatedPTYPLCI ||
14929                             (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14930                         { /* Error */
14931                                 break;
14932                         }
14933                         /* remember all necessary informations */
14934                         if (parms[i][0] != 11 || parms[i][8] != 3) /* Length Test */
14935                         {
14936                                 break;
14937                         }
14938                         if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14939                         {   /* first indication after ECT-Request on Consultation Call */
14940                                 plci->vswitchstate = parms[i][9];
14941                                 parms[i][9] = 2; /* State */
14942                                 /* now ask first Call to join */
14943                         }
14944                         else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14945                         { /* Answer of VSWITCH_REQ from first Call */
14946                                 plci->vswitchstate = parms[i][9];
14947                                 /* tell consultation call to join
14948                                    and the protocol capabilities of the first call */
14949                         }
14950                         else
14951                         { /* Error */
14952                                 break;
14953                         }
14954                         plci->vsprot = parms[i][10]; /* protocol */
14955                         plci->vsprotdialect = parms[i][11]; /* protocoldialect */
14956                         /* send join request to related PLCI */
14957                         parms[i][1] = VSWITCHIE;
14958                         parms[i][2] = VSWITCH_REQ;
14959
14960                         plci->relatedPTYPLCI->command = 0;
14961                         plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14962                         add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14963                         sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14964                         send_req(plci->relatedPTYPLCI);
14965                         break;
14966                 case VSTRANSPORT:
14967                 default:
14968                         if (plci->relatedPTYPLCI &&
14969                             plci->vswitchstate == 3 &&
14970                             plci->relatedPTYPLCI->vswitchstate == 3)
14971                         {
14972                                 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14973                                 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14974                                 send_req(plci->relatedPTYPLCI);
14975                         }
14976                         break;
14977                 }
14978                 parms[i][0] = 0; /* kill it */
14979         }
14980 }
14981
14982
14983 /*------------------------------------------------------------------*/
14984
14985 static int diva_get_dma_descriptor(PLCI *plci, dword   *dma_magic) {
14986         ENTITY e;
14987         IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14988
14989         if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14990                 return (-1);
14991         }
14992
14993         pReq->xdi_dma_descriptor_operation.Req = 0;
14994         pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14995
14996         pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14997         pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
14998         pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14999         pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15000
15001         e.user[0] = plci->adapter->Id - 1;
15002         plci->adapter->request((ENTITY *)pReq);
15003
15004         if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15005             (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15006             pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15007                 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15008                 dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
15009                                 plci->adapter->Id,
15010                                 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15011                                 *dma_magic));
15012                 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15013         } else {
15014                 dbug(1, dprintf("dma_alloc failed"));
15015                 return (-1);
15016         }
15017 }
15018
15019 static void diva_free_dma_descriptor(PLCI *plci, int nr) {
15020         ENTITY e;
15021         IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
15022
15023         if (nr < 0) {
15024                 return;
15025         }
15026
15027         pReq->xdi_dma_descriptor_operation.Req = 0;
15028         pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15029
15030         pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15031         pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
15032         pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15033         pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15034
15035         e.user[0] = plci->adapter->Id - 1;
15036         plci->adapter->request((ENTITY *)pReq);
15037
15038         if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15039                 dbug(1, dprintf("dma_free(%d)", nr));
15040         } else {
15041                 dbug(1, dprintf("dma_free failed (%d)", nr));
15042         }
15043 }
15044
15045 /*------------------------------------------------------------------*/