]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/isdn/hardware/eicon/message.c
PM / QoS: Remove global notifiers
[linux.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 *, 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         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         word multi_fac_id[] = {1, FTY};
4870         word multi_pi_id[]  = {1, PI};
4871         word multi_CiPN_id[]  = {1, OAD};
4872         word multi_ssext_id[]  = {1, ESC_SSEXT};
4873
4874         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, 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                                 PUT_WORD(&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11301                                 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11302                                 w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11303                                 if (w != _QUEUE_FULL)
11304                                 {
11305                                         if (w != 0)
11306                                         {
11307                                                 dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11308                                                                 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11309                                                                 (char *)(FILE_), __LINE__,
11310                                                                 (dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11311                                         }
11312                                         notify_plci->li_notify_update = false;
11313                                 }
11314                         }
11315                 } while (others && (notify_plci != NULL));
11316                 if (others)
11317                         plci->li_notify_update = false;
11318         }
11319 }
11320
11321
11322 static void mixer_clear_config(PLCI *plci)
11323 {
11324         DIVA_CAPI_ADAPTER *a;
11325         word i, j;
11326
11327         dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11328                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11329                         (char *)(FILE_), __LINE__));
11330
11331         plci->li_notify_update = false;
11332         plci->li_plci_b_write_pos = 0;
11333         plci->li_plci_b_read_pos = 0;
11334         plci->li_plci_b_req_pos = 0;
11335         a = plci->adapter;
11336         if ((plci->li_bchannel_id != 0)
11337             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11338         {
11339                 i = a->li_base + (plci->li_bchannel_id - 1);
11340                 li_config_table[i].curchnl = 0;
11341                 li_config_table[i].channel = 0;
11342                 li_config_table[i].chflags = 0;
11343                 for (j = 0; j < li_total_channels; j++)
11344                 {
11345                         li_config_table[j].flag_table[i] = 0;
11346                         li_config_table[i].flag_table[j] = 0;
11347                         li_config_table[i].coef_table[j] = 0;
11348                         li_config_table[j].coef_table[i] = 0;
11349                 }
11350                 if (!a->li_pri)
11351                 {
11352                         li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11353                         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11354                         {
11355                                 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11356                                 li_config_table[i].curchnl = 0;
11357                                 li_config_table[i].channel = 0;
11358                                 li_config_table[i].chflags = 0;
11359                                 for (j = 0; j < li_total_channels; j++)
11360                                 {
11361                                         li_config_table[i].flag_table[j] = 0;
11362                                         li_config_table[j].flag_table[i] = 0;
11363                                         li_config_table[i].coef_table[j] = 0;
11364                                         li_config_table[j].coef_table[i] = 0;
11365                                 }
11366                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11367                                 {
11368                                         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11369                                         li_config_table[i].curchnl = 0;
11370                                         li_config_table[i].channel = 0;
11371                                         li_config_table[i].chflags = 0;
11372                                         for (j = 0; j < li_total_channels; j++)
11373                                         {
11374                                                 li_config_table[i].flag_table[j] = 0;
11375                                                 li_config_table[j].flag_table[i] = 0;
11376                                                 li_config_table[i].coef_table[j] = 0;
11377                                                 li_config_table[j].coef_table[i] = 0;
11378                                         }
11379                                 }
11380                         }
11381                 }
11382         }
11383 }
11384
11385
11386 static void mixer_prepare_switch(dword Id, PLCI *plci)
11387 {
11388
11389         dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11390                         UnMapId(Id), (char *)(FILE_), __LINE__));
11391
11392         do
11393         {
11394                 mixer_indication_coefs_set(Id, plci);
11395         } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11396 }
11397
11398
11399 static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11400 {
11401         DIVA_CAPI_ADAPTER *a;
11402         word i, j;
11403
11404         dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11405                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11406
11407         a = plci->adapter;
11408         if ((plci->li_bchannel_id != 0)
11409             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11410         {
11411                 i = a->li_base + (plci->li_bchannel_id - 1);
11412                 for (j = 0; j < li_total_channels; j++)
11413                 {
11414                         li_config_table[i].coef_table[j] &= 0xf;
11415                         li_config_table[j].coef_table[i] &= 0xf;
11416                 }
11417                 if (!a->li_pri)
11418                         li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11419         }
11420         return (GOOD);
11421 }
11422
11423
11424 static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11425 {
11426         DIVA_CAPI_ADAPTER *a;
11427         word Info;
11428
11429         dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11430                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11431
11432         Info = GOOD;
11433         a = plci->adapter;
11434         if ((plci->B1_facilities & B1_FACILITY_MIXER)
11435             && (plci->li_bchannel_id != 0)
11436             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11437         {
11438                 switch (plci->adjust_b_state)
11439                 {
11440                 case ADJUST_B_RESTORE_MIXER_1:
11441                         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11442                         {
11443                                 plci->internal_command = plci->adjust_b_command;
11444                                 if (plci_nl_busy(plci))
11445                                 {
11446                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11447                                         break;
11448                                 }
11449                                 xconnect_query_addresses(plci);
11450                                 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11451                                 break;
11452                         }
11453                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11454                         Rc = OK;
11455                 case ADJUST_B_RESTORE_MIXER_2:
11456                 case ADJUST_B_RESTORE_MIXER_3:
11457                 case ADJUST_B_RESTORE_MIXER_4:
11458                         if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11459                         {
11460                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11461                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11462                                 Info = _WRONG_STATE;
11463                                 break;
11464                         }
11465                         if (Rc == OK)
11466                         {
11467                                 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11468                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11469                                 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11470                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11471                         }
11472                         else if (Rc == 0)
11473                         {
11474                                 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11475                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11476                                 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11477                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11478                         }
11479                         if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11480                         {
11481                                 plci->internal_command = plci->adjust_b_command;
11482                                 break;
11483                         }
11484                 case ADJUST_B_RESTORE_MIXER_5:
11485                         xconnect_write_coefs(plci, plci->adjust_b_command);
11486                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11487                         Rc = OK;
11488                 case ADJUST_B_RESTORE_MIXER_6:
11489                         if (!xconnect_write_coefs_process(Id, plci, Rc))
11490                         {
11491                                 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11492                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11493                                 Info = _FACILITY_NOT_SUPPORTED;
11494                                 break;
11495                         }
11496                         if (plci->internal_command)
11497                                 break;
11498                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11499                 case ADJUST_B_RESTORE_MIXER_7:
11500                         break;
11501                 }
11502         }
11503         return (Info);
11504 }
11505
11506
11507 static void mixer_command(dword Id, PLCI *plci, byte Rc)
11508 {
11509         DIVA_CAPI_ADAPTER *a;
11510         word i, internal_command;
11511
11512         dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11513                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11514                         plci->li_cmd));
11515
11516         a = plci->adapter;
11517         internal_command = plci->internal_command;
11518         plci->internal_command = 0;
11519         switch (plci->li_cmd)
11520         {
11521         case LI_REQ_CONNECT:
11522         case LI_REQ_DISCONNECT:
11523         case LI_REQ_SILENT_UPDATE:
11524                 switch (internal_command)
11525                 {
11526                 default:
11527                         if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11528                         {
11529                                 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11530                                                                           B1_FACILITY_MIXER), MIXER_COMMAND_1);
11531                         }
11532                 case MIXER_COMMAND_1:
11533                         if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11534                         {
11535                                 if (adjust_b_process(Id, plci, Rc) != GOOD)
11536                                 {
11537                                         dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11538                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
11539                                         break;
11540                                 }
11541                                 if (plci->internal_command)
11542                                         return;
11543                         }
11544                         plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11545                         if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11546                             || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11547                                 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11548                                                                                       ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11549                         {
11550                                 xconnect_write_coefs(plci, MIXER_COMMAND_2);
11551                         }
11552                         else
11553                         {
11554                                 do
11555                                 {
11556                                         mixer_indication_coefs_set(Id, plci);
11557                                 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11558                         }
11559                 case MIXER_COMMAND_2:
11560                         if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11561                             || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11562                                 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11563                                                                                       ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11564                         {
11565                                 if (!xconnect_write_coefs_process(Id, plci, Rc))
11566                                 {
11567                                         dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11568                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
11569                                         if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11570                                         {
11571                                                 do
11572                                                 {
11573                                                         plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11574                                                                 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11575                                                         i = (plci->li_plci_b_write_pos == 0) ?
11576                                                                 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11577                                                 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11578                                                          && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11579                                         }
11580                                         break;
11581                                 }
11582                                 if (plci->internal_command)
11583                                         return;
11584                         }
11585                         if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11586                         {
11587                                 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11588                                                                           ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11589                         }
11590                 case MIXER_COMMAND_3:
11591                         if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11592                         {
11593                                 if (adjust_b_process(Id, plci, Rc) != GOOD)
11594                                 {
11595                                         dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11596                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
11597                                         break;
11598                                 }
11599                                 if (plci->internal_command)
11600                                         return;
11601                         }
11602                         break;
11603                 }
11604                 break;
11605         }
11606         if ((plci->li_bchannel_id == 0)
11607             || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11608         {
11609                 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11610                                 UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11611         }
11612         else
11613         {
11614                 i = a->li_base + (plci->li_bchannel_id - 1);
11615                 li_config_table[i].curchnl = plci->li_channel_bits;
11616                 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11617                 {
11618                         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11619                         li_config_table[i].curchnl = plci->li_channel_bits;
11620                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11621                         {
11622                                 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11623                                 li_config_table[i].curchnl = plci->li_channel_bits;
11624                         }
11625                 }
11626         }
11627 }
11628
11629
11630 static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11631                               dword plci_b_id, byte connect, dword li_flags)
11632 {
11633         word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11634         PLCI *plci_b;
11635         DIVA_CAPI_ADAPTER *a_b;
11636
11637         a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11638         plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11639         ch_a = a->li_base + (plci->li_bchannel_id - 1);
11640         if (!a->li_pri && (plci->tel == ADV_VOICE)
11641             && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11642         {
11643                 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11644                 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11645                         a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11646         }
11647         else
11648         {
11649                 ch_a_v = ch_a;
11650                 ch_a_s = ch_a;
11651         }
11652         ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11653         if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11654             && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11655         {
11656                 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11657                 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11658                         a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11659         }
11660         else
11661         {
11662                 ch_b_v = ch_b;
11663                 ch_b_s = ch_b;
11664         }
11665         if (connect)
11666         {
11667                 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11668                 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11669                 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11670                 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11671         }
11672         li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11673         li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11674         li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11675         li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11676         if (ch_a_v == ch_b_v)
11677         {
11678                 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11679                 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11680         }
11681         else
11682         {
11683                 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11684                 {
11685                         for (i = 0; i < li_total_channels; i++)
11686                         {
11687                                 if (i != ch_a_v)
11688                                         li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11689                         }
11690                 }
11691                 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11692                 {
11693                         for (i = 0; i < li_total_channels; i++)
11694                         {
11695                                 if (i != ch_a_s)
11696                                         li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11697                         }
11698                 }
11699                 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11700                 {
11701                         for (i = 0; i < li_total_channels; i++)
11702                         {
11703                                 if (i != ch_a_v)
11704                                         li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11705                         }
11706                 }
11707                 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11708                 {
11709                         for (i = 0; i < li_total_channels; i++)
11710                         {
11711                                 if (i != ch_a_s)
11712                                         li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11713                         }
11714                 }
11715         }
11716         if (li_flags & LI_FLAG_CONFERENCE_A_B)
11717         {
11718                 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11719                 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11720                 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11721                 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11722         }
11723         if (li_flags & LI_FLAG_CONFERENCE_B_A)
11724         {
11725                 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11726                 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11727                 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11728                 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11729         }
11730         if (li_flags & LI_FLAG_MONITOR_A)
11731         {
11732                 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11733                 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11734         }
11735         if (li_flags & LI_FLAG_MONITOR_B)
11736         {
11737                 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11738                 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11739         }
11740         if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11741         {
11742                 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11743                 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11744         }
11745         if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11746         {
11747                 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11748                 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11749         }
11750         if (li_flags & LI_FLAG_MIX_A)
11751         {
11752                 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11753                 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11754         }
11755         if (li_flags & LI_FLAG_MIX_B)
11756         {
11757                 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11758                 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11759         }
11760         if (ch_a_v != ch_a_s)
11761         {
11762                 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11763                 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11764         }
11765         if (ch_b_v != ch_b_s)
11766         {
11767                 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11768                 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11769         }
11770 }
11771
11772
11773 static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11774                                dword plci_b_id, byte connect, dword li_flags)
11775 {
11776         word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11777         PLCI *plci_b;
11778         DIVA_CAPI_ADAPTER *a_b;
11779
11780         a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11781         plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11782         ch_a = a->li_base + (plci->li_bchannel_id - 1);
11783         if (!a->li_pri && (plci->tel == ADV_VOICE)
11784             && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11785         {
11786                 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11787                 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11788                         a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11789         }
11790         else
11791         {
11792                 ch_a_v = ch_a;
11793                 ch_a_s = ch_a;
11794         }
11795         ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11796         if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11797             && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11798         {
11799                 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11800                 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11801                         a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11802         }
11803         else
11804         {
11805                 ch_b_v = ch_b;
11806                 ch_b_s = ch_b;
11807         }
11808         if (connect)
11809         {
11810                 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11811                 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11812                 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11813                 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11814                 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11815                 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11816         }
11817         li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11818         li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11819         li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11820         li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11821         li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11822         li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11823         li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11824         li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11825         if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11826         {
11827                 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11828                 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11829                 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11830                 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11831         }
11832         if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11833         {
11834                 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11835                 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11836                 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11837                 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11838         }
11839         if (li_flags & LI2_FLAG_MONITOR_B)
11840         {
11841                 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11842                 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11843         }
11844         if (li_flags & LI2_FLAG_MIX_B)
11845         {
11846                 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11847                 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11848         }
11849         if (li_flags & LI2_FLAG_MONITOR_X)
11850                 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11851         if (li_flags & LI2_FLAG_MIX_X)
11852                 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11853         if (li_flags & LI2_FLAG_LOOP_B)
11854         {
11855                 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11856                 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11857                 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11858                 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11859         }
11860         if (li_flags & LI2_FLAG_LOOP_PC)
11861                 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11862         if (li_flags & LI2_FLAG_LOOP_X)
11863                 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11864         if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11865                 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11866         if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11867                 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11868         if (ch_a_v != ch_a_s)
11869         {
11870                 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11871                 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11872         }
11873         if (ch_b_v != ch_b_s)
11874         {
11875                 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11876                 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11877         }
11878 }
11879
11880
11881 static word li_check_main_plci(dword Id, PLCI *plci)
11882 {
11883         if (plci == NULL)
11884         {
11885                 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11886                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11887                 return (_WRONG_IDENTIFIER);
11888         }
11889         if (!plci->State
11890             || !plci->NL.Id || plci->nl_remove_id
11891             || (plci->li_bchannel_id == 0))
11892         {
11893                 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11894                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11895                 return (_WRONG_STATE);
11896         }
11897         li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11898         return (GOOD);
11899 }
11900
11901
11902 static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11903                              dword plci_b_id, word plci_b_write_pos, byte *p_result)
11904 {
11905         byte ctlr_b;
11906         PLCI *plci_b;
11907
11908         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11909              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11910         {
11911                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11912                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11913                 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11914                 return (NULL);
11915         }
11916         ctlr_b = 0;
11917         if ((plci_b_id & 0x7f) != 0)
11918         {
11919                 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11920                 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11921                         ctlr_b = 0;
11922         }
11923         if ((ctlr_b == 0)
11924             || (((plci_b_id >> 8) & 0xff) == 0)
11925             || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11926         {
11927                 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11928                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11929                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11930                 return (NULL);
11931         }
11932         plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11933         if (!plci_b->State
11934             || !plci_b->NL.Id || plci_b->nl_remove_id
11935             || (plci_b->li_bchannel_id == 0))
11936         {
11937                 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11938                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11939                 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11940                 return (NULL);
11941         }
11942         li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11943         if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11944             ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11945             && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11946                 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11947         {
11948                 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11949                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11950                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11951                 return (NULL);
11952         }
11953         if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11954                                                           (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11955         {
11956                 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11957                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11958                 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11959                 return (NULL);
11960         }
11961         return (plci_b);
11962 }
11963
11964
11965 static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11966                               dword plci_b_id, word plci_b_write_pos, byte *p_result)
11967 {
11968         byte ctlr_b;
11969         PLCI *plci_b;
11970
11971         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11972              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11973         {
11974                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11975                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11976                 PUT_WORD(p_result, _WRONG_STATE);
11977                 return (NULL);
11978         }
11979         ctlr_b = 0;
11980         if ((plci_b_id & 0x7f) != 0)
11981         {
11982                 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11983                 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11984                         ctlr_b = 0;
11985         }
11986         if ((ctlr_b == 0)
11987             || (((plci_b_id >> 8) & 0xff) == 0)
11988             || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11989         {
11990                 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11991                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11992                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11993                 return (NULL);
11994         }
11995         plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11996         if (!plci_b->State
11997             || !plci_b->NL.Id || plci_b->nl_remove_id
11998             || (plci_b->li_bchannel_id == 0)
11999             || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12000         {
12001                 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
12002                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12003                 PUT_WORD(p_result, _WRONG_STATE);
12004                 return (NULL);
12005         }
12006         if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12007             ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
12008             && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12009                 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12010         {
12011                 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
12012                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12013                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
12014                 return (NULL);
12015         }
12016         if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
12017                                                           (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12018         {
12019                 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12020                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12021                 PUT_WORD(p_result, _WRONG_STATE);
12022                 return (NULL);
12023         }
12024         return (plci_b);
12025 }
12026
12027
12028 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
12029 {
12030         word Info;
12031         word i;
12032         dword d, li_flags, plci_b_id;
12033         PLCI *plci_b;
12034         API_PARSE li_parms[3];
12035         API_PARSE li_req_parms[3];
12036         API_PARSE li_participant_struct[2];
12037         API_PARSE li_participant_parms[3];
12038         word participant_parms_pos;
12039         byte result_buffer[32];
12040         byte *result;
12041         word result_pos;
12042         word plci_b_write_pos;
12043
12044         dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
12045                         UnMapId(Id), (char *)(FILE_), __LINE__));
12046
12047         Info = GOOD;
12048         result = result_buffer;
12049         result_buffer[0] = 0;
12050         if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12051         {
12052                 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12053                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12054                 Info = _FACILITY_NOT_SUPPORTED;
12055         }
12056         else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
12057         {
12058                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12059                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12060                 Info = _WRONG_MESSAGE_FORMAT;
12061         }
12062         else
12063         {
12064                 result_buffer[0] = 3;
12065                 PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
12066                 result_buffer[3] = 0;
12067                 switch (GET_WORD(li_parms[0].info))
12068                 {
12069                 case LI_GET_SUPPORTED_SERVICES:
12070                         if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12071                         {
12072                                 result_buffer[0] = 17;
12073                                 result_buffer[3] = 14;
12074                                 PUT_WORD(&result_buffer[4], GOOD);
12075                                 d = 0;
12076                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12077                                         d |= LI_CONFERENCING_SUPPORTED;
12078                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12079                                         d |= LI_MONITORING_SUPPORTED;
12080                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12081                                         d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12082                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12083                                         d |= LI_CROSS_CONTROLLER_SUPPORTED;
12084                                 PUT_DWORD(&result_buffer[6], d);
12085                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12086                                 {
12087                                         d = 0;
12088                                         for (i = 0; i < li_total_channels; i++)
12089                                         {
12090                                                 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12091                                                     && (li_config_table[i].adapter->li_pri
12092                                                         || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12093                                                 {
12094                                                         d++;
12095                                                 }
12096                                         }
12097                                 }
12098                                 else
12099                                 {
12100                                         d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12101                                 }
12102                                 PUT_DWORD(&result_buffer[10], d / 2);
12103                                 PUT_DWORD(&result_buffer[14], d);
12104                         }
12105                         else
12106                         {
12107                                 result_buffer[0] = 25;
12108                                 result_buffer[3] = 22;
12109                                 PUT_WORD(&result_buffer[4], GOOD);
12110                                 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12111                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12112                                         d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12113                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12114                                         d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12115                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12116                                         d |= LI2_PC_LOOPING_SUPPORTED;
12117                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12118                                         d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12119                                 PUT_DWORD(&result_buffer[6], d);
12120                                 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12121                                 PUT_DWORD(&result_buffer[10], d / 2);
12122                                 PUT_DWORD(&result_buffer[14], d - 1);
12123                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12124                                 {
12125                                         d = 0;
12126                                         for (i = 0; i < li_total_channels; i++)
12127                                         {
12128                                                 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12129                                                     && (li_config_table[i].adapter->li_pri
12130                                                         || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12131                                                 {
12132                                                         d++;
12133                                                 }
12134                                         }
12135                                 }
12136                                 PUT_DWORD(&result_buffer[18], d / 2);
12137                                 PUT_DWORD(&result_buffer[22], d - 1);
12138                         }
12139                         break;
12140
12141                 case LI_REQ_CONNECT:
12142                         if (li_parms[1].length == 8)
12143                         {
12144                                 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12145                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12146                                 {
12147                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12148                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12149                                         Info = _WRONG_MESSAGE_FORMAT;
12150                                         break;
12151                                 }
12152                                 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12153                                 li_flags = GET_DWORD(li_req_parms[1].info);
12154                                 Info = li_check_main_plci(Id, plci);
12155                                 result_buffer[0] = 9;
12156                                 result_buffer[3] = 6;
12157                                 PUT_DWORD(&result_buffer[4], plci_b_id);
12158                                 PUT_WORD(&result_buffer[8], GOOD);
12159                                 if (Info != GOOD)
12160                                         break;
12161                                 result = plci->saved_msg.info;
12162                                 for (i = 0; i <= result_buffer[0]; i++)
12163                                         result[i] = result_buffer[i];
12164                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12165                                 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12166                                 if (plci_b == NULL)
12167                                         break;
12168                                 li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12169                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12170                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12171                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12172                         }
12173                         else
12174                         {
12175                                 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12176                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12177                                 {
12178                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12179                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12180                                         Info = _WRONG_MESSAGE_FORMAT;
12181                                         break;
12182                                 }
12183                                 li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12184                                 Info = li_check_main_plci(Id, plci);
12185                                 result_buffer[0] = 7;
12186                                 result_buffer[3] = 4;
12187                                 PUT_WORD(&result_buffer[4], Info);
12188                                 result_buffer[6] = 0;
12189                                 if (Info != GOOD)
12190                                         break;
12191                                 result = plci->saved_msg.info;
12192                                 for (i = 0; i <= result_buffer[0]; i++)
12193                                         result[i] = result_buffer[i];
12194                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12195                                 participant_parms_pos = 0;
12196                                 result_pos = 7;
12197                                 li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12198                                 while (participant_parms_pos < li_req_parms[1].length)
12199                                 {
12200                                         result[result_pos] = 6;
12201                                         result_pos += 7;
12202                                         PUT_DWORD(&result[result_pos - 6], 0);
12203                                         PUT_WORD(&result[result_pos - 2], GOOD);
12204                                         if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12205                                                       (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12206                                         {
12207                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12208                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12209                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12210                                                 break;
12211                                         }
12212                                         if (api_parse(&li_participant_struct[0].info[1],
12213                                                       li_participant_struct[0].length, "dd", li_participant_parms))
12214                                         {
12215                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12216                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12217                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12218                                                 break;
12219                                         }
12220                                         plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12221                                         li_flags = GET_DWORD(li_participant_parms[1].info);
12222                                         PUT_DWORD(&result[result_pos - 6], plci_b_id);
12223                                         if (sizeof(result) - result_pos < 7)
12224                                         {
12225                                                 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12226                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12227                                                 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12228                                                 break;
12229                                         }
12230                                         plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12231                                         if (plci_b != NULL)
12232                                         {
12233                                                 li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12234                                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12235                                                         ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12236                                                                       LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12237                                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12238                                         }
12239                                         participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12240                                                                        (&li_req_parms[1].info[1]));
12241                                 }
12242                                 result[0] = (byte)(result_pos - 1);
12243                                 result[3] = (byte)(result_pos - 4);
12244                                 result[6] = (byte)(result_pos - 7);
12245                                 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12246                                 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12247                                     || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12248                                 {
12249                                         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12250                                         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12251                                 }
12252                                 else
12253                                         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12254                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12255                         }
12256                         mixer_calculate_coefs(a);
12257                         plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12258                         mixer_notify_update(plci, true);
12259                         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12260                               "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12261                         plci->command = 0;
12262                         plci->li_cmd = GET_WORD(li_parms[0].info);
12263                         start_internal_command(Id, plci, mixer_command);
12264                         return (false);
12265
12266                 case LI_REQ_DISCONNECT:
12267                         if (li_parms[1].length == 4)
12268                         {
12269                                 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12270                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12271                                 {
12272                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12273                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12274                                         Info = _WRONG_MESSAGE_FORMAT;
12275                                         break;
12276                                 }
12277                                 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12278                                 Info = li_check_main_plci(Id, plci);
12279                                 result_buffer[0] = 9;
12280                                 result_buffer[3] = 6;
12281                                 PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12282                                 PUT_WORD(&result_buffer[8], GOOD);
12283                                 if (Info != GOOD)
12284                                         break;
12285                                 result = plci->saved_msg.info;
12286                                 for (i = 0; i <= result_buffer[0]; i++)
12287                                         result[i] = result_buffer[i];
12288                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12289                                 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12290                                 if (plci_b == NULL)
12291                                         break;
12292                                 li_update_connect(Id, a, plci, plci_b_id, false, 0);
12293                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12294                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12295                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12296                         }
12297                         else
12298                         {
12299                                 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12300                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12301                                 {
12302                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12303                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12304                                         Info = _WRONG_MESSAGE_FORMAT;
12305                                         break;
12306                                 }
12307                                 Info = li_check_main_plci(Id, plci);
12308                                 result_buffer[0] = 7;
12309                                 result_buffer[3] = 4;
12310                                 PUT_WORD(&result_buffer[4], Info);
12311                                 result_buffer[6] = 0;
12312                                 if (Info != GOOD)
12313                                         break;
12314                                 result = plci->saved_msg.info;
12315                                 for (i = 0; i <= result_buffer[0]; i++)
12316                                         result[i] = result_buffer[i];
12317                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12318                                 participant_parms_pos = 0;
12319                                 result_pos = 7;
12320                                 while (participant_parms_pos < li_req_parms[0].length)
12321                                 {
12322                                         result[result_pos] = 6;
12323                                         result_pos += 7;
12324                                         PUT_DWORD(&result[result_pos - 6], 0);
12325                                         PUT_WORD(&result[result_pos - 2], GOOD);
12326                                         if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12327                                                       (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12328                                         {
12329                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12330                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12331                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12332                                                 break;
12333                                         }
12334                                         if (api_parse(&li_participant_struct[0].info[1],
12335                                                       li_participant_struct[0].length, "d", li_participant_parms))
12336                                         {
12337                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12338                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12339                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12340                                                 break;
12341                                         }
12342                                         plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12343                                         PUT_DWORD(&result[result_pos - 6], plci_b_id);
12344                                         if (sizeof(result) - result_pos < 7)
12345                                         {
12346                                                 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12347                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12348                                                 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12349                                                 break;
12350                                         }
12351                                         plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12352                                         if (plci_b != NULL)
12353                                         {
12354                                                 li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12355                                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12356                                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12357                                         }
12358                                         participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12359                                                                        (&li_req_parms[0].info[1]));
12360                                 }
12361                                 result[0] = (byte)(result_pos - 1);
12362                                 result[3] = (byte)(result_pos - 4);
12363                                 result[6] = (byte)(result_pos - 7);
12364                                 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12365                                 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12366                                     || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12367                                 {
12368                                         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12369                                         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12370                                 }
12371                                 else
12372                                         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12373                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12374                         }
12375                         mixer_calculate_coefs(a);
12376                         plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12377                         mixer_notify_update(plci, true);
12378                         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12379                               "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12380                         plci->command = 0;
12381                         plci->li_cmd = GET_WORD(li_parms[0].info);
12382                         start_internal_command(Id, plci, mixer_command);
12383                         return (false);
12384
12385                 case LI_REQ_SILENT_UPDATE:
12386                         if (!plci || !plci->State
12387                             || !plci->NL.Id || plci->nl_remove_id
12388                             || (plci->li_bchannel_id == 0)
12389                             || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12390                         {
12391                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12392                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12393                                 return (false);
12394                         }
12395                         plci_b_write_pos = plci->li_plci_b_write_pos;
12396                         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12397                              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12398                         {
12399                                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12400                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12401                                 return (false);
12402                         }
12403                         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12404                         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12405                             || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12406                         {
12407                                 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12408                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12409                         }
12410                         else
12411                                 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12412                         plci->li_plci_b_write_pos = plci_b_write_pos;
12413                         plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12414                         plci->command = 0;
12415                         plci->li_cmd = GET_WORD(li_parms[0].info);
12416                         start_internal_command(Id, plci, mixer_command);
12417                         return (false);
12418
12419                 default:
12420                         dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12421                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12422                         Info = _FACILITY_NOT_SUPPORTED;
12423                 }
12424         }
12425         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12426               "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12427         return (false);
12428 }
12429
12430
12431 static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12432 {
12433         dword d;
12434         byte result[12];
12435
12436         dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12437                         UnMapId(Id), (char *)(FILE_), __LINE__));
12438
12439         if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12440         {
12441                 do
12442                 {
12443                         d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12444                         if (!(d & LI_PLCI_B_SKIP_FLAG))
12445                         {
12446                                 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12447                                 {
12448                                         if (d & LI_PLCI_B_DISC_FLAG)
12449                                         {
12450                                                 result[0] = 5;
12451                                                 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12452                                                 result[3] = 2;
12453                                                 PUT_WORD(&result[4], _LI_USER_INITIATED);
12454                                         }
12455                                         else
12456                                         {
12457                                                 result[0] = 7;
12458                                                 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12459                                                 result[3] = 4;
12460                                                 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12461                                         }
12462                                 }
12463                                 else
12464                                 {
12465                                         if (d & LI_PLCI_B_DISC_FLAG)
12466                                         {
12467                                                 result[0] = 9;
12468                                                 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12469                                                 result[3] = 6;
12470                                                 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12471                                                 PUT_WORD(&result[8], _LI_USER_INITIATED);
12472                                         }
12473                                         else
12474                                         {
12475                                                 result[0] = 7;
12476                                                 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12477                                                 result[3] = 4;
12478                                                 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12479                                         }
12480                                 }
12481                                 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12482                                       "ws", SELECTOR_LINE_INTERCONNECT, result);
12483                         }
12484                         plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12485                                 0 : plci->li_plci_b_read_pos + 1;
12486                 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12487         }
12488 }
12489
12490
12491 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12492 {
12493         word i, j, ch;
12494         struct xconnect_transfer_address_s s,   *p;
12495         DIVA_CAPI_ADAPTER *a;
12496
12497         dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12498                         UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12499
12500         a = plci->adapter;
12501         i = 1;
12502         for (i = 1; i < length; i += 16)
12503         {
12504                 s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12505                 s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12506                 s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12507                 ch = msg[i + 12] | (msg[i + 13] << 8);
12508                 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12509                 if (!a->li_pri && (plci->li_bchannel_id == 2))
12510                         j = 1 - j;
12511                 j += a->li_base;
12512                 if (ch & XCONNECT_CHANNEL_PORT_PC)
12513                         p = &(li_config_table[j].send_pc);
12514                 else
12515                         p = &(li_config_table[j].send_b);
12516                 p->card_address.low = s.card_address.low;
12517                 p->card_address.high = s.card_address.high;
12518                 p->offset = s.offset;
12519                 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12520         }
12521         if (plci->internal_command_queue[0]
12522             && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12523                 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12524                 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12525         {
12526                 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12527                 if (!plci->internal_command)
12528                         next_internal_command(Id, plci);
12529         }
12530         mixer_notify_update(plci, true);
12531 }
12532
12533
12534 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12535 {
12536
12537         dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12538                         UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12539
12540 }
12541
12542
12543 static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12544 {
12545         word plci_b_write_pos;
12546
12547         plci_b_write_pos = plci->li_plci_b_write_pos;
12548         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12549              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12550         {
12551                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12552                                 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12553                                 (char *)(FILE_), __LINE__));
12554                 return (false);
12555         }
12556         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12557         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12558         plci->li_plci_b_write_pos = plci_b_write_pos;
12559         return (true);
12560 }
12561
12562
12563 static void mixer_remove(PLCI *plci)
12564 {
12565         DIVA_CAPI_ADAPTER *a;
12566         PLCI *notify_plci;
12567         dword plci_b_id;
12568         word i, j;
12569
12570         dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12571                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12572                         (char *)(FILE_), __LINE__));
12573
12574         a = plci->adapter;
12575         plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12576         if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12577         {
12578                 if ((plci->li_bchannel_id != 0)
12579                     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12580                 {
12581                         i = a->li_base + (plci->li_bchannel_id - 1);
12582                         if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12583                         {
12584                                 for (j = 0; j < li_total_channels; j++)
12585                                 {
12586                                         if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12587                                             || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12588                                         {
12589                                                 notify_plci = li_config_table[j].plci;
12590                                                 if ((notify_plci != NULL)
12591                                                     && (notify_plci != plci)
12592                                                     && (notify_plci->appl != NULL)
12593                                                     && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12594                                                     && (notify_plci->State)
12595                                                     && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12596                                                 {
12597                                                         mixer_notify_source_removed(notify_plci, plci_b_id);
12598                                                 }
12599                                         }
12600                                 }
12601                                 mixer_clear_config(plci);
12602                                 mixer_calculate_coefs(a);
12603                                 mixer_notify_update(plci, true);
12604                         }
12605                         li_config_table[i].plci = NULL;
12606                         plci->li_bchannel_id = 0;
12607                 }
12608         }
12609 }
12610
12611
12612 /*------------------------------------------------------------------*/
12613 /* Echo canceller facilities                                        */
12614 /*------------------------------------------------------------------*/
12615
12616
12617 static void ec_write_parameters(PLCI *plci)
12618 {
12619         word w;
12620         byte parameter_buffer[6];
12621
12622         dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12623                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12624                         (char *)(FILE_), __LINE__));
12625
12626         parameter_buffer[0] = 5;
12627         parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12628         PUT_WORD(&parameter_buffer[2], plci->ec_idi_options);
12629         plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12630         w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12631         PUT_WORD(&parameter_buffer[4], w);
12632         add_p(plci, FTY, parameter_buffer);
12633         sig_req(plci, TEL_CTRL, 0);
12634         send_req(plci);
12635 }
12636
12637
12638 static void ec_clear_config(PLCI *plci)
12639 {
12640
12641         dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12642                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12643                         (char *)(FILE_), __LINE__));
12644
12645         plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12646                 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12647         plci->ec_tail_length = 0;
12648 }
12649
12650
12651 static void ec_prepare_switch(dword Id, PLCI *plci)
12652 {
12653
12654         dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12655                         UnMapId(Id), (char *)(FILE_), __LINE__));
12656
12657 }
12658
12659
12660 static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12661 {
12662
12663         dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12664                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12665
12666         return (GOOD);
12667 }
12668
12669
12670 static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12671 {
12672         word Info;
12673
12674         dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12675                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12676
12677         Info = GOOD;
12678         if (plci->B1_facilities & B1_FACILITY_EC)
12679         {
12680                 switch (plci->adjust_b_state)
12681                 {
12682                 case ADJUST_B_RESTORE_EC_1:
12683                         plci->internal_command = plci->adjust_b_command;
12684                         if (plci->sig_req)
12685                         {
12686                                 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12687                                 break;
12688                         }
12689                         ec_write_parameters(plci);
12690                         plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12691                         break;
12692                 case ADJUST_B_RESTORE_EC_2:
12693                         if ((Rc != OK) && (Rc != OK_FC))
12694                         {
12695                                 dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12696                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12697                                 Info = _WRONG_STATE;
12698                                 break;
12699                         }
12700                         break;
12701                 }
12702         }
12703         return (Info);
12704 }
12705
12706
12707 static void ec_command(dword Id, PLCI *plci, byte Rc)
12708 {
12709         word internal_command, Info;
12710         byte result[8];
12711
12712         dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12713                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12714                         plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12715
12716         Info = GOOD;
12717         if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12718         {
12719                 result[0] = 2;
12720                 PUT_WORD(&result[1], EC_SUCCESS);
12721         }
12722         else
12723         {
12724                 result[0] = 5;
12725                 PUT_WORD(&result[1], plci->ec_cmd);
12726                 result[3] = 2;
12727                 PUT_WORD(&result[4], GOOD);
12728         }
12729         internal_command = plci->internal_command;
12730         plci->internal_command = 0;
12731         switch (plci->ec_cmd)
12732         {
12733         case EC_ENABLE_OPERATION:
12734         case EC_FREEZE_COEFFICIENTS:
12735         case EC_RESUME_COEFFICIENT_UPDATE:
12736         case EC_RESET_COEFFICIENTS:
12737                 switch (internal_command)
12738                 {
12739                 default:
12740                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12741                                                                   B1_FACILITY_EC), EC_COMMAND_1);
12742                 case EC_COMMAND_1:
12743                         if (adjust_b_process(Id, plci, Rc) != GOOD)
12744                         {
12745                                 dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12746                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12747                                 Info = _FACILITY_NOT_SUPPORTED;
12748                                 break;
12749                         }
12750                         if (plci->internal_command)
12751                                 return;
12752                 case EC_COMMAND_2:
12753                         if (plci->sig_req)
12754                         {
12755                                 plci->internal_command = EC_COMMAND_2;
12756                                 return;
12757                         }
12758                         plci->internal_command = EC_COMMAND_3;
12759                         ec_write_parameters(plci);
12760                         return;
12761                 case EC_COMMAND_3:
12762                         if ((Rc != OK) && (Rc != OK_FC))
12763                         {
12764                                 dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12765                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12766                                 Info = _FACILITY_NOT_SUPPORTED;
12767                                 break;
12768                         }
12769                         break;
12770                 }
12771                 break;
12772
12773         case EC_DISABLE_OPERATION:
12774                 switch (internal_command)
12775                 {
12776                 default:
12777                 case EC_COMMAND_1:
12778                         if (plci->B1_facilities & B1_FACILITY_EC)
12779                         {
12780                                 if (plci->sig_req)
12781                                 {
12782                                         plci->internal_command = EC_COMMAND_1;
12783                                         return;
12784                                 }
12785                                 plci->internal_command = EC_COMMAND_2;
12786                                 ec_write_parameters(plci);
12787                                 return;
12788                         }
12789                         Rc = OK;
12790                 case EC_COMMAND_2:
12791                         if ((Rc != OK) && (Rc != OK_FC))
12792                         {
12793                                 dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12794                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12795                                 Info = _FACILITY_NOT_SUPPORTED;
12796                                 break;
12797                         }
12798                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12799                                                                   ~B1_FACILITY_EC), EC_COMMAND_3);
12800                 case EC_COMMAND_3:
12801                         if (adjust_b_process(Id, plci, Rc) != GOOD)
12802                         {
12803                                 dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12804                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12805                                 Info = _FACILITY_NOT_SUPPORTED;
12806                                 break;
12807                         }
12808                         if (plci->internal_command)
12809                                 return;
12810                         break;
12811                 }
12812                 break;
12813         }
12814         sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12815               "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12816               PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12817 }
12818
12819
12820 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
12821 {
12822         word Info;
12823         word opt;
12824         API_PARSE ec_parms[3];
12825         byte result[16];
12826
12827         dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12828                         UnMapId(Id), (char *)(FILE_), __LINE__));
12829
12830         Info = GOOD;
12831         result[0] = 0;
12832         if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12833         {
12834                 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12835                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12836                 Info = _FACILITY_NOT_SUPPORTED;
12837         }
12838         else
12839         {
12840                 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12841                 {
12842                         if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12843                         {
12844                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12845                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12846                                 Info = _WRONG_MESSAGE_FORMAT;
12847                         }
12848                         else
12849                         {
12850                                 if (plci == NULL)
12851                                 {
12852                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12853                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12854                                         Info = _WRONG_IDENTIFIER;
12855                                 }
12856                                 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12857                                 {
12858                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12859                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12860                                         Info = _WRONG_STATE;
12861                                 }
12862                                 else
12863                                 {
12864                                         plci->command = 0;
12865                                         plci->ec_cmd = GET_WORD(ec_parms[0].info);
12866                                         plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12867                                         result[0] = 2;
12868                                         PUT_WORD(&result[1], EC_SUCCESS);
12869                                         if (msg[1].length >= 4)
12870                                         {
12871                                                 opt = GET_WORD(&ec_parms[0].info[2]);
12872                                                 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12873                                                                           LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12874                                                 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12875                                                         plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12876                                                 if (opt & EC_DETECT_DISABLE_TONE)
12877                                                         plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12878                                                 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12879                                                         plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12880                                                 if (msg[1].length >= 6)
12881                                                 {
12882                                                         plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12883                                                 }
12884                                         }
12885                                         switch (plci->ec_cmd)
12886                                         {
12887                                         case EC_ENABLE_OPERATION:
12888                                                 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12889                                                 start_internal_command(Id, plci, ec_command);
12890                                                 return (false);
12891
12892                                         case EC_DISABLE_OPERATION:
12893                                                 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12894                                                         LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12895                                                         LEC_RESET_COEFFICIENTS;
12896                                                 start_internal_command(Id, plci, ec_command);
12897                                                 return (false);
12898
12899                                         case EC_FREEZE_COEFFICIENTS:
12900                                                 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12901                                                 start_internal_command(Id, plci, ec_command);
12902                                                 return (false);
12903
12904                                         case EC_RESUME_COEFFICIENT_UPDATE:
12905                                                 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12906                                                 start_internal_command(Id, plci, ec_command);
12907                                                 return (false);
12908
12909                                         case EC_RESET_COEFFICIENTS:
12910                                                 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12911                                                 start_internal_command(Id, plci, ec_command);
12912                                                 return (false);
12913
12914                                         default:
12915                                                 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12916                                                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12917                                                 PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12918                                         }
12919                                 }
12920                         }
12921                 }
12922                 else
12923                 {
12924                         if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12925                         {
12926                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12927                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12928                                 Info = _WRONG_MESSAGE_FORMAT;
12929                         }
12930                         else
12931                         {
12932                                 if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12933                                 {
12934                                         result[0] = 11;
12935                                         PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12936                                         result[3] = 8;
12937                                         PUT_WORD(&result[4], GOOD);
12938                                         PUT_WORD(&result[6], 0x0007);
12939                                         PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12940                                         PUT_WORD(&result[10], 0);
12941                                 }
12942                                 else if (plci == NULL)
12943                                 {
12944                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12945                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12946                                         Info = _WRONG_IDENTIFIER;
12947                                 }
12948                                 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12949                                 {
12950                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12951                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12952                                         Info = _WRONG_STATE;
12953                                 }
12954                                 else
12955                                 {
12956                                         plci->command = 0;
12957                                         plci->ec_cmd = GET_WORD(ec_parms[0].info);
12958                                         plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12959                                         result[0] = 5;
12960                                         PUT_WORD(&result[1], plci->ec_cmd);
12961                                         result[3] = 2;
12962                                         PUT_WORD(&result[4], GOOD);
12963                                         plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12964                                                                   LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12965                                         plci->ec_tail_length = 0;
12966                                         if (ec_parms[1].length >= 2)
12967                                         {
12968                                                 opt = GET_WORD(&ec_parms[1].info[1]);
12969                                                 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12970                                                         plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12971                                                 if (opt & EC_DETECT_DISABLE_TONE)
12972                                                         plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12973                                                 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12974                                                         plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12975                                                 if (ec_parms[1].length >= 4)
12976                                                 {
12977                                                         plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12978                                                 }
12979                                         }
12980                                         switch (plci->ec_cmd)
12981                                         {
12982                                         case EC_ENABLE_OPERATION:
12983                                                 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12984                                                 start_internal_command(Id, plci, ec_command);
12985                                                 return (false);
12986
12987                                         case EC_DISABLE_OPERATION:
12988                                                 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12989                                                         LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12990                                                         LEC_RESET_COEFFICIENTS;
12991                                                 start_internal_command(Id, plci, ec_command);
12992                                                 return (false);
12993
12994                                         default:
12995                                                 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12996                                                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12997                                                 PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12998                                         }
12999                                 }
13000                         }
13001                 }
13002         }
13003         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13004               "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13005               PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13006         return (false);
13007 }
13008
13009
13010 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
13011 {
13012         byte result[8];
13013
13014         dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
13015                         UnMapId(Id), (char *)(FILE_), __LINE__));
13016
13017         if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13018         {
13019                 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13020                 {
13021                         result[0] = 2;
13022                         PUT_WORD(&result[1], 0);
13023                         switch (msg[1])
13024                         {
13025                         case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13026                                 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13027                                 break;
13028                         case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13029                                 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13030                                 break;
13031                         case LEC_DISABLE_RELEASED:
13032                                 PUT_WORD(&result[1], EC_BYPASS_RELEASED);
13033                                 break;
13034                         }
13035                 }
13036                 else
13037                 {
13038                         result[0] = 5;
13039                         PUT_WORD(&result[1], EC_BYPASS_INDICATION);
13040                         result[3] = 2;
13041                         PUT_WORD(&result[4], 0);
13042                         switch (msg[1])
13043                         {
13044                         case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13045                                 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13046                                 break;
13047                         case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13048                                 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13049                                 break;
13050                         case LEC_DISABLE_RELEASED:
13051                                 PUT_WORD(&result[4], EC_BYPASS_RELEASED);
13052                                 break;
13053                         }
13054                 }
13055                 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13056                       PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13057         }
13058 }
13059
13060
13061
13062 /*------------------------------------------------------------------*/
13063 /* Advanced voice                                                   */
13064 /*------------------------------------------------------------------*/
13065
13066 static void adv_voice_write_coefs(PLCI *plci, word write_command)
13067 {
13068         DIVA_CAPI_ADAPTER *a;
13069         word i;
13070         byte *p;
13071
13072         word w, n, j, k;
13073         byte ch_map[MIXER_CHANNELS_BRI];
13074
13075         byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13076
13077         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
13078                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13079                         (char *)(FILE_), __LINE__, write_command));
13080
13081         a = plci->adapter;
13082         p = coef_buffer + 1;
13083         *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13084         i = 0;
13085         while (i + sizeof(word) <= a->adv_voice_coef_length)
13086         {
13087                 PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
13088                 p += 2;
13089                 i += 2;
13090         }
13091         while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13092         {
13093                 PUT_WORD(p, 0x8000);
13094                 p += 2;
13095                 i += 2;
13096         }
13097
13098         if (!a->li_pri && (plci->li_bchannel_id == 0))
13099         {
13100                 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13101                 {
13102                         plci->li_bchannel_id = 1;
13103                         li_config_table[a->li_base].plci = plci;
13104                         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13105                                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13106                                         (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13107                 }
13108                 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13109                 {
13110                         plci->li_bchannel_id = 2;
13111                         li_config_table[a->li_base + 1].plci = plci;
13112                         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13113                                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13114                                         (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13115                 }
13116         }
13117         if (!a->li_pri && (plci->li_bchannel_id != 0)
13118             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13119         {
13120                 i = a->li_base + (plci->li_bchannel_id - 1);
13121                 switch (write_command)
13122                 {
13123                 case ADV_VOICE_WRITE_ACTIVATION:
13124                         j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13125                         k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13126                         if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13127                         {
13128                                 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13129                                 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13130                         }
13131                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13132                         {
13133                                 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13134                                 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13135                                 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13136                                 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13137                         }
13138                         mixer_calculate_coefs(a);
13139                         li_config_table[i].curchnl = li_config_table[i].channel;
13140                         li_config_table[j].curchnl = li_config_table[j].channel;
13141                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13142                                 li_config_table[k].curchnl = li_config_table[k].channel;
13143                         break;
13144
13145                 case ADV_VOICE_WRITE_DEACTIVATION:
13146                         for (j = 0; j < li_total_channels; j++)
13147                         {
13148                                 li_config_table[i].flag_table[j] = 0;
13149                                 li_config_table[j].flag_table[i] = 0;
13150                         }
13151                         k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13152                         for (j = 0; j < li_total_channels; j++)
13153                         {
13154                                 li_config_table[k].flag_table[j] = 0;
13155                                 li_config_table[j].flag_table[k] = 0;
13156                         }
13157                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13158                         {
13159                                 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13160                                 for (j = 0; j < li_total_channels; j++)
13161                                 {
13162                                         li_config_table[k].flag_table[j] = 0;
13163                                         li_config_table[j].flag_table[k] = 0;
13164                                 }
13165                         }
13166                         mixer_calculate_coefs(a);
13167                         break;
13168                 }
13169                 if (plci->B1_facilities & B1_FACILITY_MIXER)
13170                 {
13171                         w = 0;
13172                         if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13173                                 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13174                         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13175                                 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13176                         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13177                                 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13178                         *(p++) = (byte) w;
13179                         *(p++) = (byte)(w >> 8);
13180                         for (j = 0; j < sizeof(ch_map); j += 2)
13181                         {
13182                                 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13183                                 ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13184                         }
13185                         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13186                         {
13187                                 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13188                                 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13189                                 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13190                                 {
13191                                         *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13192                                         w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13193                                         li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13194                                 }
13195                                 else
13196                                 {
13197                                         *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13198                                                 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13199                                 }
13200                         }
13201                 }
13202                 else
13203                 {
13204                         for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13205                                 *(p++) = a->adv_voice_coef_buffer[i];
13206                 }
13207         }
13208         else
13209
13210         {
13211                 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13212                         *(p++) = a->adv_voice_coef_buffer[i];
13213         }
13214         coef_buffer[0] = (p - coef_buffer) - 1;
13215         add_p(plci, FTY, coef_buffer);
13216         sig_req(plci, TEL_CTRL, 0);
13217         send_req(plci);
13218 }
13219
13220
13221 static void adv_voice_clear_config(PLCI *plci)
13222 {
13223         DIVA_CAPI_ADAPTER *a;
13224
13225         word i, j;
13226
13227
13228         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13229                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13230                         (char *)(FILE_), __LINE__));
13231
13232         a = plci->adapter;
13233         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13234         {
13235                 a->adv_voice_coef_length = 0;
13236
13237                 if (!a->li_pri && (plci->li_bchannel_id != 0)
13238                     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13239                 {
13240                         i = a->li_base + (plci->li_bchannel_id - 1);
13241                         li_config_table[i].curchnl = 0;
13242                         li_config_table[i].channel = 0;
13243                         li_config_table[i].chflags = 0;
13244                         for (j = 0; j < li_total_channels; j++)
13245                         {
13246                                 li_config_table[i].flag_table[j] = 0;
13247                                 li_config_table[j].flag_table[i] = 0;
13248                                 li_config_table[i].coef_table[j] = 0;
13249                                 li_config_table[j].coef_table[i] = 0;
13250                         }
13251                         li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13252                         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13253                         li_config_table[i].curchnl = 0;
13254                         li_config_table[i].channel = 0;
13255                         li_config_table[i].chflags = 0;
13256                         for (j = 0; j < li_total_channels; j++)
13257                         {
13258                                 li_config_table[i].flag_table[j] = 0;
13259                                 li_config_table[j].flag_table[i] = 0;
13260                                 li_config_table[i].coef_table[j] = 0;
13261                                 li_config_table[j].coef_table[i] = 0;
13262                         }
13263                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13264                         {
13265                                 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13266                                 li_config_table[i].curchnl = 0;
13267                                 li_config_table[i].channel = 0;
13268                                 li_config_table[i].chflags = 0;
13269                                 for (j = 0; j < li_total_channels; j++)
13270                                 {
13271                                         li_config_table[i].flag_table[j] = 0;
13272                                         li_config_table[j].flag_table[i] = 0;
13273                                         li_config_table[i].coef_table[j] = 0;
13274                                         li_config_table[j].coef_table[i] = 0;
13275                                 }
13276                         }
13277                 }
13278
13279         }
13280 }
13281
13282
13283 static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13284 {
13285
13286         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13287                         UnMapId(Id), (char *)(FILE_), __LINE__));
13288
13289 }
13290
13291
13292 static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13293 {
13294
13295         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13296                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13297
13298         return (GOOD);
13299 }
13300
13301
13302 static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13303 {
13304         DIVA_CAPI_ADAPTER *a;
13305         word Info;
13306
13307         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13308                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13309
13310         Info = GOOD;
13311         a = plci->adapter;
13312         if ((plci->B1_facilities & B1_FACILITY_VOICE)
13313             && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13314         {
13315                 switch (plci->adjust_b_state)
13316                 {
13317                 case ADJUST_B_RESTORE_VOICE_1:
13318                         plci->internal_command = plci->adjust_b_command;
13319                         if (plci->sig_req)
13320                         {
13321                                 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13322                                 break;
13323                         }
13324                         adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13325                         plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13326                         break;
13327                 case ADJUST_B_RESTORE_VOICE_2:
13328                         if ((Rc != OK) && (Rc != OK_FC))
13329                         {
13330                                 dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13331                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13332                                 Info = _WRONG_STATE;
13333                                 break;
13334                         }
13335                         break;
13336                 }
13337         }
13338         return (Info);
13339 }
13340
13341
13342
13343
13344 /*------------------------------------------------------------------*/
13345 /* B1 resource switching                                            */
13346 /*------------------------------------------------------------------*/
13347
13348 static byte b1_facilities_table[] =
13349 {
13350         0x00,  /* 0  No bchannel resources      */
13351         0x00,  /* 1  Codec (automatic law)      */
13352         0x00,  /* 2  Codec (A-law)              */
13353         0x00,  /* 3  Codec (y-law)              */
13354         0x00,  /* 4  HDLC for X.21              */
13355         0x00,  /* 5  HDLC                       */
13356         0x00,  /* 6  External Device 0          */
13357         0x00,  /* 7  External Device 1          */
13358         0x00,  /* 8  HDLC 56k                   */
13359         0x00,  /* 9  Transparent                */
13360         0x00,  /* 10 Loopback to network        */
13361         0x00,  /* 11 Test pattern to net        */
13362         0x00,  /* 12 Rate adaptation sync       */
13363         0x00,  /* 13 Rate adaptation async      */
13364         0x00,  /* 14 R-Interface                */
13365         0x00,  /* 15 HDLC 128k leased line      */
13366         0x00,  /* 16 FAX                        */
13367         0x00,  /* 17 Modem async                */
13368         0x00,  /* 18 Modem sync HDLC            */
13369         0x00,  /* 19 V.110 async HDLC           */
13370         0x12,  /* 20 Adv voice (Trans,mixer)    */
13371         0x00,  /* 21 Codec connected to IC      */
13372         0x0c,  /* 22 Trans,DTMF                 */
13373         0x1e,  /* 23 Trans,DTMF+mixer           */
13374         0x1f,  /* 24 Trans,DTMF+mixer+local     */
13375         0x13,  /* 25 Trans,mixer+local          */
13376         0x12,  /* 26 HDLC,mixer                 */
13377         0x12,  /* 27 HDLC 56k,mixer             */
13378         0x2c,  /* 28 Trans,LEC+DTMF             */
13379         0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13380         0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13381         0x2c,  /* 31 RTP,LEC+DTMF               */
13382         0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13383         0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13384         0x00,  /* 34 Signaling task             */
13385         0x00,  /* 35 PIAFS                      */
13386         0x0c,  /* 36 Trans,DTMF+TONE            */
13387         0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13388         0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13389 };
13390
13391
13392 static word get_b1_facilities(PLCI *plci, byte b1_resource)
13393 {
13394         word b1_facilities;
13395
13396         b1_facilities = b1_facilities_table[b1_resource];
13397         if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13398         {
13399
13400                 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13401                       || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13402
13403                 {
13404                         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13405                                 b1_facilities |= B1_FACILITY_DTMFX;
13406                         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13407                                 b1_facilities |= B1_FACILITY_DTMFR;
13408                 }
13409         }
13410         if ((b1_resource == 17) || (b1_resource == 18))
13411         {
13412                 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13413                         b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13414         }
13415 /*
13416   dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13417   (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13418   (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13419 */
13420         return (b1_facilities);
13421 }
13422
13423
13424 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13425 {
13426         byte b;
13427
13428         switch (b1_resource)
13429         {
13430         case 5:
13431         case 26:
13432                 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13433                         b = 26;
13434                 else
13435                         b = 5;
13436                 break;
13437
13438         case 8:
13439         case 27:
13440                 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13441                         b = 27;
13442                 else
13443                         b = 8;
13444                 break;
13445
13446         case 9:
13447         case 20:
13448         case 22:
13449         case 23:
13450         case 24:
13451         case 25:
13452         case 28:
13453         case 29:
13454         case 30:
13455         case 36:
13456         case 37:
13457         case 38:
13458                 if (b1_facilities & B1_FACILITY_EC)
13459                 {
13460                         if (b1_facilities & B1_FACILITY_LOCAL)
13461                                 b = 30;
13462                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13463                                 b = 29;
13464                         else
13465                                 b = 28;
13466                 }
13467
13468                 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13469                          && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13470                              || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13471                 {
13472                         if (b1_facilities & B1_FACILITY_LOCAL)
13473                                 b = 38;
13474                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13475                                 b = 37;
13476                         else
13477                                 b = 36;
13478                 }
13479
13480                 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13481                           && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13482                          || ((b1_facilities & B1_FACILITY_DTMFR)
13483                              && ((b1_facilities & B1_FACILITY_MIXER)
13484                                  || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13485                          || ((b1_facilities & B1_FACILITY_DTMFX)
13486                              && ((b1_facilities & B1_FACILITY_MIXER)
13487                                  || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13488                 {
13489                         if (b1_facilities & B1_FACILITY_LOCAL)
13490                                 b = 24;
13491                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13492                                 b = 23;
13493                         else
13494                                 b = 22;
13495                 }
13496                 else
13497                 {
13498                         if (b1_facilities & B1_FACILITY_LOCAL)
13499                                 b = 25;
13500                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13501                                 b = 20;
13502                         else
13503                                 b = 9;
13504                 }
13505                 break;
13506
13507         case 31:
13508         case 32:
13509         case 33:
13510                 if (b1_facilities & B1_FACILITY_LOCAL)
13511                         b = 33;
13512                 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13513                         b = 32;
13514                 else
13515                         b = 31;
13516                 break;
13517
13518         default:
13519                 b = b1_resource;
13520         }
13521         dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13522                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13523                         (char *)(FILE_), __LINE__,
13524                         b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13525         return (b);
13526 }
13527
13528
13529 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13530 {
13531         word removed_facilities;
13532
13533         dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13534                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13535                         (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13536                         new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13537
13538         new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13539         removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13540
13541         if (removed_facilities & B1_FACILITY_EC)
13542                 ec_clear_config(plci);
13543
13544
13545         if (removed_facilities & B1_FACILITY_DTMFR)
13546         {
13547                 dtmf_rec_clear_config(plci);
13548                 dtmf_parameter_clear_config(plci);
13549         }
13550         if (removed_facilities & B1_FACILITY_DTMFX)
13551                 dtmf_send_clear_config(plci);
13552
13553
13554         if (removed_facilities & B1_FACILITY_MIXER)
13555                 mixer_clear_config(plci);
13556
13557         if (removed_facilities & B1_FACILITY_VOICE)
13558                 adv_voice_clear_config(plci);
13559         plci->B1_facilities = new_b1_facilities;
13560 }
13561
13562
13563 static void adjust_b_clear(PLCI *plci)
13564 {
13565
13566         dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13567                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13568                         (char *)(FILE_), __LINE__));
13569
13570         plci->adjust_b_restore = false;
13571 }
13572
13573
13574 static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13575 {
13576         word Info;
13577         byte b1_resource;
13578         NCCI *ncci_ptr;
13579         API_PARSE bp[2];
13580
13581         dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13582                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13583
13584         Info = GOOD;
13585         switch (plci->adjust_b_state)
13586         {
13587         case ADJUST_B_START:
13588                 if ((plci->adjust_b_parms_msg == NULL)
13589                     && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13590                     && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13591                                                  ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13592                 {
13593                         b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13594                                 0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13595                         if (b1_resource == plci->B1_resource)
13596                         {
13597                                 adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13598                                 break;
13599                         }
13600                         if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13601                         {
13602                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13603                                                 UnMapId(Id), (char *)(FILE_), __LINE__,
13604                                                 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13605                                 Info = _WRONG_STATE;
13606                                 break;
13607                         }
13608                 }
13609                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13610                 {
13611
13612                         mixer_prepare_switch(Id, plci);
13613
13614
13615                         dtmf_prepare_switch(Id, plci);
13616                         dtmf_parameter_prepare_switch(Id, plci);
13617
13618
13619                         ec_prepare_switch(Id, plci);
13620
13621                         adv_voice_prepare_switch(Id, plci);
13622                 }
13623                 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13624                 Rc = OK;
13625         case ADJUST_B_SAVE_MIXER_1:
13626                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13627                 {
13628
13629                         Info = mixer_save_config(Id, plci, Rc);
13630                         if ((Info != GOOD) || plci->internal_command)
13631                                 break;
13632
13633                 }
13634                 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13635                 Rc = OK;
13636         case ADJUST_B_SAVE_DTMF_1:
13637                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13638                 {
13639
13640                         Info = dtmf_save_config(Id, plci, Rc);
13641                         if ((Info != GOOD) || plci->internal_command)
13642                                 break;
13643
13644                 }
13645                 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13646         case ADJUST_B_REMOVE_L23_1:
13647                 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13648                     && plci->NL.Id && !plci->nl_remove_id)
13649                 {
13650                         plci->internal_command = plci->adjust_b_command;
13651                         if (plci->adjust_b_ncci != 0)
13652                         {
13653                                 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13654                                 while (ncci_ptr->data_pending)
13655                                 {
13656                                         plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13657                                         data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13658                                 }
13659                                 while (ncci_ptr->data_ack_pending)
13660                                         data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13661                         }
13662                         nl_req_ncci(plci, REMOVE,
13663                                     (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13664                         send_req(plci);
13665                         plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13666                         break;
13667                 }
13668                 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13669                 Rc = OK;
13670         case ADJUST_B_REMOVE_L23_2:
13671                 if ((Rc != OK) && (Rc != OK_FC))
13672                 {
13673                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13674                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13675                         Info = _WRONG_STATE;
13676                         break;
13677                 }
13678                 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13679                 {
13680                         if (plci_nl_busy(plci))
13681                         {
13682                                 plci->internal_command = plci->adjust_b_command;
13683                                 break;
13684                         }
13685                 }
13686                 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13687                 Rc = OK;
13688         case ADJUST_B_SAVE_EC_1:
13689                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13690                 {
13691
13692                         Info = ec_save_config(Id, plci, Rc);
13693                         if ((Info != GOOD) || plci->internal_command)
13694                                 break;
13695
13696                 }
13697                 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13698                 Rc = OK;
13699         case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13700                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13701                 {
13702
13703                         Info = dtmf_parameter_save_config(Id, plci, Rc);
13704                         if ((Info != GOOD) || plci->internal_command)
13705                                 break;
13706
13707                 }
13708                 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13709                 Rc = OK;
13710         case ADJUST_B_SAVE_VOICE_1:
13711                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13712                 {
13713                         Info = adv_voice_save_config(Id, plci, Rc);
13714                         if ((Info != GOOD) || plci->internal_command)
13715                                 break;
13716                 }
13717                 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13718         case ADJUST_B_SWITCH_L1_1:
13719                 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13720                 {
13721                         if (plci->sig_req)
13722                         {
13723                                 plci->internal_command = plci->adjust_b_command;
13724                                 break;
13725                         }
13726                         if (plci->adjust_b_parms_msg != NULL)
13727                                 api_load_msg(plci->adjust_b_parms_msg, bp);
13728                         else
13729                                 api_load_msg(&plci->B_protocol, bp);
13730                         Info = add_b1(plci, bp,
13731                                       (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13732                                       plci->adjust_b_facilities);
13733                         if (Info != GOOD)
13734                         {
13735                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13736                                                 UnMapId(Id), (char *)(FILE_), __LINE__,
13737                                                 plci->B1_resource, plci->adjust_b_facilities));
13738                                 break;
13739                         }
13740                         plci->internal_command = plci->adjust_b_command;
13741                         sig_req(plci, RESOURCES, 0);
13742                         send_req(plci);
13743                         plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13744                         break;
13745                 }
13746                 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13747                 Rc = OK;
13748         case ADJUST_B_SWITCH_L1_2:
13749                 if ((Rc != OK) && (Rc != OK_FC))
13750                 {
13751                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13752                                         UnMapId(Id), (char *)(FILE_), __LINE__,
13753                                         Rc, plci->B1_resource, plci->adjust_b_facilities));
13754                         Info = _WRONG_STATE;
13755                         break;
13756                 }
13757                 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13758                 Rc = OK;
13759         case ADJUST_B_RESTORE_VOICE_1:
13760         case ADJUST_B_RESTORE_VOICE_2:
13761                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13762                 {
13763                         Info = adv_voice_restore_config(Id, plci, Rc);
13764                         if ((Info != GOOD) || plci->internal_command)
13765                                 break;
13766                 }
13767                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13768                 Rc = OK;
13769         case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13770         case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13771                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13772                 {
13773
13774                         Info = dtmf_parameter_restore_config(Id, plci, Rc);
13775                         if ((Info != GOOD) || plci->internal_command)
13776                                 break;
13777
13778                 }
13779                 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13780                 Rc = OK;
13781         case ADJUST_B_RESTORE_EC_1:
13782         case ADJUST_B_RESTORE_EC_2:
13783                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13784                 {
13785
13786                         Info = ec_restore_config(Id, plci, Rc);
13787                         if ((Info != GOOD) || plci->internal_command)
13788                                 break;
13789
13790                 }
13791                 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13792         case ADJUST_B_ASSIGN_L23_1:
13793                 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13794                 {
13795                         if (plci_nl_busy(plci))
13796                         {
13797                                 plci->internal_command = plci->adjust_b_command;
13798                                 break;
13799                         }
13800                         if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13801                                 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13802                         if (plci->adjust_b_parms_msg != NULL)
13803                                 api_load_msg(plci->adjust_b_parms_msg, bp);
13804                         else
13805                                 api_load_msg(&plci->B_protocol, bp);
13806                         Info = add_b23(plci, bp);
13807                         if (Info != GOOD)
13808                         {
13809                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13810                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13811                                 break;
13812                         }
13813                         plci->internal_command = plci->adjust_b_command;
13814                         nl_req_ncci(plci, ASSIGN, 0);
13815                         send_req(plci);
13816                         plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13817                         break;
13818                 }
13819                 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13820                 Rc = ASSIGN_OK;
13821         case ADJUST_B_ASSIGN_L23_2:
13822                 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13823                 {
13824                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13825                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13826                         Info = _WRONG_STATE;
13827                         break;
13828                 }
13829                 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13830                 {
13831                         if (Rc != ASSIGN_OK)
13832                         {
13833                                 plci->internal_command = plci->adjust_b_command;
13834                                 break;
13835                         }
13836                 }
13837                 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13838                 {
13839                         plci->adjust_b_restore = true;
13840                         break;
13841                 }
13842                 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13843         case ADJUST_B_CONNECT_1:
13844                 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13845                 {
13846                         plci->internal_command = plci->adjust_b_command;
13847                         if (plci_nl_busy(plci))
13848                                 break;
13849                         nl_req_ncci(plci, N_CONNECT, 0);
13850                         send_req(plci);
13851                         plci->adjust_b_state = ADJUST_B_CONNECT_2;
13852                         break;
13853                 }
13854                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13855                 Rc = OK;
13856         case ADJUST_B_CONNECT_2:
13857         case ADJUST_B_CONNECT_3:
13858         case ADJUST_B_CONNECT_4:
13859                 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13860                 {
13861                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13862                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13863                         Info = _WRONG_STATE;
13864                         break;
13865                 }
13866                 if (Rc == OK)
13867                 {
13868                         if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13869                         {
13870                                 get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13871                                 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13872                         }
13873                         if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13874                                 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13875                         else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13876                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13877                 }
13878                 else if (Rc == 0)
13879                 {
13880                         if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13881                                 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13882                         else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13883                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13884                 }
13885                 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13886                 {
13887                         plci->internal_command = plci->adjust_b_command;
13888                         break;
13889                 }
13890                 Rc = OK;
13891         case ADJUST_B_RESTORE_DTMF_1:
13892         case ADJUST_B_RESTORE_DTMF_2:
13893                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13894                 {
13895
13896                         Info = dtmf_restore_config(Id, plci, Rc);
13897                         if ((Info != GOOD) || plci->internal_command)
13898                                 break;
13899
13900                 }
13901                 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13902                 Rc = OK;
13903         case ADJUST_B_RESTORE_MIXER_1:
13904         case ADJUST_B_RESTORE_MIXER_2:
13905         case ADJUST_B_RESTORE_MIXER_3:
13906         case ADJUST_B_RESTORE_MIXER_4:
13907         case ADJUST_B_RESTORE_MIXER_5:
13908         case ADJUST_B_RESTORE_MIXER_6:
13909         case ADJUST_B_RESTORE_MIXER_7:
13910                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13911                 {
13912
13913                         Info = mixer_restore_config(Id, plci, Rc);
13914                         if ((Info != GOOD) || plci->internal_command)
13915                                 break;
13916
13917                 }
13918                 plci->adjust_b_state = ADJUST_B_END;
13919         case ADJUST_B_END:
13920                 break;
13921         }
13922         return (Info);
13923 }
13924
13925
13926 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13927 {
13928
13929         dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13930                         UnMapId(Id), (char *)(FILE_), __LINE__,
13931                         plci->B1_resource, b1_facilities));
13932
13933         plci->adjust_b_parms_msg = bp_msg;
13934         plci->adjust_b_facilities = b1_facilities;
13935         plci->adjust_b_command = internal_command;
13936         plci->adjust_b_ncci = (word)(Id >> 16);
13937         if ((bp_msg == NULL) && (plci->B1_resource == 0))
13938                 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13939         else
13940                 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13941         plci->adjust_b_state = ADJUST_B_START;
13942         dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13943                         UnMapId(Id), (char *)(FILE_), __LINE__,
13944                         plci->B1_resource, b1_facilities));
13945 }
13946
13947
13948 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13949 {
13950         word internal_command;
13951
13952         dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13953                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13954
13955         internal_command = plci->internal_command;
13956         plci->internal_command = 0;
13957         switch (internal_command)
13958         {
13959         default:
13960                 plci->command = 0;
13961                 if (plci->req_in != 0)
13962                 {
13963                         plci->internal_command = ADJUST_B_RESTORE_1;
13964                         break;
13965                 }
13966                 Rc = OK;
13967         case ADJUST_B_RESTORE_1:
13968                 if ((Rc != OK) && (Rc != OK_FC))
13969                 {
13970                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13971                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13972                 }
13973                 plci->adjust_b_parms_msg = NULL;
13974                 plci->adjust_b_facilities = plci->B1_facilities;
13975                 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13976                 plci->adjust_b_ncci = (word)(Id >> 16);
13977                 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13978                 plci->adjust_b_state = ADJUST_B_START;
13979                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13980                                 UnMapId(Id), (char *)(FILE_), __LINE__));
13981         case ADJUST_B_RESTORE_2:
13982                 if (adjust_b_process(Id, plci, Rc) != GOOD)
13983                 {
13984                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13985                                         UnMapId(Id), (char *)(FILE_), __LINE__));
13986                 }
13987                 if (plci->internal_command)
13988                         break;
13989                 break;
13990         }
13991 }
13992
13993
13994 static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
13995 {
13996         word Info;
13997         word internal_command;
13998
13999         dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
14000                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14001
14002         Info = GOOD;
14003         internal_command = plci->internal_command;
14004         plci->internal_command = 0;
14005         switch (internal_command)
14006         {
14007         default:
14008                 plci->command = 0;
14009                 plci->adjust_b_parms_msg = NULL;
14010                 plci->adjust_b_facilities = plci->B1_facilities;
14011                 plci->adjust_b_command = RESET_B3_COMMAND_1;
14012                 plci->adjust_b_ncci = (word)(Id >> 16);
14013                 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14014                 plci->adjust_b_state = ADJUST_B_START;
14015                 dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
14016                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14017         case RESET_B3_COMMAND_1:
14018                 Info = adjust_b_process(Id, plci, Rc);
14019                 if (Info != GOOD)
14020                 {
14021                         dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
14022                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14023                         break;
14024                 }
14025                 if (plci->internal_command)
14026                         return;
14027                 break;
14028         }
14029 /*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14030         sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
14031 }
14032
14033
14034 static void select_b_command(dword Id, PLCI *plci, byte Rc)
14035 {
14036         word Info;
14037         word internal_command;
14038         byte esc_chi[3];
14039
14040         dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
14041                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14042
14043         Info = GOOD;
14044         internal_command = plci->internal_command;
14045         plci->internal_command = 0;
14046         switch (internal_command)
14047         {
14048         default:
14049                 plci->command = 0;
14050                 plci->adjust_b_parms_msg = &plci->saved_msg;
14051                 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14052                         plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14053                 else
14054                         plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14055                 plci->adjust_b_command = SELECT_B_COMMAND_1;
14056                 plci->adjust_b_ncci = (word)(Id >> 16);
14057                 if (plci->saved_msg.parms[0].length == 0)
14058                 {
14059                         plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14060                                 ADJUST_B_MODE_NO_RESOURCE;
14061                 }
14062                 else
14063                 {
14064                         plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14065                                 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14066                 }
14067                 plci->adjust_b_state = ADJUST_B_START;
14068                 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
14069                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14070         case SELECT_B_COMMAND_1:
14071                 Info = adjust_b_process(Id, plci, Rc);
14072                 if (Info != GOOD)
14073                 {
14074                         dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
14075                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14076                         break;
14077                 }
14078                 if (plci->internal_command)
14079                         return;
14080                 if (plci->tel == ADV_VOICE)
14081                 {
14082                         esc_chi[0] = 0x02;
14083                         esc_chi[1] = 0x18;
14084                         esc_chi[2] = plci->b_channel;
14085                         SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14086                 }
14087                 break;
14088         }
14089         sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14090 }
14091
14092
14093 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
14094 {
14095         word internal_command;
14096
14097         dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14098                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14099
14100         internal_command = plci->internal_command;
14101         plci->internal_command = 0;
14102         switch (internal_command)
14103         {
14104         default:
14105                 plci->command = 0;
14106         case FAX_CONNECT_ACK_COMMAND_1:
14107                 if (plci_nl_busy(plci))
14108                 {
14109                         plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14110                         return;
14111                 }
14112                 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14113                 plci->NData[0].P = plci->fax_connect_info_buffer;
14114                 plci->NData[0].PLength = plci->fax_connect_info_length;
14115                 plci->NL.X = plci->NData;
14116                 plci->NL.ReqCh = 0;
14117                 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14118                 plci->adapter->request(&plci->NL);
14119                 return;
14120         case FAX_CONNECT_ACK_COMMAND_2:
14121                 if ((Rc != OK) && (Rc != OK_FC))
14122                 {
14123                         dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14124                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14125                         break;
14126                 }
14127         }
14128         if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14129             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14130         {
14131                 if (plci->B3_prot == 4)
14132                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14133                 else
14134                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
14135                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14136         }
14137 }
14138
14139
14140 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14141 {
14142         word internal_command;
14143
14144         dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14145                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14146
14147         internal_command = plci->internal_command;
14148         plci->internal_command = 0;
14149         switch (internal_command)
14150         {
14151         default:
14152                 plci->command = 0;
14153         case FAX_EDATA_ACK_COMMAND_1:
14154                 if (plci_nl_busy(plci))
14155                 {
14156                         plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14157                         return;
14158                 }
14159                 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14160                 plci->NData[0].P = plci->fax_connect_info_buffer;
14161                 plci->NData[0].PLength = plci->fax_edata_ack_length;
14162                 plci->NL.X = plci->NData;
14163                 plci->NL.ReqCh = 0;
14164                 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14165                 plci->adapter->request(&plci->NL);
14166                 return;
14167         case FAX_EDATA_ACK_COMMAND_2:
14168                 if ((Rc != OK) && (Rc != OK_FC))
14169                 {
14170                         dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14171                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14172                         break;
14173                 }
14174         }
14175 }
14176
14177
14178 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14179 {
14180         word Info;
14181         word internal_command;
14182
14183         dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14184                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14185
14186         Info = GOOD;
14187         internal_command = plci->internal_command;
14188         plci->internal_command = 0;
14189         switch (internal_command)
14190         {
14191         default:
14192                 plci->command = 0;
14193         case FAX_CONNECT_INFO_COMMAND_1:
14194                 if (plci_nl_busy(plci))
14195                 {
14196                         plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14197                         return;
14198                 }
14199                 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14200                 plci->NData[0].P = plci->fax_connect_info_buffer;
14201                 plci->NData[0].PLength = plci->fax_connect_info_length;
14202                 plci->NL.X = plci->NData;
14203                 plci->NL.ReqCh = 0;
14204                 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14205                 plci->adapter->request(&plci->NL);
14206                 return;
14207         case FAX_CONNECT_INFO_COMMAND_2:
14208                 if ((Rc != OK) && (Rc != OK_FC))
14209                 {
14210                         dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14211                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14212                         Info = _WRONG_STATE;
14213                         break;
14214                 }
14215                 if (plci_nl_busy(plci))
14216                 {
14217                         plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14218                         return;
14219                 }
14220                 plci->command = _CONNECT_B3_R;
14221                 nl_req_ncci(plci, N_CONNECT, 0);
14222                 send_req(plci);
14223                 return;
14224         }
14225         sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14226 }
14227
14228
14229 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14230 {
14231         word Info;
14232         word internal_command;
14233
14234         dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14235                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14236
14237         Info = GOOD;
14238         internal_command = plci->internal_command;
14239         plci->internal_command = 0;
14240         switch (internal_command)
14241         {
14242         default:
14243                 plci->command = 0;
14244                 plci->adjust_b_parms_msg = NULL;
14245                 plci->adjust_b_facilities = plci->B1_facilities;
14246                 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14247                 plci->adjust_b_ncci = (word)(Id >> 16);
14248                 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14249                 plci->adjust_b_state = ADJUST_B_START;
14250                 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14251                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14252         case FAX_ADJUST_B23_COMMAND_1:
14253                 Info = adjust_b_process(Id, plci, Rc);
14254                 if (Info != GOOD)
14255                 {
14256                         dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14257                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14258                         break;
14259                 }
14260                 if (plci->internal_command)
14261                         return;
14262         case FAX_ADJUST_B23_COMMAND_2:
14263                 if (plci_nl_busy(plci))
14264                 {
14265                         plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14266                         return;
14267                 }
14268                 plci->command = _CONNECT_B3_R;
14269                 nl_req_ncci(plci, N_CONNECT, 0);
14270                 send_req(plci);
14271                 return;
14272         }
14273         sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14274 }
14275
14276
14277 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14278 {
14279         word internal_command;
14280
14281         dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14282                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14283
14284         internal_command = plci->internal_command;
14285         plci->internal_command = 0;
14286         switch (internal_command)
14287         {
14288         default:
14289                 plci->command = 0;
14290                 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14291                 return;
14292         case FAX_DISCONNECT_COMMAND_1:
14293         case FAX_DISCONNECT_COMMAND_2:
14294         case FAX_DISCONNECT_COMMAND_3:
14295                 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14296                 {
14297                         dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14298                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14299                         break;
14300                 }
14301                 if (Rc == OK)
14302                 {
14303                         if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14304                             || (internal_command == FAX_DISCONNECT_COMMAND_2))
14305                         {
14306                                 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14307                         }
14308                 }
14309                 else if (Rc == 0)
14310                 {
14311                         if (internal_command == FAX_DISCONNECT_COMMAND_1)
14312                                 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14313                 }
14314                 return;
14315         }
14316 }
14317
14318
14319
14320 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14321 {
14322         word Info;
14323         word internal_command;
14324
14325         dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14326                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14327
14328         Info = GOOD;
14329         internal_command = plci->internal_command;
14330         plci->internal_command = 0;
14331         switch (internal_command)
14332         {
14333         default:
14334                 plci->command = 0;
14335         case RTP_CONNECT_B3_REQ_COMMAND_1:
14336                 if (plci_nl_busy(plci))
14337                 {
14338                         plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14339                         return;
14340                 }
14341                 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14342                 nl_req_ncci(plci, N_CONNECT, 0);
14343                 send_req(plci);
14344                 return;
14345         case RTP_CONNECT_B3_REQ_COMMAND_2:
14346                 if ((Rc != OK) && (Rc != OK_FC))
14347                 {
14348                         dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14349                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14350                         Info = _WRONG_STATE;
14351                         break;
14352                 }
14353                 if (plci_nl_busy(plci))
14354                 {
14355                         plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14356                         return;
14357                 }
14358                 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14359                 plci->NData[0].PLength = plci->internal_req_buffer[0];
14360                 plci->NData[0].P = plci->internal_req_buffer + 1;
14361                 plci->NL.X = plci->NData;
14362                 plci->NL.ReqCh = 0;
14363                 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14364                 plci->adapter->request(&plci->NL);
14365                 break;
14366         case RTP_CONNECT_B3_REQ_COMMAND_3:
14367                 return;
14368         }
14369         sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14370 }
14371
14372
14373 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14374 {
14375         word internal_command;
14376
14377         dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14378                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14379
14380         internal_command = plci->internal_command;
14381         plci->internal_command = 0;
14382         switch (internal_command)
14383         {
14384         default:
14385                 plci->command = 0;
14386         case RTP_CONNECT_B3_RES_COMMAND_1:
14387                 if (plci_nl_busy(plci))
14388                 {
14389                         plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14390                         return;
14391                 }
14392                 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14393                 nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14394                 send_req(plci);
14395                 return;
14396         case RTP_CONNECT_B3_RES_COMMAND_2:
14397                 if ((Rc != OK) && (Rc != OK_FC))
14398                 {
14399                         dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14400                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14401                         break;
14402                 }
14403                 if (plci_nl_busy(plci))
14404                 {
14405                         plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14406                         return;
14407                 }
14408                 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14409                 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14410                 plci->NData[0].PLength = plci->internal_req_buffer[0];
14411                 plci->NData[0].P = plci->internal_req_buffer + 1;
14412                 plci->NL.X = plci->NData;
14413                 plci->NL.ReqCh = 0;
14414                 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14415                 plci->adapter->request(&plci->NL);
14416                 return;
14417         case RTP_CONNECT_B3_RES_COMMAND_3:
14418                 return;
14419         }
14420 }
14421
14422
14423
14424 static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14425 {
14426         byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14427         word Info;
14428         word internal_command;
14429
14430         dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14431                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14432
14433         Info = GOOD;
14434         internal_command = plci->internal_command;
14435         plci->internal_command = 0;
14436         switch (internal_command)
14437         {
14438         default:
14439                 if (!plci->NL.Id)
14440                         break;
14441                 plci->command = 0;
14442                 plci->adjust_b_parms_msg = NULL;
14443                 plci->adjust_b_facilities = plci->B1_facilities;
14444                 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14445                 plci->adjust_b_ncci = (word)(Id >> 16);
14446                 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14447                 plci->adjust_b_state = ADJUST_B_START;
14448                 dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14449                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14450         case HOLD_SAVE_COMMAND_1:
14451                 Info = adjust_b_process(Id, plci, Rc);
14452                 if (Info != GOOD)
14453                 {
14454                         dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14455                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14456                         break;
14457                 }
14458                 if (plci->internal_command)
14459                         return;
14460         }
14461         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14462 }
14463
14464
14465 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14466 {
14467         byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14468         word Info;
14469         word internal_command;
14470
14471         dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14472                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14473
14474         Info = GOOD;
14475         internal_command = plci->internal_command;
14476         plci->internal_command = 0;
14477         switch (internal_command)
14478         {
14479         default:
14480                 plci->command = 0;
14481                 plci->adjust_b_parms_msg = NULL;
14482                 plci->adjust_b_facilities = plci->B1_facilities;
14483                 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14484                 plci->adjust_b_ncci = (word)(Id >> 16);
14485                 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14486                 plci->adjust_b_state = ADJUST_B_START;
14487                 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14488                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14489         case RETRIEVE_RESTORE_COMMAND_1:
14490                 Info = adjust_b_process(Id, plci, Rc);
14491                 if (Info != GOOD)
14492                 {
14493                         dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14494                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14495                         break;
14496                 }
14497                 if (plci->internal_command)
14498                         return;
14499         }
14500         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14501 }
14502
14503
14504 static void init_b1_config(PLCI *plci)
14505 {
14506
14507         dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14508                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14509                         (char *)(FILE_), __LINE__));
14510
14511         plci->B1_resource = 0;
14512         plci->B1_facilities = 0;
14513
14514         plci->li_bchannel_id = 0;
14515         mixer_clear_config(plci);
14516
14517
14518         ec_clear_config(plci);
14519
14520
14521         dtmf_rec_clear_config(plci);
14522         dtmf_send_clear_config(plci);
14523         dtmf_parameter_clear_config(plci);
14524
14525         adv_voice_clear_config(plci);
14526         adjust_b_clear(plci);
14527 }
14528
14529
14530 static void clear_b1_config(PLCI *plci)
14531 {
14532
14533         dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14534                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14535                         (char *)(FILE_), __LINE__));
14536
14537         adv_voice_clear_config(plci);
14538         adjust_b_clear(plci);
14539
14540         ec_clear_config(plci);
14541
14542
14543         dtmf_rec_clear_config(plci);
14544         dtmf_send_clear_config(plci);
14545         dtmf_parameter_clear_config(plci);
14546
14547
14548         if ((plci->li_bchannel_id != 0)
14549             && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14550         {
14551                 mixer_clear_config(plci);
14552                 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14553                 plci->li_bchannel_id = 0;
14554         }
14555
14556         plci->B1_resource = 0;
14557         plci->B1_facilities = 0;
14558 }
14559
14560
14561 /* -----------------------------------------------------------------
14562    XON protocol local helpers
14563    ----------------------------------------------------------------- */
14564 static void channel_flow_control_remove(PLCI *plci) {
14565         DIVA_CAPI_ADAPTER *a = plci->adapter;
14566         word i;
14567         for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14568                 if (a->ch_flow_plci[i] == plci->Id) {
14569                         a->ch_flow_plci[i] = 0;
14570                         a->ch_flow_control[i] = 0;
14571                 }
14572         }
14573 }
14574
14575 static void channel_x_on(PLCI *plci, byte ch) {
14576         DIVA_CAPI_ADAPTER *a = plci->adapter;
14577         if (a->ch_flow_control[ch] & N_XON_SENT) {
14578                 a->ch_flow_control[ch] &= ~N_XON_SENT;
14579         }
14580 }
14581
14582 static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14583         DIVA_CAPI_ADAPTER *a = plci->adapter;
14584         if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14585                 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14586                 a->ch_flow_plci[ch] = plci->Id;
14587                 a->ch_flow_control_pending++;
14588         }
14589 }
14590
14591 static void channel_request_xon(PLCI *plci, byte ch) {
14592         DIVA_CAPI_ADAPTER *a = plci->adapter;
14593
14594         if (a->ch_flow_control[ch] & N_CH_XOFF) {
14595                 a->ch_flow_control[ch] |= N_XON_REQ;
14596                 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14597                 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14598         }
14599 }
14600
14601 static void channel_xmit_extended_xon(PLCI *plci) {
14602         DIVA_CAPI_ADAPTER *a;
14603         int max_ch = ARRAY_SIZE(a->ch_flow_control);
14604         int i, one_requested = 0;
14605
14606         if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14607                 return;
14608         }
14609
14610         for (i = 0; i < max_ch; i++) {
14611                 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14612                     (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14613                     (plci->Id == a->ch_flow_plci[i])) {
14614                         channel_request_xon(plci, (byte)i);
14615                         one_requested = 1;
14616                 }
14617         }
14618
14619         if (one_requested) {
14620                 channel_xmit_xon(plci);
14621         }
14622 }
14623
14624 /*
14625   Try to xmit next X_ON
14626 */
14627 static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14628         int max_ch = ARRAY_SIZE(a->ch_flow_control);
14629         int i;
14630
14631         if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14632                 return (0);
14633         }
14634
14635         if (a->last_flow_control_ch >= max_ch) {
14636                 a->last_flow_control_ch = 1;
14637         }
14638         for (i = a->last_flow_control_ch; i < max_ch; i++) {
14639                 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14640                     (plci->Id == a->ch_flow_plci[i])) {
14641                         a->last_flow_control_ch = i + 1;
14642                         return (i);
14643                 }
14644         }
14645
14646         for (i = 1; i < a->last_flow_control_ch; i++) {
14647                 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14648                     (plci->Id == a->ch_flow_plci[i])) {
14649                         a->last_flow_control_ch = i + 1;
14650                         return (i);
14651                 }
14652         }
14653
14654         return (0);
14655 }
14656
14657 static void channel_xmit_xon(PLCI *plci) {
14658         DIVA_CAPI_ADAPTER *a = plci->adapter;
14659         byte ch;
14660
14661         if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14662                 return;
14663         }
14664         if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14665                 return;
14666         }
14667         a->ch_flow_control[ch] &= ~N_XON_REQ;
14668         a->ch_flow_control[ch] |= N_XON_SENT;
14669
14670         plci->NL.Req = plci->nl_req = (byte)N_XON;
14671         plci->NL.ReqCh         = ch;
14672         plci->NL.X             = plci->NData;
14673         plci->NL.XNum          = 1;
14674         plci->NData[0].P       = &plci->RBuffer[0];
14675         plci->NData[0].PLength = 0;
14676
14677         plci->adapter->request(&plci->NL);
14678 }
14679
14680 static int channel_can_xon(PLCI *plci, byte ch) {
14681         APPL *APPLptr;
14682         DIVA_CAPI_ADAPTER *a;
14683         word NCCIcode;
14684         dword count;
14685         word Num;
14686         word i;
14687
14688         APPLptr = plci->appl;
14689         a = plci->adapter;
14690
14691         if (!APPLptr)
14692                 return (0);
14693
14694         NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14695
14696         /* count all buffers within the Application pool    */
14697         /* belonging to the same NCCI. XON if a first is    */
14698         /* used.                                            */
14699         count = 0;
14700         Num = 0xffff;
14701         for (i = 0; i < APPLptr->MaxBuffer; i++) {
14702                 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14703                 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14704         }
14705         if ((count > 2) || (Num == 0xffff)) {
14706                 return (0);
14707         }
14708         return (1);
14709 }
14710
14711
14712 /*------------------------------------------------------------------*/
14713
14714 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14715 {
14716         return 1;
14717 }
14718
14719
14720
14721 /**********************************************************************************/
14722 /* function groups the listening applications according to the CIP mask and the   */
14723 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14724 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14725 /* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14726 /* function must be enabled by setting "a->group_optimization_enabled" from the   */
14727 /* OS specific part (per adapter).                                                */
14728 /**********************************************************************************/
14729 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14730 {
14731         word i, j, k, busy, group_found;
14732         dword info_mask_group[MAX_CIP_TYPES];
14733         dword cip_mask_group[MAX_CIP_TYPES];
14734         word appl_number_group_type[MAX_APPL];
14735         PLCI *auxplci;
14736
14737         set_group_ind_mask(plci); /* all APPLs within this inc. call are allowed to dial in */
14738
14739         if (!a->group_optimization_enabled)
14740         {
14741                 dbug(1, dprintf("No group optimization"));
14742                 return;
14743         }
14744
14745         dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14746
14747         for (i = 0; i < MAX_CIP_TYPES; i++)
14748         {
14749                 info_mask_group[i] = 0;
14750                 cip_mask_group[i] = 0;
14751         }
14752         for (i = 0; i < MAX_APPL; i++)
14753         {
14754                 appl_number_group_type[i] = 0;
14755         }
14756         for (i = 0; i < max_appl; i++) /* check if any multi instance capable application is present */
14757         {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14758                 if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14759                 {
14760                         dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14761                         return; /* allow good application unfiltered access */
14762                 }
14763         }
14764         for (i = 0; i < max_appl; i++) /* Build CIP Groups */
14765         {
14766                 if (application[i].Id && a->CIP_Mask[i])
14767                 {
14768                         for (k = 0, busy = false; k < a->max_plci; k++)
14769                         {
14770                                 if (a->plci[k].Id)
14771                                 {
14772                                         auxplci = &a->plci[k];
14773                                         if (auxplci->appl == &application[i]) /* application has a busy PLCI */
14774                                         {
14775                                                 busy = true;
14776                                                 dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14777                                         }
14778                                         else if (test_c_ind_mask_bit(auxplci, i)) /* application has an incoming call pending */
14779                                         {
14780                                                 busy = true;
14781                                                 dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14782                                         }
14783                                 }
14784                         }
14785
14786                         for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++)     /* build groups with free applications only */
14787                         {
14788                                 if (j == MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14789                                 {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14790                                         appl_number_group_type[i] = MAX_CIP_TYPES;
14791                                         group_found = true;
14792                                         dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14793                                 }
14794                                 else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14795                                 {                                      /* is group already present ?                  */
14796                                         appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14797                                         group_found = true;
14798                                         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]));
14799                                 }
14800                                 else if (!info_mask_group[j])
14801                                 {                                      /* establish a new group                       */
14802                                         appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14803                                         info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14804                                         cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14805                                         group_found = true;
14806                                         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]));
14807                                 }
14808                         }
14809                 }
14810         }
14811
14812         for (i = 0; i < max_appl; i++) /* Build group_optimization_mask_table */
14813         {
14814                 if (appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14815                 {
14816                         if (appl_number_group_type[i] == MAX_CIP_TYPES)
14817                         {
14818                                 dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14819                         }
14820                         else
14821                         {
14822                                 dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14823                                 for (j = i + 1; j < max_appl; j++)   /* search other group members and mark them as busy        */
14824                                 {
14825                                         if (appl_number_group_type[i] == appl_number_group_type[j])
14826                                         {
14827                                                 dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14828                                                 clear_group_ind_mask_bit(plci, j);           /* disable call on other group members */
14829                                                 appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14830                                         }
14831                                 }
14832                         }
14833                 }
14834                 else                                                 /* application should not get a call */
14835                 {
14836                         clear_group_ind_mask_bit(plci, i);
14837                 }
14838         }
14839
14840 }
14841
14842
14843
14844 /* OS notifies the driver about a application Capi_Register */
14845 word CapiRegister(word id)
14846 {
14847         word i, j, appls_found;
14848
14849         PLCI *plci;
14850         DIVA_CAPI_ADAPTER *a;
14851
14852         for (i = 0, appls_found = 0; i < max_appl; i++)
14853         {
14854                 if (application[i].Id && (application[i].Id != id))
14855                 {
14856                         appls_found++;                       /* an application has been found */
14857                 }
14858         }
14859
14860         if (appls_found) return true;
14861         for (i = 0; i < max_adapter; i++)                   /* scan all adapters...    */
14862         {
14863                 a = &adapter[i];
14864                 if (a->request)
14865                 {
14866                         if (a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14867                         {
14868                                 if (!appls_found)           /* first application does a capi register   */
14869                                 {
14870                                         if ((j = get_plci(a)))                    /* activate L1 of all adapters */
14871                                         {
14872                                                 plci = &a->plci[j - 1];
14873                                                 plci->command = 0;
14874                                                 add_p(plci, OAD, "\x01\xfd");
14875                                                 add_p(plci, CAI, "\x01\x80");
14876                                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14877                                                 add_p(plci, SHIFT | 6, NULL);
14878                                                 add_p(plci, SIN, "\x02\x00\x00");
14879                                                 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14880                                                 sig_req(plci, ASSIGN, DSIG_ID);
14881                                                 add_p(plci, FTY, "\x02\xff\x07"); /* l1 start */
14882                                                 sig_req(plci, SIG_CTRL, 0);
14883                                                 send_req(plci);
14884                                         }
14885                                 }
14886                         }
14887                 }
14888         }
14889         return false;
14890 }
14891
14892 /*------------------------------------------------------------------*/
14893
14894 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14895
14896 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14897 {
14898         word i;
14899         /* Format of vswitch_t:
14900            0 byte length
14901            1 byte VSWITCHIE
14902            2 byte VSWITCH_REQ/VSWITCH_IND
14903            3 byte reserved
14904            4 word VSwitchcommand
14905            6 word returnerror
14906            8... Params
14907         */
14908         if (!plci ||
14909             !plci->appl ||
14910             !plci->State ||
14911             plci->Sig.Ind == NCR_FACILITY
14912                 )
14913                 return;
14914
14915         for (i = 0; i < MAX_MULTI_IE; i++)
14916         {
14917                 if (!parms[i][0]) continue;
14918                 if (parms[i][0] < 7)
14919                 {
14920                         parms[i][0] = 0; /* kill it */
14921                         continue;
14922                 }
14923                 dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14924                 switch (parms[i][4])
14925                 {
14926                 case VSJOIN:
14927                         if (!plci->relatedPTYPLCI ||
14928                             (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14929                         { /* Error */
14930                                 break;
14931                         }
14932                         /* remember all necessary informations */
14933                         if (parms[i][0] != 11 || parms[i][8] != 3) /* Length Test */
14934                         {
14935                                 break;
14936                         }
14937                         if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14938                         {   /* first indication after ECT-Request on Consultation Call */
14939                                 plci->vswitchstate = parms[i][9];
14940                                 parms[i][9] = 2; /* State */
14941                                 /* now ask first Call to join */
14942                         }
14943                         else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14944                         { /* Answer of VSWITCH_REQ from first Call */
14945                                 plci->vswitchstate = parms[i][9];
14946                                 /* tell consultation call to join
14947                                    and the protocol capabilities of the first call */
14948                         }
14949                         else
14950                         { /* Error */
14951                                 break;
14952                         }
14953                         plci->vsprot = parms[i][10]; /* protocol */
14954                         plci->vsprotdialect = parms[i][11]; /* protocoldialect */
14955                         /* send join request to related PLCI */
14956                         parms[i][1] = VSWITCHIE;
14957                         parms[i][2] = VSWITCH_REQ;
14958
14959                         plci->relatedPTYPLCI->command = 0;
14960                         plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14961                         add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14962                         sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14963                         send_req(plci->relatedPTYPLCI);
14964                         break;
14965                 case VSTRANSPORT:
14966                 default:
14967                         if (plci->relatedPTYPLCI &&
14968                             plci->vswitchstate == 3 &&
14969                             plci->relatedPTYPLCI->vswitchstate == 3)
14970                         {
14971                                 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14972                                 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14973                                 send_req(plci->relatedPTYPLCI);
14974                         }
14975                         break;
14976                 }
14977                 parms[i][0] = 0; /* kill it */
14978         }
14979 }
14980
14981
14982 /*------------------------------------------------------------------*/
14983
14984 static int diva_get_dma_descriptor(PLCI *plci, dword   *dma_magic) {
14985         ENTITY e;
14986         IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14987
14988         if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14989                 return (-1);
14990         }
14991
14992         pReq->xdi_dma_descriptor_operation.Req = 0;
14993         pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14994
14995         pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14996         pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
14997         pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14998         pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
14999
15000         e.user[0] = plci->adapter->Id - 1;
15001         plci->adapter->request((ENTITY *)pReq);
15002
15003         if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15004             (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15005             pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15006                 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15007                 dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
15008                                 plci->adapter->Id,
15009                                 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15010                                 *dma_magic));
15011                 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15012         } else {
15013                 dbug(1, dprintf("dma_alloc failed"));
15014                 return (-1);
15015         }
15016 }
15017
15018 static void diva_free_dma_descriptor(PLCI *plci, int nr) {
15019         ENTITY e;
15020         IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
15021
15022         if (nr < 0) {
15023                 return;
15024         }
15025
15026         pReq->xdi_dma_descriptor_operation.Req = 0;
15027         pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15028
15029         pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15030         pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
15031         pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15032         pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15033
15034         e.user[0] = plci->adapter->Id - 1;
15035         plci->adapter->request((ENTITY *)pReq);
15036
15037         if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15038                 dbug(1, dprintf("dma_free(%d)", nr));
15039         } else {
15040                 dbug(1, dprintf("dma_free failed (%d)", nr));
15041         }
15042 }
15043
15044 /*------------------------------------------------------------------*/