Upgrade to 4.4.50-rt62
[kvmfornfv.git] / kernel / 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         static char hex_digit_table[0x10] =
1151                 {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
1152         word i, j, k;
1153         dword d;
1154         char *p;
1155         char buf[40];
1156
1157         for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1158         {
1159                 p = buf + 36;
1160                 *p = '\0';
1161                 for (j = 0; j < 4; j++)
1162                 {
1163                         if (i + j < C_IND_MASK_DWORDS)
1164                         {
1165                                 d = plci->c_ind_mask_table[i + j];
1166                                 for (k = 0; k < 8; k++)
1167                                 {
1168                                         *(--p) = hex_digit_table[d & 0xf];
1169                                         d >>= 4;
1170                                 }
1171                         }
1172                         else if (i != 0)
1173                         {
1174                                 for (k = 0; k < 8; k++)
1175                                         *(--p) = ' ';
1176                         }
1177                         *(--p) = ' ';
1178                 }
1179                 dbug(1, dprintf("c_ind_mask =%s", (char *) p));
1180         }
1181 }
1182
1183
1184
1185
1186
1187 #define dump_plcis(a)
1188
1189
1190
1191 /*------------------------------------------------------------------*/
1192 /* translation function for each message                            */
1193 /*------------------------------------------------------------------*/
1194
1195 static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1196                         PLCI *plci, APPL *appl, API_PARSE *parms)
1197 {
1198         word ch;
1199         word i;
1200         word Info;
1201         byte LinkLayer;
1202         API_PARSE *ai;
1203         API_PARSE *bp;
1204         API_PARSE ai_parms[5];
1205         word channel = 0;
1206         dword ch_mask;
1207         byte m;
1208         static byte esc_chi[35] = {0x02, 0x18, 0x01};
1209         static byte lli[2] = {0x01, 0x00};
1210         byte noCh = 0;
1211         word dir = 0;
1212         byte *p_chi = "";
1213
1214         for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1215
1216         dbug(1, dprintf("connect_req(%d)", parms->length));
1217         Info = _WRONG_IDENTIFIER;
1218         if (a)
1219         {
1220                 if (a->adapter_disabled)
1221                 {
1222                         dbug(1, dprintf("adapter disabled"));
1223                         Id = ((word)1 << 8) | a->Id;
1224                         sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
1225                         sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1226                         return false;
1227                 }
1228                 Info = _OUT_OF_PLCI;
1229                 if ((i = get_plci(a)))
1230                 {
1231                         Info = 0;
1232                         plci = &a->plci[i - 1];
1233                         plci->appl = appl;
1234                         plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1235                         /* check 'external controller' bit for codec support */
1236                         if (Id & EXT_CONTROLLER)
1237                         {
1238                                 if (AdvCodecSupport(a, plci, appl, 0))
1239                                 {
1240                                         plci->Id = 0;
1241                                         sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1242                                         return 2;
1243                                 }
1244                         }
1245                         ai = &parms[9];
1246                         bp = &parms[5];
1247                         ch = 0;
1248                         if (bp->length)LinkLayer = bp->info[3];
1249                         else LinkLayer = 0;
1250                         if (ai->length)
1251                         {
1252                                 ch = 0xffff;
1253                                 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1254                                 {
1255                                         ch = 0;
1256                                         if (ai_parms[0].length)
1257                                         {
1258                                                 ch = GET_WORD(ai_parms[0].info + 1);
1259                                                 if (ch > 4) ch = 0; /* safety -> ignore ChannelID */
1260                                                 if (ch == 4) /* explizit CHI in message */
1261                                                 {
1262                                                         /* check length of B-CH struct */
1263                                                         if ((ai_parms[0].info)[3] >= 1)
1264                                                         {
1265                                                                 if ((ai_parms[0].info)[4] == CHI)
1266                                                                 {
1267                                                                         p_chi = &((ai_parms[0].info)[5]);
1268                                                                 }
1269                                                                 else
1270                                                                 {
1271                                                                         p_chi = &((ai_parms[0].info)[3]);
1272                                                                 }
1273                                                                 if (p_chi[0] > 35) /* check length of channel ID */
1274                                                                 {
1275                                                                         Info = _WRONG_MESSAGE_FORMAT;
1276                                                                 }
1277                                                         }
1278                                                         else Info = _WRONG_MESSAGE_FORMAT;
1279                                                 }
1280
1281                                                 if (ch == 3 && ai_parms[0].length >= 7 && ai_parms[0].length <= 36)
1282                                                 {
1283                                                         dir = GET_WORD(ai_parms[0].info + 3);
1284                                                         ch_mask = 0;
1285                                                         m = 0x3f;
1286                                                         for (i = 0; i + 5 <= ai_parms[0].length; i++)
1287                                                         {
1288                                                                 if (ai_parms[0].info[i + 5] != 0)
1289                                                                 {
1290                                                                         if ((ai_parms[0].info[i + 5] | m) != 0xff)
1291                                                                                 Info = _WRONG_MESSAGE_FORMAT;
1292                                                                         else
1293                                                                         {
1294                                                                                 if (ch_mask == 0)
1295                                                                                         channel = i;
1296                                                                                 ch_mask |= 1L << i;
1297                                                                         }
1298                                                                 }
1299                                                                 m = 0;
1300                                                         }
1301                                                         if (ch_mask == 0)
1302                                                                 Info = _WRONG_MESSAGE_FORMAT;
1303                                                         if (!Info)
1304                                                         {
1305                                                                 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1306                                                                 {
1307                                                                         esc_chi[0] = (byte)(ai_parms[0].length - 2);
1308                                                                         for (i = 0; i + 5 <= ai_parms[0].length; i++)
1309                                                                                 esc_chi[i + 3] = ai_parms[0].info[i + 5];
1310                                                                 }
1311                                                                 else
1312                                                                         esc_chi[0] = 2;
1313                                                                 esc_chi[2] = (byte)channel;
1314                                                                 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1315                                                                 add_p(plci, LLI, lli);
1316                                                                 add_p(plci, ESC, esc_chi);
1317                                                                 plci->State = LOCAL_CONNECT;
1318                                                                 if (!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
1319                                                         }
1320                                                 }
1321                                         }
1322                                 }
1323                                 else  Info = _WRONG_MESSAGE_FORMAT;
1324                         }
1325
1326                         dbug(1, dprintf("ch=%x,dir=%x,p_ch=%d", ch, dir, channel));
1327                         plci->command = _CONNECT_R;
1328                         plci->number = Number;
1329                         /* x.31 or D-ch free SAPI in LinkLayer? */
1330                         if (ch == 1 && LinkLayer != 3 && LinkLayer != 12) noCh = true;
1331                         if ((ch == 0 || ch == 2 || noCh || ch == 3 || ch == 4) && !Info)
1332                         {
1333                                 /* B-channel used for B3 connections (ch==0), or no B channel    */
1334                                 /* is used (ch==2) or perm. connection (3) is used  do a CALL    */
1335                                 if (noCh) Info = add_b1(plci, &parms[5], 2, 0);    /* no resource    */
1336                                 else     Info = add_b1(plci, &parms[5], ch, 0);
1337                                 add_s(plci, OAD, &parms[2]);
1338                                 add_s(plci, OSA, &parms[4]);
1339                                 add_s(plci, BC, &parms[6]);
1340                                 add_s(plci, LLC, &parms[7]);
1341                                 add_s(plci, HLC, &parms[8]);
1342                                 if (a->Info_Mask[appl->Id - 1] & 0x200)
1343                                 {
1344                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
1345                                         add_p(plci, LLI, "\x01\x01");
1346                                 }
1347                                 if (GET_WORD(parms[0].info) < 29) {
1348                                         add_p(plci, BC, cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1349                                         add_p(plci, HLC, cip_hlc[GET_WORD(parms[0].info)]);
1350                                 }
1351                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1352                                 sig_req(plci, ASSIGN, DSIG_ID);
1353                         }
1354                         else if (ch == 1) {
1355
1356                                 /* D-Channel used for B3 connections */
1357                                 plci->Sig.Id = 0xff;
1358                                 Info = 0;
1359                         }
1360
1361                         if (!Info && ch != 2 && !noCh) {
1362                                 Info = add_b23(plci, &parms[5]);
1363                                 if (!Info) {
1364                                         if (!(plci->tel && !plci->adv_nl))nl_req_ncci(plci, ASSIGN, 0);
1365                                 }
1366                         }
1367
1368                         if (!Info)
1369                         {
1370                                 if (ch == 0 || ch == 2 || ch == 3 || noCh || ch == 4)
1371                                 {
1372                                         if (plci->spoofed_msg == SPOOFING_REQUIRED)
1373                                         {
1374                                                 api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1375                                                 plci->spoofed_msg = CALL_REQ;
1376                                                 plci->internal_command = BLOCK_PLCI;
1377                                                 plci->command = 0;
1378                                                 dbug(1, dprintf("Spoof"));
1379                                                 send_req(plci);
1380                                                 return false;
1381                                         }
1382                                         if (ch == 4)add_p(plci, CHI, p_chi);
1383                                         add_s(plci, CPN, &parms[1]);
1384                                         add_s(plci, DSA, &parms[3]);
1385                                         if (noCh) add_p(plci, ESC, "\x02\x18\xfd");  /* D-channel, no B-L3 */
1386                                         add_ai(plci, &parms[9]);
1387                                         if (!dir)sig_req(plci, CALL_REQ, 0);
1388                                         else
1389                                         {
1390                                                 plci->command = PERM_LIST_REQ;
1391                                                 plci->appl = appl;
1392                                                 sig_req(plci, LISTEN_REQ, 0);
1393                                                 send_req(plci);
1394                                                 return false;
1395                                         }
1396                                 }
1397                                 send_req(plci);
1398                                 return false;
1399                         }
1400                         plci->Id = 0;
1401                 }
1402         }
1403         sendf(appl,
1404               _CONNECT_R | CONFIRM,
1405               Id,
1406               Number,
1407               "w", Info);
1408         return 2;
1409 }
1410
1411 static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1412                         PLCI *plci, APPL *appl, API_PARSE *parms)
1413 {
1414         word i, Info;
1415         word Reject;
1416         static byte cau_t[] = {0, 0, 0x90, 0x91, 0xac, 0x9d, 0x86, 0xd8, 0x9b};
1417         static byte esc_t[] = {0x03, 0x08, 0x00, 0x00};
1418         API_PARSE *ai;
1419         API_PARSE ai_parms[5];
1420         word ch = 0;
1421
1422         if (!plci) {
1423                 dbug(1, dprintf("connect_res(no plci)"));
1424                 return 0;  /* no plci, no send */
1425         }
1426
1427         dbug(1, dprintf("connect_res(State=0x%x)", plci->State));
1428         for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1429         ai = &parms[5];
1430         dbug(1, dprintf("ai->length=%d", ai->length));
1431
1432         if (ai->length)
1433         {
1434                 if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1435                 {
1436                         dbug(1, dprintf("ai_parms[0].length=%d/0x%x", ai_parms[0].length, GET_WORD(ai_parms[0].info + 1)));
1437                         ch = 0;
1438                         if (ai_parms[0].length)
1439                         {
1440                                 ch = GET_WORD(ai_parms[0].info + 1);
1441                                 dbug(1, dprintf("BCH-I=0x%x", ch));
1442                         }
1443                 }
1444         }
1445
1446         if (plci->State == INC_CON_CONNECTED_ALERT)
1447         {
1448                 dbug(1, dprintf("Connected Alert Call_Res"));
1449                 if (a->Info_Mask[appl->Id - 1] & 0x200)
1450                 {
1451                         /* early B3 connect (CIP mask bit 9) no release after a disc */
1452                         add_p(plci, LLI, "\x01\x01");
1453                 }
1454                 add_s(plci, CONN_NR, &parms[2]);
1455                 add_s(plci, LLC, &parms[4]);
1456                 add_ai(plci, &parms[5]);
1457                 plci->State = INC_CON_ACCEPT;
1458                 sig_req(plci, CALL_RES, 0);
1459                 return 1;
1460         }
1461         else if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT) {
1462                 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1463                 dump_c_ind_mask(plci);
1464                 Reject = GET_WORD(parms[0].info);
1465                 dbug(1, dprintf("Reject=0x%x", Reject));
1466                 if (Reject)
1467                 {
1468                         if (c_ind_mask_empty(plci))
1469                         {
1470                                 if ((Reject & 0xff00) == 0x3400)
1471                                 {
1472                                         esc_t[2] = ((byte)(Reject & 0x00ff)) | 0x80;
1473                                         add_p(plci, ESC, esc_t);
1474                                         add_ai(plci, &parms[5]);
1475                                         sig_req(plci, REJECT, 0);
1476                                 }
1477                                 else if (Reject == 1 || Reject >= 9)
1478                                 {
1479                                         add_ai(plci, &parms[5]);
1480                                         sig_req(plci, HANGUP, 0);
1481                                 }
1482                                 else
1483                                 {
1484                                         esc_t[2] = cau_t[(Reject&0x000f)];
1485                                         add_p(plci, ESC, esc_t);
1486                                         add_ai(plci, &parms[5]);
1487                                         sig_req(plci, REJECT, 0);
1488                                 }
1489                                 plci->appl = appl;
1490                         }
1491                         else
1492                         {
1493                                 sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1494                         }
1495                 }
1496                 else {
1497                         plci->appl = appl;
1498                         if (Id & EXT_CONTROLLER) {
1499                                 if (AdvCodecSupport(a, plci, appl, 0)) {
1500                                         dbug(1, dprintf("connect_res(error from AdvCodecSupport)"));
1501                                         sig_req(plci, HANGUP, 0);
1502                                         return 1;
1503                                 }
1504                                 if (plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1505                                 {
1506                                         Info = add_b23(plci, &parms[1]);
1507                                         if (Info)
1508                                         {
1509                                                 dbug(1, dprintf("connect_res(error from add_b23)"));
1510                                                 sig_req(plci, HANGUP, 0);
1511                                                 return 1;
1512                                         }
1513                                         if (plci->adv_nl)
1514                                         {
1515                                                 nl_req_ncci(plci, ASSIGN, 0);
1516                                         }
1517                                 }
1518                         }
1519                         else
1520                         {
1521                                 plci->tel = 0;
1522                                 if (ch != 2)
1523                                 {
1524                                         Info = add_b23(plci, &parms[1]);
1525                                         if (Info)
1526                                         {
1527                                                 dbug(1, dprintf("connect_res(error from add_b23 2)"));
1528                                                 sig_req(plci, HANGUP, 0);
1529                                                 return 1;
1530                                         }
1531                                 }
1532                                 nl_req_ncci(plci, ASSIGN, 0);
1533                         }
1534
1535                         if (plci->spoofed_msg == SPOOFING_REQUIRED)
1536                         {
1537                                 api_save_msg(parms, "wsssss", &plci->saved_msg);
1538                                 plci->spoofed_msg = CALL_RES;
1539                                 plci->internal_command = BLOCK_PLCI;
1540                                 plci->command = 0;
1541                                 dbug(1, dprintf("Spoof"));
1542                         }
1543                         else
1544                         {
1545                                 add_b1(plci, &parms[1], ch, plci->B1_facilities);
1546                                 if (a->Info_Mask[appl->Id - 1] & 0x200)
1547                                 {
1548                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
1549                                         add_p(plci, LLI, "\x01\x01");
1550                                 }
1551                                 add_s(plci, CONN_NR, &parms[2]);
1552                                 add_s(plci, LLC, &parms[4]);
1553                                 add_ai(plci, &parms[5]);
1554                                 plci->State = INC_CON_ACCEPT;
1555                                 sig_req(plci, CALL_RES, 0);
1556                         }
1557
1558                         for (i = 0; i < max_appl; i++) {
1559                                 if (test_c_ind_mask_bit(plci, i)) {
1560                                         sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1561                                 }
1562                         }
1563                 }
1564         }
1565         return 1;
1566 }
1567
1568 static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1569                           PLCI *plci, APPL *appl, API_PARSE *msg)
1570 {
1571         dbug(1, dprintf("connect_a_res"));
1572         return false;
1573 }
1574
1575 static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1576                            PLCI *plci, APPL *appl, API_PARSE *msg)
1577 {
1578         word Info;
1579         word i;
1580
1581         dbug(1, dprintf("disconnect_req"));
1582
1583         Info = _WRONG_IDENTIFIER;
1584
1585         if (plci)
1586         {
1587                 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
1588                 {
1589                         clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1590                         plci->appl = appl;
1591                         for (i = 0; i < max_appl; i++)
1592                         {
1593                                 if (test_c_ind_mask_bit(plci, i))
1594                                         sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1595                         }
1596                         plci->State = OUTG_DIS_PENDING;
1597                 }
1598                 if (plci->Sig.Id && plci->appl)
1599                 {
1600                         Info = 0;
1601                         if (plci->Sig.Id != 0xff)
1602                         {
1603                                 if (plci->State != INC_DIS_PENDING)
1604                                 {
1605                                         add_ai(plci, &msg[0]);
1606                                         sig_req(plci, HANGUP, 0);
1607                                         plci->State = OUTG_DIS_PENDING;
1608                                         return 1;
1609                                 }
1610                         }
1611                         else
1612                         {
1613                                 if (plci->NL.Id && !plci->nl_remove_id)
1614                                 {
1615                                         mixer_remove(plci);
1616                                         nl_req_ncci(plci, REMOVE, 0);
1617                                         sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
1618                                         sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1619                                         plci->State = INC_DIS_PENDING;
1620                                 }
1621                                 return 1;
1622                         }
1623                 }
1624         }
1625
1626         if (!appl)  return false;
1627         sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", Info);
1628         return false;
1629 }
1630
1631 static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1632                            PLCI *plci, APPL *appl, API_PARSE *msg)
1633 {
1634         dbug(1, dprintf("disconnect_res"));
1635         if (plci)
1636         {
1637                 /* clear ind mask bit, just in case of collsion of          */
1638                 /* DISCONNECT_IND and CONNECT_RES                           */
1639                 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1640                 ncci_free_receive_buffers(plci, 0);
1641                 if (plci_remove_check(plci))
1642                 {
1643                         return 0;
1644                 }
1645                 if (plci->State == INC_DIS_PENDING
1646                     || plci->State == SUSPENDING) {
1647                         if (c_ind_mask_empty(plci)) {
1648                                 if (plci->State != SUSPENDING) plci->State = IDLE;
1649                                 dbug(1, dprintf("chs=%d", plci->channels));
1650                                 if (!plci->channels) {
1651                                         plci_remove(plci);
1652                                 }
1653                         }
1654                 }
1655         }
1656         return 0;
1657 }
1658
1659 static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1660                        PLCI *plci, APPL *appl, API_PARSE *parms)
1661 {
1662         word Info;
1663         byte i;
1664
1665         dbug(1, dprintf("listen_req(Appl=0x%x)", appl->Id));
1666
1667         Info = _WRONG_IDENTIFIER;
1668         if (a) {
1669                 Info = 0;
1670                 a->Info_Mask[appl->Id - 1] = GET_DWORD(parms[0].info);
1671                 a->CIP_Mask[appl->Id - 1] = GET_DWORD(parms[1].info);
1672                 dbug(1, dprintf("CIP_MASK=0x%lx", GET_DWORD(parms[1].info)));
1673                 if (a->Info_Mask[appl->Id - 1] & 0x200) { /* early B3 connect provides */
1674                         a->Info_Mask[appl->Id - 1] |=  0x10;   /* call progression infos    */
1675                 }
1676
1677                 /* check if external controller listen and switch listen on or off*/
1678                 if (Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)) {
1679                         if (a->profile.Global_Options & ON_BOARD_CODEC) {
1680                                 dummy_plci.State = IDLE;
1681                                 a->codec_listen[appl->Id - 1] = &dummy_plci;
1682                                 a->TelOAD[0] = (byte)(parms[3].length);
1683                                 for (i = 1; parms[3].length >= i && i < 22; i++) {
1684                                         a->TelOAD[i] = parms[3].info[i];
1685                                 }
1686                                 a->TelOAD[i] = 0;
1687                                 a->TelOSA[0] = (byte)(parms[4].length);
1688                                 for (i = 1; parms[4].length >= i && i < 22; i++) {
1689                                         a->TelOSA[i] = parms[4].info[i];
1690                                 }
1691                                 a->TelOSA[i] = 0;
1692                         }
1693                         else Info = 0x2002; /* wrong controller, codec not supported */
1694                 }
1695                 else{               /* clear listen */
1696                         a->codec_listen[appl->Id - 1] = (PLCI *)0;
1697                 }
1698         }
1699         sendf(appl,
1700               _LISTEN_R | CONFIRM,
1701               Id,
1702               Number,
1703               "w", Info);
1704
1705         if (a) listen_check(a);
1706         return false;
1707 }
1708
1709 static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1710                      PLCI *plci, APPL *appl, API_PARSE *msg)
1711 {
1712         word i;
1713         API_PARSE *ai;
1714         PLCI *rc_plci = NULL;
1715         API_PARSE ai_parms[5];
1716         word Info = 0;
1717
1718         dbug(1, dprintf("info_req"));
1719         for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1720
1721         ai = &msg[1];
1722
1723         if (ai->length)
1724         {
1725                 if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1726                 {
1727                         dbug(1, dprintf("AddInfo wrong"));
1728                         Info = _WRONG_MESSAGE_FORMAT;
1729                 }
1730         }
1731         if (!a) Info = _WRONG_STATE;
1732
1733         if (!Info && plci)
1734         {                /* no fac, with CPN, or KEY */
1735                 rc_plci = plci;
1736                 if (!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length))
1737                 {
1738                         /* overlap sending option */
1739                         dbug(1, dprintf("OvlSnd"));
1740                         add_s(plci, CPN, &msg[0]);
1741                         add_s(plci, KEY, &ai_parms[1]);
1742                         sig_req(plci, INFO_REQ, 0);
1743                         send_req(plci);
1744                         return false;
1745                 }
1746
1747                 if (plci->State && ai_parms[2].length)
1748                 {
1749                         /* User_Info option */
1750                         dbug(1, dprintf("UUI"));
1751                         add_s(plci, UUI, &ai_parms[2]);
1752                         sig_req(plci, USER_DATA, 0);
1753                 }
1754                 else if (plci->State && ai_parms[3].length)
1755                 {
1756                         /* Facility option */
1757                         dbug(1, dprintf("FAC"));
1758                         add_s(plci, CPN, &msg[0]);
1759                         add_ai(plci, &msg[1]);
1760                         sig_req(plci, FACILITY_REQ, 0);
1761                 }
1762                 else
1763                 {
1764                         Info = _WRONG_STATE;
1765                 }
1766         }
1767         else if ((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1768         {
1769                 /* NCR_Facility option -> send UUI and Keypad too */
1770                 dbug(1, dprintf("NCR_FAC"));
1771                 if ((i = get_plci(a)))
1772                 {
1773                         rc_plci = &a->plci[i - 1];
1774                         appl->NullCREnable = true;
1775                         rc_plci->internal_command = C_NCR_FAC_REQ;
1776                         rc_plci->appl = appl;
1777                         add_p(rc_plci, CAI, "\x01\x80");
1778                         add_p(rc_plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1779                         sig_req(rc_plci, ASSIGN, DSIG_ID);
1780                         send_req(rc_plci);
1781                 }
1782                 else
1783                 {
1784                         Info = _OUT_OF_PLCI;
1785                 }
1786
1787                 if (!Info)
1788                 {
1789                         add_s(rc_plci, CPN, &msg[0]);
1790                         add_ai(rc_plci, &msg[1]);
1791                         sig_req(rc_plci, NCR_FACILITY, 0);
1792                         send_req(rc_plci);
1793                         return false;
1794                         /* for application controlled supplementary services    */
1795                 }
1796         }
1797
1798         if (!rc_plci)
1799         {
1800                 Info = _WRONG_MESSAGE_FORMAT;
1801         }
1802
1803         if (!Info)
1804         {
1805                 send_req(rc_plci);
1806         }
1807         else
1808         {  /* appl is not assigned to a PLCI or error condition */
1809                 dbug(1, dprintf("localInfoCon"));
1810                 sendf(appl,
1811                       _INFO_R | CONFIRM,
1812                       Id,
1813                       Number,
1814                       "w", Info);
1815         }
1816         return false;
1817 }
1818
1819 static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1820                      PLCI *plci, APPL *appl, API_PARSE *msg)
1821 {
1822         dbug(1, dprintf("info_res"));
1823         return false;
1824 }
1825
1826 static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1827                       PLCI *plci, APPL *appl, API_PARSE *msg)
1828 {
1829         word Info;
1830         byte ret;
1831
1832         dbug(1, dprintf("alert_req"));
1833
1834         Info = _WRONG_IDENTIFIER;
1835         ret = false;
1836         if (plci) {
1837                 Info = _ALERT_IGNORED;
1838                 if (plci->State != INC_CON_ALERT) {
1839                         Info = _WRONG_STATE;
1840                         if (plci->State == INC_CON_PENDING) {
1841                                 Info = 0;
1842                                 plci->State = INC_CON_ALERT;
1843                                 add_ai(plci, &msg[0]);
1844                                 sig_req(plci, CALL_ALERT, 0);
1845                                 ret = 1;
1846                         }
1847                 }
1848         }
1849         sendf(appl,
1850               _ALERT_R | CONFIRM,
1851               Id,
1852               Number,
1853               "w", Info);
1854         return ret;
1855 }
1856
1857 static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1858                          PLCI *plci, APPL *appl, API_PARSE *msg)
1859 {
1860         word Info = 0;
1861         word i    = 0;
1862
1863         word selector;
1864         word SSreq;
1865         long relatedPLCIvalue;
1866         DIVA_CAPI_ADAPTER *relatedadapter;
1867         byte *SSparms  = "";
1868         byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1869         byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1870         API_PARSE *parms;
1871         API_PARSE ss_parms[11];
1872         PLCI *rplci;
1873         byte cai[15];
1874         dword d;
1875         API_PARSE dummy;
1876
1877         dbug(1, dprintf("facility_req"));
1878         for (i = 0; i < 9; i++) ss_parms[i].length = 0;
1879
1880         parms = &msg[1];
1881
1882         if (!a)
1883         {
1884                 dbug(1, dprintf("wrong Ctrl"));
1885                 Info = _WRONG_IDENTIFIER;
1886         }
1887
1888         selector = GET_WORD(msg[0].info);
1889
1890         if (!Info)
1891         {
1892                 switch (selector)
1893                 {
1894                 case SELECTOR_HANDSET:
1895                         Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1896                         break;
1897
1898                 case SELECTOR_SU_SERV:
1899                         if (!msg[1].length)
1900                         {
1901                                 Info = _WRONG_MESSAGE_FORMAT;
1902                                 break;
1903                         }
1904                         SSreq = GET_WORD(&(msg[1].info[1]));
1905                         PUT_WORD(&RCparms[1], SSreq);
1906                         SSparms = RCparms;
1907                         switch (SSreq)
1908                         {
1909                         case S_GET_SUPPORTED_SERVICES:
1910                                 if ((i = get_plci(a)))
1911                                 {
1912                                         rplci = &a->plci[i - 1];
1913                                         rplci->appl = appl;
1914                                         add_p(rplci, CAI, "\x01\x80");
1915                                         add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1916                                         sig_req(rplci, ASSIGN, DSIG_ID);
1917                                         send_req(rplci);
1918                                 }
1919                                 else
1920                                 {
1921                                         PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1922                                         SSparms = (byte *)SSstruct;
1923                                         break;
1924                                 }
1925                                 rplci->internal_command = GETSERV_REQ_PEND;
1926                                 rplci->number = Number;
1927                                 rplci->appl = appl;
1928                                 sig_req(rplci, S_SUPPORTED, 0);
1929                                 send_req(rplci);
1930                                 return false;
1931                                 break;
1932
1933                         case S_LISTEN:
1934                                 if (parms->length == 7)
1935                                 {
1936                                         if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1937                                         {
1938                                                 dbug(1, dprintf("format wrong"));
1939                                                 Info = _WRONG_MESSAGE_FORMAT;
1940                                                 break;
1941                                         }
1942                                 }
1943                                 else
1944                                 {
1945                                         Info = _WRONG_MESSAGE_FORMAT;
1946                                         break;
1947                                 }
1948                                 a->Notification_Mask[appl->Id - 1] = GET_DWORD(ss_parms[2].info);
1949                                 if (a->Notification_Mask[appl->Id - 1] & SMASK_MWI) /* MWI active? */
1950                                 {
1951                                         if ((i = get_plci(a)))
1952                                         {
1953                                                 rplci = &a->plci[i - 1];
1954                                                 rplci->appl = appl;
1955                                                 add_p(rplci, CAI, "\x01\x80");
1956                                                 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1957                                                 sig_req(rplci, ASSIGN, DSIG_ID);
1958                                                 send_req(rplci);
1959                                         }
1960                                         else
1961                                         {
1962                                                 break;
1963                                         }
1964                                         rplci->internal_command = GET_MWI_STATE;
1965                                         rplci->number = Number;
1966                                         sig_req(rplci, MWI_POLL, 0);
1967                                         send_req(rplci);
1968                                 }
1969                                 break;
1970
1971                         case S_HOLD:
1972                                 api_parse(&parms->info[1], (word)parms->length, "ws", ss_parms);
1973                                 if (plci && plci->State && plci->SuppState == IDLE)
1974                                 {
1975                                         plci->SuppState = HOLD_REQUEST;
1976                                         plci->command = C_HOLD_REQ;
1977                                         add_s(plci, CAI, &ss_parms[1]);
1978                                         sig_req(plci, CALL_HOLD, 0);
1979                                         send_req(plci);
1980                                         return false;
1981                                 }
1982                                 else Info = 0x3010;                    /* wrong state           */
1983                                 break;
1984                         case S_RETRIEVE:
1985                                 if (plci && plci->State && plci->SuppState == CALL_HELD)
1986                                 {
1987                                         if (Id & EXT_CONTROLLER)
1988                                         {
1989                                                 if (AdvCodecSupport(a, plci, appl, 0))
1990                                                 {
1991                                                         Info = 0x3010;                    /* wrong state           */
1992                                                         break;
1993                                                 }
1994                                         }
1995                                         else plci->tel = 0;
1996
1997                                         plci->SuppState = RETRIEVE_REQUEST;
1998                                         plci->command = C_RETRIEVE_REQ;
1999                                         if (plci->spoofed_msg == SPOOFING_REQUIRED)
2000                                         {
2001                                                 plci->spoofed_msg = CALL_RETRIEVE;
2002                                                 plci->internal_command = BLOCK_PLCI;
2003                                                 plci->command = 0;
2004                                                 dbug(1, dprintf("Spoof"));
2005                                                 return false;
2006                                         }
2007                                         else
2008                                         {
2009                                                 sig_req(plci, CALL_RETRIEVE, 0);
2010                                                 send_req(plci);
2011                                                 return false;
2012                                         }
2013                                 }
2014                                 else Info = 0x3010;                    /* wrong state           */
2015                                 break;
2016                         case S_SUSPEND:
2017                                 if (parms->length)
2018                                 {
2019                                         if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2020                                         {
2021                                                 dbug(1, dprintf("format wrong"));
2022                                                 Info = _WRONG_MESSAGE_FORMAT;
2023                                                 break;
2024                                         }
2025                                 }
2026                                 if (plci && plci->State)
2027                                 {
2028                                         add_s(plci, CAI, &ss_parms[2]);
2029                                         plci->command = SUSPEND_REQ;
2030                                         sig_req(plci, SUSPEND, 0);
2031                                         plci->State = SUSPENDING;
2032                                         send_req(plci);
2033                                 }
2034                                 else Info = 0x3010;                    /* wrong state           */
2035                                 break;
2036
2037                         case S_RESUME:
2038                                 if (!(i = get_plci(a)))
2039                                 {
2040                                         Info = _OUT_OF_PLCI;
2041                                         break;
2042                                 }
2043                                 rplci = &a->plci[i - 1];
2044                                 rplci->appl = appl;
2045                                 rplci->number = Number;
2046                                 rplci->tel = 0;
2047                                 rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2048                                 /* check 'external controller' bit for codec support */
2049                                 if (Id & EXT_CONTROLLER)
2050                                 {
2051                                         if (AdvCodecSupport(a, rplci, appl, 0))
2052                                         {
2053                                                 rplci->Id = 0;
2054                                                 Info = 0x300A;
2055                                                 break;
2056                                         }
2057                                 }
2058                                 if (parms->length)
2059                                 {
2060                                         if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2061                                         {
2062                                                 dbug(1, dprintf("format wrong"));
2063                                                 rplci->Id = 0;
2064                                                 Info = _WRONG_MESSAGE_FORMAT;
2065                                                 break;
2066                                         }
2067                                 }
2068                                 dummy.length = 0;
2069                                 dummy.info = "\x00";
2070                                 add_b1(rplci, &dummy, 0, 0);
2071                                 if (a->Info_Mask[appl->Id - 1] & 0x200)
2072                                 {
2073                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
2074                                         add_p(rplci, LLI, "\x01\x01");
2075                                 }
2076                                 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2077                                 sig_req(rplci, ASSIGN, DSIG_ID);
2078                                 send_req(rplci);
2079                                 add_s(rplci, CAI, &ss_parms[2]);
2080                                 rplci->command = RESUME_REQ;
2081                                 sig_req(rplci, RESUME, 0);
2082                                 rplci->State = RESUMING;
2083                                 send_req(rplci);
2084                                 break;
2085
2086                         case S_CONF_BEGIN: /* Request */
2087                         case S_CONF_DROP:
2088                         case S_CONF_ISOLATE:
2089                         case S_CONF_REATTACH:
2090                                 if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2091                                 {
2092                                         dbug(1, dprintf("format wrong"));
2093                                         Info = _WRONG_MESSAGE_FORMAT;
2094                                         break;
2095                                 }
2096                                 if (plci && plci->State && ((plci->SuppState == IDLE) || (plci->SuppState == CALL_HELD)))
2097                                 {
2098                                         d = GET_DWORD(ss_parms[2].info);
2099                                         if (d >= 0x80)
2100                                         {
2101                                                 dbug(1, dprintf("format wrong"));
2102                                                 Info = _WRONG_MESSAGE_FORMAT;
2103                                                 break;
2104                                         }
2105                                         plci->ptyState = (byte)SSreq;
2106                                         plci->command = 0;
2107                                         cai[0] = 2;
2108                                         switch (SSreq)
2109                                         {
2110                                         case S_CONF_BEGIN:
2111                                                 cai[1] = CONF_BEGIN;
2112                                                 plci->internal_command = CONF_BEGIN_REQ_PEND;
2113                                                 break;
2114                                         case S_CONF_DROP:
2115                                                 cai[1] = CONF_DROP;
2116                                                 plci->internal_command = CONF_DROP_REQ_PEND;
2117                                                 break;
2118                                         case S_CONF_ISOLATE:
2119                                                 cai[1] = CONF_ISOLATE;
2120                                                 plci->internal_command = CONF_ISOLATE_REQ_PEND;
2121                                                 break;
2122                                         case S_CONF_REATTACH:
2123                                                 cai[1] = CONF_REATTACH;
2124                                                 plci->internal_command = CONF_REATTACH_REQ_PEND;
2125                                                 break;
2126                                         }
2127                                         cai[2] = (byte)d; /* Conference Size resp. PartyId */
2128                                         add_p(plci, CAI, cai);
2129                                         sig_req(plci, S_SERVICE, 0);
2130                                         send_req(plci);
2131                                         return false;
2132                                 }
2133                                 else Info = 0x3010;                    /* wrong state           */
2134                                 break;
2135
2136                         case S_ECT:
2137                         case S_3PTY_BEGIN:
2138                         case S_3PTY_END:
2139                         case S_CONF_ADD:
2140                                 if (parms->length == 7)
2141                                 {
2142                                         if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2143                                         {
2144                                                 dbug(1, dprintf("format wrong"));
2145                                                 Info = _WRONG_MESSAGE_FORMAT;
2146                                                 break;
2147                                         }
2148                                 }
2149                                 else if (parms->length == 8) /* workaround for the T-View-S */
2150                                 {
2151                                         if (api_parse(&parms->info[1], (word)parms->length, "wbdb", ss_parms))
2152                                         {
2153                                                 dbug(1, dprintf("format wrong"));
2154                                                 Info = _WRONG_MESSAGE_FORMAT;
2155                                                 break;
2156                                         }
2157                                 }
2158                                 else
2159                                 {
2160                                         Info = _WRONG_MESSAGE_FORMAT;
2161                                         break;
2162                                 }
2163                                 if (!msg[1].length)
2164                                 {
2165                                         Info = _WRONG_MESSAGE_FORMAT;
2166                                         break;
2167                                 }
2168                                 if (!plci)
2169                                 {
2170                                         Info = _WRONG_IDENTIFIER;
2171                                         break;
2172                                 }
2173                                 relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2174                                 relatedPLCIvalue &= 0x0000FFFF;
2175                                 dbug(1, dprintf("PTY/ECT/addCONF,relPLCI=%lx", relatedPLCIvalue));
2176                                 /* controller starts with 0 up to (max_adapter - 1) */
2177                                 if (((relatedPLCIvalue & 0x7f) == 0)
2178                                     || (MapController((byte)(relatedPLCIvalue & 0x7f)) == 0)
2179                                     || (MapController((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2180                                 {
2181                                         if (SSreq == S_3PTY_END)
2182                                         {
2183                                                 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2184                                                 rplci = plci;
2185                                         }
2186                                         else
2187                                         {
2188                                                 Info = 0x3010;                    /* wrong state           */
2189                                                 break;
2190                                         }
2191                                 }
2192                                 else
2193                                 {
2194                                         relatedadapter = &adapter[MapController((byte)(relatedPLCIvalue & 0x7f)) - 1];
2195                                         relatedPLCIvalue >>= 8;
2196                                         /* find PLCI PTR*/
2197                                         for (i = 0, rplci = NULL; i < relatedadapter->max_plci; i++)
2198                                         {
2199                                                 if (relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2200                                                 {
2201                                                         rplci = &relatedadapter->plci[i];
2202                                                 }
2203                                         }
2204                                         if (!rplci || !relatedPLCIvalue)
2205                                         {
2206                                                 if (SSreq == S_3PTY_END)
2207                                                 {
2208                                                         dbug(1, dprintf("use 2nd PLCI=PLCI"));
2209                                                         rplci = plci;
2210                                                 }
2211                                                 else
2212                                                 {
2213                                                         Info = 0x3010;                    /* wrong state           */
2214                                                         break;
2215                                                 }
2216                                         }
2217                                 }
2218 /*
2219   dbug(1, dprintf("rplci:%x", rplci));
2220   dbug(1, dprintf("plci:%x", plci));
2221   dbug(1, dprintf("rplci->ptyState:%x", rplci->ptyState));
2222   dbug(1, dprintf("plci->ptyState:%x", plci->ptyState));
2223   dbug(1, dprintf("SSreq:%x", SSreq));
2224   dbug(1, dprintf("rplci->internal_command:%x", rplci->internal_command));
2225   dbug(1, dprintf("rplci->appl:%x", rplci->appl));
2226   dbug(1, dprintf("rplci->Id:%x", rplci->Id));
2227 */
2228                                 /* send PTY/ECT req, cannot check all states because of US stuff */
2229                                 if (!rplci->internal_command && rplci->appl)
2230                                 {
2231                                         plci->command = 0;
2232                                         rplci->relatedPTYPLCI = plci;
2233                                         plci->relatedPTYPLCI = rplci;
2234                                         rplci->ptyState = (byte)SSreq;
2235                                         if (SSreq == S_ECT)
2236                                         {
2237                                                 rplci->internal_command = ECT_REQ_PEND;
2238                                                 cai[1] = ECT_EXECUTE;
2239
2240                                                 rplci->vswitchstate = 0;
2241                                                 rplci->vsprot = 0;
2242                                                 rplci->vsprotdialect = 0;
2243                                                 plci->vswitchstate = 0;
2244                                                 plci->vsprot = 0;
2245                                                 plci->vsprotdialect = 0;
2246
2247                                         }
2248                                         else if (SSreq == S_CONF_ADD)
2249                                         {
2250                                                 rplci->internal_command = CONF_ADD_REQ_PEND;
2251                                                 cai[1] = CONF_ADD;
2252                                         }
2253                                         else
2254                                         {
2255                                                 rplci->internal_command = PTY_REQ_PEND;
2256                                                 cai[1] = (byte)(SSreq - 3);
2257                                         }
2258                                         rplci->number = Number;
2259                                         if (plci != rplci) /* explicit invocation */
2260                                         {
2261                                                 cai[0] = 2;
2262                                                 cai[2] = plci->Sig.Id;
2263                                                 dbug(1, dprintf("explicit invocation"));
2264                                         }
2265                                         else
2266                                         {
2267                                                 dbug(1, dprintf("implicit invocation"));
2268                                                 cai[0] = 1;
2269                                         }
2270                                         add_p(rplci, CAI, cai);
2271                                         sig_req(rplci, S_SERVICE, 0);
2272                                         send_req(rplci);
2273                                         return false;
2274                                 }
2275                                 else
2276                                 {
2277                                         dbug(0, dprintf("Wrong line"));
2278                                         Info = 0x3010;                    /* wrong state           */
2279                                         break;
2280                                 }
2281                                 break;
2282
2283                         case S_CALL_DEFLECTION:
2284                                 if (api_parse(&parms->info[1], (word)parms->length, "wbwss", ss_parms))
2285                                 {
2286                                         dbug(1, dprintf("format wrong"));
2287                                         Info = _WRONG_MESSAGE_FORMAT;
2288                                         break;
2289                                 }
2290                                 if (!plci)
2291                                 {
2292                                         Info = _WRONG_IDENTIFIER;
2293                                         break;
2294                                 }
2295                                 /* reuse unused screening indicator */
2296                                 ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2297                                 plci->command = 0;
2298                                 plci->internal_command = CD_REQ_PEND;
2299                                 appl->CDEnable = true;
2300                                 cai[0] = 1;
2301                                 cai[1] = CALL_DEFLECTION;
2302                                 add_p(plci, CAI, cai);
2303                                 add_p(plci, CPN, ss_parms[3].info);
2304                                 sig_req(plci, S_SERVICE, 0);
2305                                 send_req(plci);
2306                                 return false;
2307                                 break;
2308
2309                         case S_CALL_FORWARDING_START:
2310                                 if (api_parse(&parms->info[1], (word)parms->length, "wbdwwsss", ss_parms))
2311                                 {
2312                                         dbug(1, dprintf("format wrong"));
2313                                         Info = _WRONG_MESSAGE_FORMAT;
2314                                         break;
2315                                 }
2316
2317                                 if ((i = get_plci(a)))
2318                                 {
2319                                         rplci = &a->plci[i - 1];
2320                                         rplci->appl = appl;
2321                                         add_p(rplci, CAI, "\x01\x80");
2322                                         add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2323                                         sig_req(rplci, ASSIGN, DSIG_ID);
2324                                         send_req(rplci);
2325                                 }
2326                                 else
2327                                 {
2328                                         Info = _OUT_OF_PLCI;
2329                                         break;
2330                                 }
2331
2332                                 /* reuse unused screening indicator */
2333                                 rplci->internal_command = CF_START_PEND;
2334                                 rplci->appl = appl;
2335                                 rplci->number = Number;
2336                                 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2337                                 cai[0] = 2;
2338                                 cai[1] = 0x70 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2339                                 cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2340                                 add_p(rplci, CAI, cai);
2341                                 add_p(rplci, OAD, ss_parms[5].info);
2342                                 add_p(rplci, CPN, ss_parms[6].info);
2343                                 sig_req(rplci, S_SERVICE, 0);
2344                                 send_req(rplci);
2345                                 return false;
2346                                 break;
2347
2348                         case S_INTERROGATE_DIVERSION:
2349                         case S_INTERROGATE_NUMBERS:
2350                         case S_CALL_FORWARDING_STOP:
2351                         case S_CCBS_REQUEST:
2352                         case S_CCBS_DEACTIVATE:
2353                         case S_CCBS_INTERROGATE:
2354                                 switch (SSreq)
2355                                 {
2356                                 case S_INTERROGATE_NUMBERS:
2357                                         if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2358                                         {
2359                                                 dbug(0, dprintf("format wrong"));
2360                                                 Info = _WRONG_MESSAGE_FORMAT;
2361                                         }
2362                                         break;
2363                                 case S_CCBS_REQUEST:
2364                                 case S_CCBS_DEACTIVATE:
2365                                         if (api_parse(&parms->info[1], (word)parms->length, "wbdw", ss_parms))
2366                                         {
2367                                                 dbug(0, dprintf("format wrong"));
2368                                                 Info = _WRONG_MESSAGE_FORMAT;
2369                                         }
2370                                         break;
2371                                 case S_CCBS_INTERROGATE:
2372                                         if (api_parse(&parms->info[1], (word)parms->length, "wbdws", ss_parms))
2373                                         {
2374                                                 dbug(0, dprintf("format wrong"));
2375                                                 Info = _WRONG_MESSAGE_FORMAT;
2376                                         }
2377                                         break;
2378                                 default:
2379                                         if (api_parse(&parms->info[1], (word)parms->length, "wbdwws", ss_parms))
2380                                         {
2381                                                 dbug(0, dprintf("format wrong"));
2382                                                 Info = _WRONG_MESSAGE_FORMAT;
2383                                                 break;
2384                                         }
2385                                         break;
2386                                 }
2387
2388                                 if (Info) break;
2389                                 if ((i = get_plci(a)))
2390                                 {
2391                                         rplci = &a->plci[i - 1];
2392                                         switch (SSreq)
2393                                         {
2394                                         case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2395                                                 cai[1] = 0x60 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2396                                                 rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2397                                                 break;
2398                                         case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2399                                                 cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2400                                                 rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2401                                                 break;
2402                                         case S_CALL_FORWARDING_STOP:
2403                                                 rplci->internal_command = CF_STOP_PEND;
2404                                                 cai[1] = 0x80 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2405                                                 break;
2406                                         case S_CCBS_REQUEST:
2407                                                 cai[1] = CCBS_REQUEST;
2408                                                 rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2409                                                 break;
2410                                         case S_CCBS_DEACTIVATE:
2411                                                 cai[1] = CCBS_DEACTIVATE;
2412                                                 rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2413                                                 break;
2414                                         case S_CCBS_INTERROGATE:
2415                                                 cai[1] = CCBS_INTERROGATE;
2416                                                 rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2417                                                 break;
2418                                         default:
2419                                                 cai[1] = 0;
2420                                                 break;
2421                                         }
2422                                         rplci->appl = appl;
2423                                         rplci->number = Number;
2424                                         add_p(rplci, CAI, "\x01\x80");
2425                                         add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2426                                         sig_req(rplci, ASSIGN, DSIG_ID);
2427                                         send_req(rplci);
2428                                 }
2429                                 else
2430                                 {
2431                                         Info = _OUT_OF_PLCI;
2432                                         break;
2433                                 }
2434
2435                                 appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2436                                 switch (SSreq)
2437                                 {
2438                                 case S_INTERROGATE_NUMBERS:
2439                                         cai[0] = 1;
2440                                         add_p(rplci, CAI, cai);
2441                                         break;
2442                                 case S_CCBS_REQUEST:
2443                                 case S_CCBS_DEACTIVATE:
2444                                         cai[0] = 3;
2445                                         PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2446                                         add_p(rplci, CAI, cai);
2447                                         break;
2448                                 case S_CCBS_INTERROGATE:
2449                                         cai[0] = 3;
2450                                         PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2451                                         add_p(rplci, CAI, cai);
2452                                         add_p(rplci, OAD, ss_parms[4].info);
2453                                         break;
2454                                 default:
2455                                         cai[0] = 2;
2456                                         cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2457                                         add_p(rplci, CAI, cai);
2458                                         add_p(rplci, OAD, ss_parms[5].info);
2459                                         break;
2460                                 }
2461
2462                                 sig_req(rplci, S_SERVICE, 0);
2463                                 send_req(rplci);
2464                                 return false;
2465                                 break;
2466
2467                         case S_MWI_ACTIVATE:
2468                                 if (api_parse(&parms->info[1], (word)parms->length, "wbwdwwwssss", ss_parms))
2469                                 {
2470                                         dbug(1, dprintf("format wrong"));
2471                                         Info = _WRONG_MESSAGE_FORMAT;
2472                                         break;
2473                                 }
2474                                 if (!plci)
2475                                 {
2476                                         if ((i = get_plci(a)))
2477                                         {
2478                                                 rplci = &a->plci[i - 1];
2479                                                 rplci->appl = appl;
2480                                                 rplci->cr_enquiry = true;
2481                                                 add_p(rplci, CAI, "\x01\x80");
2482                                                 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2483                                                 sig_req(rplci, ASSIGN, DSIG_ID);
2484                                                 send_req(rplci);
2485                                         }
2486                                         else
2487                                         {
2488                                                 Info = _OUT_OF_PLCI;
2489                                                 break;
2490                                         }
2491                                 }
2492                                 else
2493                                 {
2494                                         rplci = plci;
2495                                         rplci->cr_enquiry = false;
2496                                 }
2497
2498                                 rplci->command = 0;
2499                                 rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2500                                 rplci->appl = appl;
2501                                 rplci->number = Number;
2502
2503                                 cai[0] = 13;
2504                                 cai[1] = ACTIVATION_MWI; /* Function */
2505                                 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2506                                 PUT_DWORD(&cai[4], GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2507                                 PUT_WORD(&cai[8], GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2508                                 PUT_WORD(&cai[10], GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2509                                 PUT_WORD(&cai[12], GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2510                                 add_p(rplci, CAI, cai);
2511                                 add_p(rplci, CPN, ss_parms[7].info); /* Receiving User Number */
2512                                 add_p(rplci, OAD, ss_parms[8].info); /* Controlling User Number */
2513                                 add_p(rplci, OSA, ss_parms[9].info); /* Controlling User Provided Number */
2514                                 add_p(rplci, UID, ss_parms[10].info); /* Time */
2515                                 sig_req(rplci, S_SERVICE, 0);
2516                                 send_req(rplci);
2517                                 return false;
2518
2519                         case S_MWI_DEACTIVATE:
2520                                 if (api_parse(&parms->info[1], (word)parms->length, "wbwwss", ss_parms))
2521                                 {
2522                                         dbug(1, dprintf("format wrong"));
2523                                         Info = _WRONG_MESSAGE_FORMAT;
2524                                         break;
2525                                 }
2526                                 if (!plci)
2527                                 {
2528                                         if ((i = get_plci(a)))
2529                                         {
2530                                                 rplci = &a->plci[i - 1];
2531                                                 rplci->appl = appl;
2532                                                 rplci->cr_enquiry = true;
2533                                                 add_p(rplci, CAI, "\x01\x80");
2534                                                 add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2535                                                 sig_req(rplci, ASSIGN, DSIG_ID);
2536                                                 send_req(rplci);
2537                                         }
2538                                         else
2539                                         {
2540                                                 Info = _OUT_OF_PLCI;
2541                                                 break;
2542                                         }
2543                                 }
2544                                 else
2545                                 {
2546                                         rplci = plci;
2547                                         rplci->cr_enquiry = false;
2548                                 }
2549
2550                                 rplci->command = 0;
2551                                 rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2552                                 rplci->appl = appl;
2553                                 rplci->number = Number;
2554
2555                                 cai[0] = 5;
2556                                 cai[1] = DEACTIVATION_MWI; /* Function */
2557                                 PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2558                                 PUT_WORD(&cai[4], GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2559                                 add_p(rplci, CAI, cai);
2560                                 add_p(rplci, CPN, ss_parms[4].info); /* Receiving User Number */
2561                                 add_p(rplci, OAD, ss_parms[5].info); /* Controlling User Number */
2562                                 sig_req(rplci, S_SERVICE, 0);
2563                                 send_req(rplci);
2564                                 return false;
2565
2566                         default:
2567                                 Info = 0x300E;  /* not supported */
2568                                 break;
2569                         }
2570                         break; /* case SELECTOR_SU_SERV: end */
2571
2572
2573                 case SELECTOR_DTMF:
2574                         return (dtmf_request(Id, Number, a, plci, appl, msg));
2575
2576
2577
2578                 case SELECTOR_LINE_INTERCONNECT:
2579                         return (mixer_request(Id, Number, a, plci, appl, msg));
2580
2581
2582
2583                 case PRIV_SELECTOR_ECHO_CANCELLER:
2584                         appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2585                         return (ec_request(Id, Number, a, plci, appl, msg));
2586
2587                 case SELECTOR_ECHO_CANCELLER:
2588                         appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2589                         return (ec_request(Id, Number, a, plci, appl, msg));
2590
2591
2592                 case SELECTOR_V42BIS:
2593                 default:
2594                         Info = _FACILITY_NOT_SUPPORTED;
2595                         break;
2596                 } /* end of switch (selector) */
2597         }
2598
2599         dbug(1, dprintf("SendFacRc"));
2600         sendf(appl,
2601               _FACILITY_R | CONFIRM,
2602               Id,
2603               Number,
2604               "wws", Info, selector, SSparms);
2605         return false;
2606 }
2607
2608 static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2609                          PLCI *plci, APPL *appl, API_PARSE *msg)
2610 {
2611         dbug(1, dprintf("facility_res"));
2612         return false;
2613 }
2614
2615 static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2616                            PLCI *plci, APPL *appl, API_PARSE *parms)
2617 {
2618         word Info = 0;
2619         byte req;
2620         byte len;
2621         word w;
2622         word fax_control_bits, fax_feature_bits, fax_info_change;
2623         API_PARSE *ncpi;
2624         byte pvc[2];
2625
2626         API_PARSE fax_parms[9];
2627         word i;
2628
2629
2630         dbug(1, dprintf("connect_b3_req"));
2631         if (plci)
2632         {
2633                 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2634                     || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2635                 {
2636                         Info = _WRONG_STATE;
2637                 }
2638                 else
2639                 {
2640                         /* local reply if assign unsuccessful
2641                            or B3 protocol allows only one layer 3 connection
2642                            and already connected
2643                            or B2 protocol not any LAPD
2644                            and connect_b3_req contradicts originate/answer direction */
2645                         if (!plci->NL.Id
2646                             || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2647                                 && ((plci->channels != 0)
2648                                     || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2649                                         && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2650                         {
2651                                 dbug(1, dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2652                                                 plci->channels, plci->NL.Id, plci->call_dir, plci->SuppState));
2653                                 Info = _WRONG_STATE;
2654                                 sendf(appl,
2655                                       _CONNECT_B3_R | CONFIRM,
2656                                       Id,
2657                                       Number,
2658                                       "w", Info);
2659                                 return false;
2660                         }
2661                         plci->requested_options_conn = 0;
2662
2663                         req = N_CONNECT;
2664                         ncpi = &parms[0];
2665                         if (plci->B3_prot == 2 || plci->B3_prot == 3)
2666                         {
2667                                 if (ncpi->length > 2)
2668                                 {
2669                                         /* check for PVC */
2670                                         if (ncpi->info[2] || ncpi->info[3])
2671                                         {
2672                                                 pvc[0] = ncpi->info[3];
2673                                                 pvc[1] = ncpi->info[2];
2674                                                 add_d(plci, 2, pvc);
2675                                                 req = N_RESET;
2676                                         }
2677                                         else
2678                                         {
2679                                                 if (ncpi->info[1] & 1) req = N_CONNECT | N_D_BIT;
2680                                                 add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2681                                         }
2682                                 }
2683                         }
2684                         else if (plci->B3_prot == 5)
2685                         {
2686                                 if (plci->NL.Id && !plci->nl_remove_id)
2687                                 {
2688                                         fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2689                                         fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2690                                         if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2691                                             || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2692                                         {
2693                                                 len = offsetof(T30_INFO, universal_6);
2694                                                 fax_info_change = false;
2695                                                 if (ncpi->length >= 4)
2696                                                 {
2697                                                         w = GET_WORD(&ncpi->info[3]);
2698                                                         if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2699                                                         {
2700                                                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2701                                                                         (byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2702                                                                                ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2703                                                                 fax_info_change = true;
2704                                                         }
2705                                                         fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2706                                                         if (w & 0x0002)  /* Fax-polling request */
2707                                                                 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2708                                                         if ((w & 0x0004) /* Request to send / poll another document */
2709                                                             && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2710                                                         {
2711                                                                 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2712                                                         }
2713                                                         if (ncpi->length >= 6)
2714                                                         {
2715                                                                 w = GET_WORD(&ncpi->info[5]);
2716                                                                 if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2717                                                                 {
2718                                                                         ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2719                                                                         fax_info_change = true;
2720                                                                 }
2721
2722                                                                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2723                                                                     && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2724                                                                 {
2725                                                                         plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2726                                                                 }
2727                                                                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2728                                                                     && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2729                                                                 {
2730                                                                         plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2731                                                                 }
2732                                                                 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2733                                                                                       T30_CONTROL_BIT_ACCEPT_PASSWORD);
2734                                                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2735                                                                     & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2736                                                                 {
2737                                                                         if (api_parse(&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2738                                                                                 Info = _WRONG_MESSAGE_FORMAT;
2739                                                                         else
2740                                                                         {
2741                                                                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2742                                                                                     & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2743                                                                                 {
2744                                                                                         fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2745                                                                                         if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2746                                                                                                 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2747                                                                                 }
2748                                                                                 w = fax_parms[4].length;
2749                                                                                 if (w > 20)
2750                                                                                         w = 20;
2751                                                                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2752                                                                                 for (i = 0; i < w; i++)
2753                                                                                         ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1 + i];
2754                                                                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2755                                                                                 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2756                                                                                 w = fax_parms[5].length;
2757                                                                                 if (w > 20)
2758                                                                                         w = 20;
2759                                                                                 plci->fax_connect_info_buffer[len++] = (byte) w;
2760                                                                                 for (i = 0; i < w; i++)
2761                                                                                         plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1 + i];
2762                                                                                 w = fax_parms[6].length;
2763                                                                                 if (w > 20)
2764                                                                                         w = 20;
2765                                                                                 plci->fax_connect_info_buffer[len++] = (byte) w;
2766                                                                                 for (i = 0; i < w; i++)
2767                                                                                         plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1 + i];
2768                                                                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2769                                                                                     & (1L << PRIVATE_FAX_NONSTANDARD))
2770                                                                                 {
2771                                                                                         if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2772                                                                                         {
2773                                                                                                 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2774                                                                                                 plci->fax_connect_info_buffer[len++] = 0;
2775                                                                                         }
2776                                                                                         else
2777                                                                                         {
2778                                                                                                 if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2779                                                                                                         plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2780                                                                                                 plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2781                                                                                                 for (i = 0; i < fax_parms[7].length; i++)
2782                                                                                                         plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2783                                                                                         }
2784                                                                                 }
2785                                                                         }
2786                                                                 }
2787                                                                 else
2788                                                                 {
2789                                                                         len = offsetof(T30_INFO, universal_6);
2790                                                                 }
2791                                                                 fax_info_change = true;
2792
2793                                                         }
2794                                                         if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2795                                                         {
2796                                                                 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2797                                                                 fax_info_change = true;
2798                                                         }
2799                                                 }
2800                                                 if (Info == GOOD)
2801                                                 {
2802                                                         plci->fax_connect_info_length = len;
2803                                                         if (fax_info_change)
2804                                                         {
2805                                                                 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2806                                                                 {
2807                                                                         start_internal_command(Id, plci, fax_connect_info_command);
2808                                                                         return false;
2809                                                                 }
2810                                                                 else
2811                                                                 {
2812                                                                         start_internal_command(Id, plci, fax_adjust_b23_command);
2813                                                                         return false;
2814                                                                 }
2815                                                         }
2816                                                 }
2817                                         }
2818                                         else  Info = _WRONG_STATE;
2819                                 }
2820                                 else  Info = _WRONG_STATE;
2821                         }
2822
2823                         else if (plci->B3_prot == B3_RTP)
2824                         {
2825                                 plci->internal_req_buffer[0] = ncpi->length + 1;
2826                                 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2827                                 for (w = 0; w < ncpi->length; w++)
2828                                         plci->internal_req_buffer[2 + w] = ncpi->info[1 + w];
2829                                 start_internal_command(Id, plci, rtp_connect_b3_req_command);
2830                                 return false;
2831                         }
2832
2833                         if (!Info)
2834                         {
2835                                 nl_req_ncci(plci, req, 0);
2836                                 return 1;
2837                         }
2838                 }
2839         }
2840         else Info = _WRONG_IDENTIFIER;
2841
2842         sendf(appl,
2843               _CONNECT_B3_R | CONFIRM,
2844               Id,
2845               Number,
2846               "w", Info);
2847         return false;
2848 }
2849
2850 static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2851                            PLCI *plci, APPL *appl, API_PARSE *parms)
2852 {
2853         word ncci;
2854         API_PARSE *ncpi;
2855         byte req;
2856
2857         word w;
2858
2859
2860         API_PARSE fax_parms[9];
2861         word i;
2862         byte len;
2863
2864
2865         dbug(1, dprintf("connect_b3_res"));
2866
2867         ncci = (word)(Id >> 16);
2868         if (plci && ncci) {
2869                 if (a->ncci_state[ncci] == INC_CON_PENDING) {
2870                         if (GET_WORD(&parms[0].info[0]) != 0)
2871                         {
2872                                 a->ncci_state[ncci] = OUTG_REJ_PENDING;
2873                                 channel_request_xon(plci, a->ncci_ch[ncci]);
2874                                 channel_xmit_xon(plci);
2875                                 cleanup_ncci_data(plci, ncci);
2876                                 nl_req_ncci(plci, N_DISC, (byte)ncci);
2877                                 return 1;
2878                         }
2879                         a->ncci_state[ncci] = INC_ACT_PENDING;
2880
2881                         req = N_CONNECT_ACK;
2882                         ncpi = &parms[1];
2883                         if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2884                         {
2885
2886                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
2887                                     & (1L << PRIVATE_FAX_NONSTANDARD))
2888                                 {
2889                                         if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2890                                             && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2891                                             && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2892                                         {
2893                                                 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2894                                                 if (plci->fax_connect_info_length < len)
2895                                                 {
2896                                                         ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2897                                                         ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2898                                                 }
2899                                                 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2900                                                 {
2901                                                         dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2902                                                 }
2903                                                 else
2904                                                 {
2905                                                         if (plci->fax_connect_info_length <= len)
2906                                                                 plci->fax_connect_info_buffer[len] = 0;
2907                                                         len += 1 + plci->fax_connect_info_buffer[len];
2908                                                         if (plci->fax_connect_info_length <= len)
2909                                                                 plci->fax_connect_info_buffer[len] = 0;
2910                                                         len += 1 + plci->fax_connect_info_buffer[len];
2911                                                         if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2912                                                                 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2913                                                         plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2914                                                         for (i = 0; i < fax_parms[7].length; i++)
2915                                                                 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2916                                                 }
2917                                                 plci->fax_connect_info_length = len;
2918                                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2919                                                 start_internal_command(Id, plci, fax_connect_ack_command);
2920                                                 return false;
2921                                         }
2922                                 }
2923
2924                                 nl_req_ncci(plci, req, (byte)ncci);
2925                                 if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2926                                     && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2927                                 {
2928                                         if (plci->B3_prot == 4)
2929                                                 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2930                                         else
2931                                                 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
2932                                         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2933                                 }
2934                         }
2935
2936                         else if (plci->B3_prot == B3_RTP)
2937                         {
2938                                 plci->internal_req_buffer[0] = ncpi->length + 1;
2939                                 plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2940                                 for (w = 0; w < ncpi->length; w++)
2941                                         plci->internal_req_buffer[2 + w] = ncpi->info[1+w];
2942                                 start_internal_command(Id, plci, rtp_connect_b3_res_command);
2943                                 return false;
2944                         }
2945
2946                         else
2947                         {
2948                                 if (ncpi->length > 2) {
2949                                         if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
2950                                         add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2951                                 }
2952                                 nl_req_ncci(plci, req, (byte)ncci);
2953                                 sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2954                                 if (plci->adjust_b_restore)
2955                                 {
2956                                         plci->adjust_b_restore = false;
2957                                         start_internal_command(Id, plci, adjust_b_restore);
2958                                 }
2959                         }
2960                         return 1;
2961                 }
2962         }
2963         return false;
2964 }
2965
2966 static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2967                              PLCI *plci, APPL *appl, API_PARSE *parms)
2968 {
2969         word ncci;
2970
2971         ncci = (word)(Id >> 16);
2972         dbug(1, dprintf("connect_b3_a_res(ncci=0x%x)", ncci));
2973
2974         if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2975             && (plci->State != OUTG_DIS_PENDING))
2976         {
2977                 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
2978                         a->ncci_state[ncci] = CONNECTED;
2979                         if (plci->State != INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2980                         channel_request_xon(plci, a->ncci_ch[ncci]);
2981                         channel_xmit_xon(plci);
2982                 }
2983         }
2984         return false;
2985 }
2986
2987 static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2988                               PLCI *plci, APPL *appl, API_PARSE *parms)
2989 {
2990         word Info;
2991         word ncci;
2992         API_PARSE *ncpi;
2993
2994         dbug(1, dprintf("disconnect_b3_req"));
2995
2996         Info = _WRONG_IDENTIFIER;
2997         ncci = (word)(Id >> 16);
2998         if (plci && ncci)
2999         {
3000                 Info = _WRONG_STATE;
3001                 if ((a->ncci_state[ncci] == CONNECTED)
3002                     || (a->ncci_state[ncci] == OUTG_CON_PENDING)
3003                     || (a->ncci_state[ncci] == INC_CON_PENDING)
3004                     || (a->ncci_state[ncci] == INC_ACT_PENDING))
3005                 {
3006                         a->ncci_state[ncci] = OUTG_DIS_PENDING;
3007                         channel_request_xon(plci, a->ncci_ch[ncci]);
3008                         channel_xmit_xon(plci);
3009
3010                         if (a->ncci[ncci].data_pending
3011                             && ((plci->B3_prot == B3_TRANSPARENT)
3012                                 || (plci->B3_prot == B3_T30)
3013                                 || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3014                         {
3015                                 plci->send_disc = (byte)ncci;
3016                                 plci->command = 0;
3017                                 return false;
3018                         }
3019                         else
3020                         {
3021                                 cleanup_ncci_data(plci, ncci);
3022
3023                                 if (plci->B3_prot == 2 || plci->B3_prot == 3)
3024                                 {
3025                                         ncpi = &parms[0];
3026                                         if (ncpi->length > 3)
3027                                         {
3028                                                 add_d(plci, (word)(ncpi->length - 3), (byte *)&(ncpi->info[4]));
3029                                         }
3030                                 }
3031                                 nl_req_ncci(plci, N_DISC, (byte)ncci);
3032                         }
3033                         return 1;
3034                 }
3035         }
3036         sendf(appl,
3037               _DISCONNECT_B3_R | CONFIRM,
3038               Id,
3039               Number,
3040               "w", Info);
3041         return false;
3042 }
3043
3044 static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3045                               PLCI *plci, APPL *appl, API_PARSE *parms)
3046 {
3047         word ncci;
3048         word i;
3049
3050         ncci = (word)(Id >> 16);
3051         dbug(1, dprintf("disconnect_b3_res(ncci=0x%x", ncci));
3052         if (plci && ncci) {
3053                 plci->requested_options_conn = 0;
3054                 plci->fax_connect_info_length = 0;
3055                 plci->ncpi_state = 0x00;
3056                 if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3057                     && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3058                 {
3059                         plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3060                 }
3061                 for (i = 0; i < MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i] != (byte)ncci; i++);
3062                 if (i < MAX_CHANNELS_PER_PLCI) {
3063                         if (plci->channels)plci->channels--;
3064                         for (; i < MAX_CHANNELS_PER_PLCI - 1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i + 1];
3065                         plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI - 1] = 0;
3066
3067                         ncci_free_receive_buffers(plci, ncci);
3068
3069                         if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
3070                                 if (plci->State == SUSPENDING) {
3071                                         sendf(plci->appl,
3072                                               _FACILITY_I,
3073                                               Id & 0xffffL,
3074                                               0,
3075                                               "ws", (word)3, "\x03\x04\x00\x00");
3076                                         sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3077                                 }
3078                                 plci_remove(plci);
3079                                 plci->State = IDLE;
3080                         }
3081                 }
3082                 else
3083                 {
3084                         if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3085                             && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3086                             && (a->ncci_state[ncci] == INC_DIS_PENDING))
3087                         {
3088                                 ncci_free_receive_buffers(plci, ncci);
3089
3090                                 nl_req_ncci(plci, N_EDATA, (byte)ncci);
3091
3092                                 plci->adapter->ncci_state[ncci] = IDLE;
3093                                 start_internal_command(Id, plci, fax_disconnect_command);
3094                                 return 1;
3095                         }
3096                 }
3097         }
3098         return false;
3099 }
3100
3101 static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3102                         PLCI *plci, APPL *appl, API_PARSE *parms)
3103 {
3104         NCCI *ncci_ptr;
3105         DATA_B3_DESC *data;
3106         word Info;
3107         word ncci;
3108         word i;
3109
3110         dbug(1, dprintf("data_b3_req"));
3111
3112         Info = _WRONG_IDENTIFIER;
3113         ncci = (word)(Id >> 16);
3114         dbug(1, dprintf("ncci=0x%x, plci=0x%x", ncci, plci));
3115
3116         if (plci && ncci)
3117         {
3118                 Info = _WRONG_STATE;
3119                 if ((a->ncci_state[ncci] == CONNECTED)
3120                     || (a->ncci_state[ncci] == INC_ACT_PENDING))
3121                 {
3122                         /* queue data */
3123                         ncci_ptr = &(a->ncci[ncci]);
3124                         i = ncci_ptr->data_out + ncci_ptr->data_pending;
3125                         if (i >= MAX_DATA_B3)
3126                                 i -= MAX_DATA_B3;
3127                         data = &(ncci_ptr->DBuffer[i]);
3128                         data->Number = Number;
3129                         if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3130                             && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3131                         {
3132
3133                                 data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3134
3135                         }
3136                         else
3137                                 data->P = TransmitBufferSet(appl, *(dword *)parms[0].info);
3138                         data->Length = GET_WORD(parms[1].info);
3139                         data->Handle = GET_WORD(parms[2].info);
3140                         data->Flags = GET_WORD(parms[3].info);
3141                         (ncci_ptr->data_pending)++;
3142
3143                         /* check for delivery confirmation */
3144                         if (data->Flags & 0x0004)
3145                         {
3146                                 i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3147                                 if (i >= MAX_DATA_ACK)
3148                                         i -= MAX_DATA_ACK;
3149                                 ncci_ptr->DataAck[i].Number = data->Number;
3150                                 ncci_ptr->DataAck[i].Handle = data->Handle;
3151                                 (ncci_ptr->data_ack_pending)++;
3152                         }
3153
3154                         send_data(plci);
3155                         return false;
3156                 }
3157         }
3158         if (appl)
3159         {
3160                 if (plci)
3161                 {
3162                         if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3163                             && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3164                         {
3165
3166                                 TransmitBufferFree(appl, (byte *)(long)(*((dword *)(parms[0].info))));
3167
3168                         }
3169                 }
3170                 sendf(appl,
3171                       _DATA_B3_R | CONFIRM,
3172                       Id,
3173                       Number,
3174                       "ww", GET_WORD(parms[2].info), Info);
3175         }
3176         return false;
3177 }
3178
3179 static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3180                         PLCI *plci, APPL *appl, API_PARSE *parms)
3181 {
3182         word n;
3183         word ncci;
3184         word NCCIcode;
3185
3186         dbug(1, dprintf("data_b3_res"));
3187
3188         ncci = (word)(Id >> 16);
3189         if (plci && ncci) {
3190                 n = GET_WORD(parms[0].info);
3191                 dbug(1, dprintf("free(%d)", n));
3192                 NCCIcode = ncci | (((word) a->Id) << 8);
3193                 if (n < appl->MaxBuffer &&
3194                     appl->DataNCCI[n] == NCCIcode &&
3195                     (byte)(appl->DataFlags[n] >> 8) == plci->Id) {
3196                         dbug(1, dprintf("found"));
3197                         appl->DataNCCI[n] = 0;
3198
3199                         if (channel_can_xon(plci, a->ncci_ch[ncci])) {
3200                                 channel_request_xon(plci, a->ncci_ch[ncci]);
3201                         }
3202                         channel_xmit_xon(plci);
3203
3204                         if (appl->DataFlags[n] & 4) {
3205                                 nl_req_ncci(plci, N_DATA_ACK, (byte)ncci);
3206                                 return 1;
3207                         }
3208                 }
3209         }
3210         return false;
3211 }
3212
3213 static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3214                          PLCI *plci, APPL *appl, API_PARSE *parms)
3215 {
3216         word Info;
3217         word ncci;
3218
3219         dbug(1, dprintf("reset_b3_req"));
3220
3221         Info = _WRONG_IDENTIFIER;
3222         ncci = (word)(Id >> 16);
3223         if (plci && ncci)
3224         {
3225                 Info = _WRONG_STATE;
3226                 switch (plci->B3_prot)
3227                 {
3228                 case B3_ISO8208:
3229                 case B3_X25_DCE:
3230                         if (a->ncci_state[ncci] == CONNECTED)
3231                         {
3232                                 nl_req_ncci(plci, N_RESET, (byte)ncci);
3233                                 send_req(plci);
3234                                 Info = GOOD;
3235                         }
3236                         break;
3237                 case B3_TRANSPARENT:
3238                         if (a->ncci_state[ncci] == CONNECTED)
3239                         {
3240                                 start_internal_command(Id, plci, reset_b3_command);
3241                                 Info = GOOD;
3242                         }
3243                         break;
3244                 }
3245         }
3246         /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3247         sendf(appl,
3248               _RESET_B3_R | CONFIRM,
3249               Id,
3250               Number,
3251               "w", Info);
3252         return false;
3253 }
3254
3255 static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3256                          PLCI *plci, APPL *appl, API_PARSE *parms)
3257 {
3258         word ncci;
3259
3260         dbug(1, dprintf("reset_b3_res"));
3261
3262         ncci = (word)(Id >> 16);
3263         if (plci && ncci) {
3264                 switch (plci->B3_prot)
3265                 {
3266                 case B3_ISO8208:
3267                 case B3_X25_DCE:
3268                         if (a->ncci_state[ncci] == INC_RES_PENDING)
3269                         {
3270                                 a->ncci_state[ncci] = CONNECTED;
3271                                 nl_req_ncci(plci, N_RESET_ACK, (byte)ncci);
3272                                 return true;
3273                         }
3274                         break;
3275                 }
3276         }
3277         return false;
3278 }
3279
3280 static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3281                                  PLCI *plci, APPL *appl, API_PARSE *parms)
3282 {
3283         word ncci;
3284         API_PARSE *ncpi;
3285         byte req;
3286
3287         dbug(1, dprintf("connect_b3_t90_a_res"));
3288
3289         ncci = (word)(Id >> 16);
3290         if (plci && ncci) {
3291                 if (a->ncci_state[ncci] == INC_ACT_PENDING) {
3292                         a->ncci_state[ncci] = CONNECTED;
3293                 }
3294                 else if (a->ncci_state[ncci] == INC_CON_PENDING) {
3295                         a->ncci_state[ncci] = CONNECTED;
3296
3297                         req = N_CONNECT_ACK;
3298
3299                         /* parms[0]==0 for CAPI original message definition! */
3300                         if (parms[0].info) {
3301                                 ncpi = &parms[1];
3302                                 if (ncpi->length > 2) {
3303                                         if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
3304                                         add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
3305                                 }
3306                         }
3307                         nl_req_ncci(plci, req, (byte)ncci);
3308                         return 1;
3309                 }
3310         }
3311         return false;
3312 }
3313
3314
3315 static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3316                          PLCI *plci, APPL *appl, API_PARSE *msg)
3317 {
3318         word Info = 0;
3319         word i;
3320         byte tel;
3321         API_PARSE bp_parms[7];
3322
3323         if (!plci || !msg)
3324         {
3325                 Info = _WRONG_IDENTIFIER;
3326         }
3327         else
3328         {
3329                 dbug(1, dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3330                                 msg->length, plci->Id, plci->tel, plci->NL.Id, plci->appl, plci->SuppState));
3331                 dbug(1, dprintf("PlciState=0x%x", plci->State));
3332                 for (i = 0; i < 7; i++) bp_parms[i].length = 0;
3333
3334                 /* check if no channel is open, no B3 connected only */
3335                 if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3336                     || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3337                 {
3338                         Info = _WRONG_STATE;
3339                 }
3340                 /* check message format and fill bp_parms pointer */
3341                 else if (msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3342                 {
3343                         Info = _WRONG_MESSAGE_FORMAT;
3344                 }
3345                 else
3346                 {
3347                         if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT)) /* send alert tone inband to the network, */
3348                         {                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3349                                 if (Id & EXT_CONTROLLER)
3350                                 {
3351                                         sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3352                                         return 0;
3353                                 }
3354                                 plci->State = INC_CON_CONNECTED_ALERT;
3355                                 plci->appl = appl;
3356                                 clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
3357                                 dump_c_ind_mask(plci);
3358                                 for (i = 0; i < max_appl; i++) /* disconnect the other appls */
3359                                 {                         /* its quasi a connect        */
3360                                         if (test_c_ind_mask_bit(plci, i))
3361                                                 sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3362                                 }
3363                         }
3364
3365                         api_save_msg(msg, "s", &plci->saved_msg);
3366                         tel = plci->tel;
3367                         if (Id & EXT_CONTROLLER)
3368                         {
3369                                 if (tel) /* external controller in use by this PLCI */
3370                                 {
3371                                         if (a->AdvSignalAppl && a->AdvSignalAppl != appl)
3372                                         {
3373                                                 dbug(1, dprintf("Ext_Ctrl in use 1"));
3374                                                 Info = _WRONG_STATE;
3375                                         }
3376                                 }
3377                                 else  /* external controller NOT in use by this PLCI ? */
3378                                 {
3379                                         if (a->AdvSignalPLCI)
3380                                         {
3381                                                 dbug(1, dprintf("Ext_Ctrl in use 2"));
3382                                                 Info = _WRONG_STATE;
3383                                         }
3384                                         else /* activate the codec */
3385                                         {
3386                                                 dbug(1, dprintf("Ext_Ctrl start"));
3387                                                 if (AdvCodecSupport(a, plci, appl, 0))
3388                                                 {
3389                                                         dbug(1, dprintf("Error in codec procedures"));
3390                                                         Info = _WRONG_STATE;
3391                                                 }
3392                                                 else if (plci->spoofed_msg == SPOOFING_REQUIRED) /* wait until codec is active */
3393                                                 {
3394                                                         plci->spoofed_msg = AWAITING_SELECT_B;
3395                                                         plci->internal_command = BLOCK_PLCI; /* lock other commands */
3396                                                         plci->command = 0;
3397                                                         dbug(1, dprintf("continue if codec loaded"));
3398                                                         return false;
3399                                                 }
3400                                         }
3401                                 }
3402                         }
3403                         else /* external controller bit is OFF */
3404                         {
3405                                 if (tel) /* external controller in use, need to switch off */
3406                                 {
3407                                         if (a->AdvSignalAppl == appl)
3408                                         {
3409                                                 CodecIdCheck(a, plci);
3410                                                 plci->tel = 0;
3411                                                 plci->adv_nl = 0;
3412                                                 dbug(1, dprintf("Ext_Ctrl disable"));
3413                                         }
3414                                         else
3415                                         {
3416                                                 dbug(1, dprintf("Ext_Ctrl not requested"));
3417                                         }
3418                                 }
3419                         }
3420                         if (!Info)
3421                         {
3422                                 if (plci->call_dir & CALL_DIR_OUT)
3423                                         plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3424                                 else if (plci->call_dir & CALL_DIR_IN)
3425                                         plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3426                                 start_internal_command(Id, plci, select_b_command);
3427                                 return false;
3428                         }
3429                 }
3430         }
3431         sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", Info);
3432         return false;
3433 }
3434
3435 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3436                              PLCI *plci, APPL *appl, API_PARSE *parms)
3437 {
3438         word command;
3439         word i;
3440         word ncci;
3441         API_PARSE *m;
3442         API_PARSE m_parms[5];
3443         word codec;
3444         byte req;
3445         byte ch;
3446         byte dir;
3447         static byte chi[2] = {0x01, 0x00};
3448         static byte lli[2] = {0x01, 0x00};
3449         static byte codec_cai[2] = {0x01, 0x01};
3450         static byte null_msg = {0};
3451         static API_PARSE null_parms = { 0, &null_msg };
3452         PLCI *v_plci;
3453         word Info = 0;
3454
3455         dbug(1, dprintf("manufacturer_req"));
3456         for (i = 0; i < 5; i++) m_parms[i].length = 0;
3457
3458         if (GET_DWORD(parms[0].info) != _DI_MANU_ID) {
3459                 Info = _WRONG_MESSAGE_FORMAT;
3460         }
3461         command = GET_WORD(parms[1].info);
3462         m = &parms[2];
3463         if (!Info)
3464         {
3465                 switch (command) {
3466                 case _DI_ASSIGN_PLCI:
3467                         if (api_parse(&m->info[1], (word)m->length, "wbbs", m_parms)) {
3468                                 Info = _WRONG_MESSAGE_FORMAT;
3469                                 break;
3470                         }
3471                         codec = GET_WORD(m_parms[0].info);
3472                         ch = m_parms[1].info[0];
3473                         dir = m_parms[2].info[0];
3474                         if ((i = get_plci(a))) {
3475                                 plci = &a->plci[i - 1];
3476                                 plci->appl = appl;
3477                                 plci->command = _MANUFACTURER_R;
3478                                 plci->m_command = command;
3479                                 plci->number = Number;
3480                                 plci->State = LOCAL_CONNECT;
3481                                 Id = (((word)plci->Id << 8) | plci->adapter->Id | 0x80);
3482                                 dbug(1, dprintf("ManCMD,plci=0x%x", Id));
3483
3484                                 if ((ch == 1 || ch == 2) && (dir <= 2)) {
3485                                         chi[1] = (byte)(0x80 | ch);
3486                                         lli[1] = 0;
3487                                         plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3488                                         switch (codec)
3489                                         {
3490                                         case 0:
3491                                                 Info = add_b1(plci, &m_parms[3], 0, 0);
3492                                                 break;
3493                                         case 1:
3494                                                 add_p(plci, CAI, codec_cai);
3495                                                 break;
3496                                                 /* manual 'swich on' to the codec support without signalling */
3497                                                 /* first 'assign plci' with this function, then use */
3498                                         case 2:
3499                                                 if (AdvCodecSupport(a, plci, appl, 0)) {
3500                                                         Info = _RESOURCE_ERROR;
3501                                                 }
3502                                                 else {
3503                                                         Info = add_b1(plci, &null_parms, 0, B1_FACILITY_LOCAL);
3504                                                         lli[1] = 0x10; /* local call codec stream */
3505                                                 }
3506                                                 break;
3507                                         }
3508
3509                                         plci->State = LOCAL_CONNECT;
3510                                         plci->manufacturer = true;
3511                                         plci->command = _MANUFACTURER_R;
3512                                         plci->m_command = command;
3513                                         plci->number = Number;
3514
3515                                         if (!Info)
3516                                         {
3517                                                 add_p(plci, LLI, lli);
3518                                                 add_p(plci, CHI, chi);
3519                                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
3520                                                 sig_req(plci, ASSIGN, DSIG_ID);
3521
3522                                                 if (!codec)
3523                                                 {
3524                                                         Info = add_b23(plci, &m_parms[3]);
3525                                                         if (!Info)
3526                                                         {
3527                                                                 nl_req_ncci(plci, ASSIGN, 0);
3528                                                                 send_req(plci);
3529                                                         }
3530                                                 }
3531                                                 if (!Info)
3532                                                 {
3533                                                         dbug(1, dprintf("dir=0x%x,spoof=0x%x", dir, plci->spoofed_msg));
3534                                                         if (plci->spoofed_msg == SPOOFING_REQUIRED)
3535                                                         {
3536                                                                 api_save_msg(m_parms, "wbbs", &plci->saved_msg);
3537                                                                 plci->spoofed_msg = AWAITING_MANUF_CON;
3538                                                                 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3539                                                                 plci->command = 0;
3540                                                                 send_req(plci);
3541                                                                 return false;
3542                                                         }
3543                                                         if (dir == 1) {
3544                                                                 sig_req(plci, CALL_REQ, 0);
3545                                                         }
3546                                                         else if (!dir) {
3547                                                                 sig_req(plci, LISTEN_REQ, 0);
3548                                                         }
3549                                                         send_req(plci);
3550                                                 }
3551                                                 else
3552                                                 {
3553                                                         sendf(appl,
3554                                                               _MANUFACTURER_R | CONFIRM,
3555                                                               Id,
3556                                                               Number,
3557                                                               "dww", _DI_MANU_ID, command, Info);
3558                                                         return 2;
3559                                                 }
3560                                         }
3561                                 }
3562                         }
3563                         else  Info = _OUT_OF_PLCI;
3564                         break;
3565
3566                 case _DI_IDI_CTRL:
3567                         if (!plci)
3568                         {
3569                                 Info = _WRONG_IDENTIFIER;
3570                                 break;
3571                         }
3572                         if (api_parse(&m->info[1], (word)m->length, "bs", m_parms)) {
3573                                 Info = _WRONG_MESSAGE_FORMAT;
3574                                 break;
3575                         }
3576                         req = m_parms[0].info[0];
3577                         plci->command = _MANUFACTURER_R;
3578                         plci->m_command = command;
3579                         plci->number = Number;
3580                         if (req == CALL_REQ)
3581                         {
3582                                 plci->b_channel = getChannel(&m_parms[1]);
3583                                 mixer_set_bchannel_id_esc(plci, plci->b_channel);
3584                                 if (plci->spoofed_msg == SPOOFING_REQUIRED)
3585                                 {
3586                                         plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3587                                         plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3588                                         plci->command = 0;
3589                                         break;
3590                                 }
3591                         }
3592                         else if (req == LAW_REQ)
3593                         {
3594                                 plci->cr_enquiry = true;
3595                         }
3596                         add_ss(plci, FTY, &m_parms[1]);
3597                         sig_req(plci, req, 0);
3598                         send_req(plci);
3599                         if (req == HANGUP)
3600                         {
3601                                 if (plci->NL.Id && !plci->nl_remove_id)
3602                                 {
3603                                         if (plci->channels)
3604                                         {
3605                                                 for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
3606                                                 {
3607                                                         if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3608                                                         {
3609                                                                 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3610                                                                 cleanup_ncci_data(plci, ncci);
3611                                                                 nl_req_ncci(plci, N_DISC, (byte)ncci);
3612                                                         }
3613                                                 }
3614                                         }
3615                                         mixer_remove(plci);
3616                                         nl_req_ncci(plci, REMOVE, 0);
3617                                         send_req(plci);
3618                                 }
3619                         }
3620                         break;
3621
3622                 case _DI_SIG_CTRL:
3623                         /* signalling control for loop activation B-channel */
3624                         if (!plci)
3625                         {
3626                                 Info = _WRONG_IDENTIFIER;
3627                                 break;
3628                         }
3629                         if (m->length) {
3630                                 plci->command = _MANUFACTURER_R;
3631                                 plci->number = Number;
3632                                 add_ss(plci, FTY, m);
3633                                 sig_req(plci, SIG_CTRL, 0);
3634                                 send_req(plci);
3635                         }
3636                         else Info = _WRONG_MESSAGE_FORMAT;
3637                         break;
3638
3639                 case _DI_RXT_CTRL:
3640                         /* activation control for receiver/transmitter B-channel */
3641                         if (!plci)
3642                         {
3643                                 Info = _WRONG_IDENTIFIER;
3644                                 break;
3645                         }
3646                         if (m->length) {
3647                                 plci->command = _MANUFACTURER_R;
3648                                 plci->number = Number;
3649                                 add_ss(plci, FTY, m);
3650                                 sig_req(plci, DSP_CTRL, 0);
3651                                 send_req(plci);
3652                         }
3653                         else Info = _WRONG_MESSAGE_FORMAT;
3654                         break;
3655
3656                 case _DI_ADV_CODEC:
3657                 case _DI_DSP_CTRL:
3658                         /* TEL_CTRL commands to support non standard adjustments: */
3659                         /* Ring on/off, Handset micro volume, external micro vol. */
3660                         /* handset+external speaker volume, receiver+transm. gain,*/
3661                         /* handsfree on (hookinfo off), set mixer command         */
3662
3663                         if (command == _DI_ADV_CODEC)
3664                         {
3665                                 if (!a->AdvCodecPLCI) {
3666                                         Info = _WRONG_STATE;
3667                                         break;
3668                                 }
3669                                 v_plci = a->AdvCodecPLCI;
3670                         }
3671                         else
3672                         {
3673                                 if (plci
3674                                     && (m->length >= 3)
3675                                     && (m->info[1] == 0x1c)
3676                                     && (m->info[2] >= 1))
3677                                 {
3678                                         if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3679                                         {
3680                                                 if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3681                                                 {
3682                                                         Info = _WRONG_STATE;
3683                                                         break;
3684                                                 }
3685                                                 a->adv_voice_coef_length = m->info[2] - 1;
3686                                                 if (a->adv_voice_coef_length > m->length - 3)
3687                                                         a->adv_voice_coef_length = (byte)(m->length - 3);
3688                                                 if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3689                                                         a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3690                                                 for (i = 0; i < a->adv_voice_coef_length; i++)
3691                                                         a->adv_voice_coef_buffer[i] = m->info[4 + i];
3692                                                 if (plci->B1_facilities & B1_FACILITY_VOICE)
3693                                                         adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
3694                                                 break;
3695                                         }
3696                                         else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3697                                         {
3698                                                 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3699                                                 {
3700                                                         Info = _FACILITY_NOT_SUPPORTED;
3701                                                         break;
3702                                                 }
3703
3704                                                 plci->dtmf_parameter_length = m->info[2] - 1;
3705                                                 if (plci->dtmf_parameter_length > m->length - 3)
3706                                                         plci->dtmf_parameter_length = (byte)(m->length - 3);
3707                                                 if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3708                                                         plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3709                                                 for (i = 0; i < plci->dtmf_parameter_length; i++)
3710                                                         plci->dtmf_parameter_buffer[i] = m->info[4 + i];
3711                                                 if (plci->B1_facilities & B1_FACILITY_DTMFR)
3712                                                         dtmf_parameter_write(plci);
3713                                                 break;
3714
3715                                         }
3716                                 }
3717                                 v_plci = plci;
3718                         }
3719
3720                         if (!v_plci)
3721                         {
3722                                 Info = _WRONG_IDENTIFIER;
3723                                 break;
3724                         }
3725                         if (m->length) {
3726                                 add_ss(v_plci, FTY, m);
3727                                 sig_req(v_plci, TEL_CTRL, 0);
3728                                 send_req(v_plci);
3729                         }
3730                         else Info = _WRONG_MESSAGE_FORMAT;
3731
3732                         break;
3733
3734                 case _DI_OPTIONS_REQUEST:
3735                         if (api_parse(&m->info[1], (word)m->length, "d", m_parms)) {
3736                                 Info = _WRONG_MESSAGE_FORMAT;
3737                                 break;
3738                         }
3739                         if (GET_DWORD(m_parms[0].info) & ~a->man_profile.private_options)
3740                         {
3741                                 Info = _FACILITY_NOT_SUPPORTED;
3742                                 break;
3743                         }
3744                         a->requested_options_table[appl->Id - 1] = GET_DWORD(m_parms[0].info);
3745                         break;
3746
3747
3748
3749                 default:
3750                         Info = _WRONG_MESSAGE_FORMAT;
3751                         break;
3752                 }
3753         }
3754
3755         sendf(appl,
3756               _MANUFACTURER_R | CONFIRM,
3757               Id,
3758               Number,
3759               "dww", _DI_MANU_ID, command, Info);
3760         return false;
3761 }
3762
3763
3764 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3765                              PLCI *plci, APPL *appl, API_PARSE *msg)
3766 {
3767         word indication;
3768
3769         API_PARSE m_parms[3];
3770         API_PARSE *ncpi;
3771         API_PARSE fax_parms[9];
3772         word i;
3773         byte len;
3774
3775
3776         dbug(1, dprintf("manufacturer_res"));
3777
3778         if ((msg[0].length == 0)
3779             || (msg[1].length == 0)
3780             || (GET_DWORD(msg[0].info) != _DI_MANU_ID))
3781         {
3782                 return false;
3783         }
3784         indication = GET_WORD(msg[1].info);
3785         switch (indication)
3786         {
3787
3788         case _DI_NEGOTIATE_B3:
3789                 if (!plci)
3790                         break;
3791                 if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3792                     || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3793                 {
3794                         dbug(1, dprintf("wrong state for NEGOTIATE_B3 parameters"));
3795                         break;
3796                 }
3797                 if (api_parse(&msg[2].info[1], msg[2].length, "ws", m_parms))
3798                 {
3799                         dbug(1, dprintf("wrong format in NEGOTIATE_B3 parameters"));
3800                         break;
3801                 }
3802                 ncpi = &m_parms[1];
3803                 len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
3804                 if (plci->fax_connect_info_length < len)
3805                 {
3806                         ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3807                         ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3808                 }
3809                 if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3810                 {
3811                         dbug(1, dprintf("non-standard facilities info missing or wrong format"));
3812                 }
3813                 else
3814                 {
3815                         if (plci->fax_connect_info_length <= len)
3816                                 plci->fax_connect_info_buffer[len] = 0;
3817                         len += 1 + plci->fax_connect_info_buffer[len];
3818                         if (plci->fax_connect_info_length <= len)
3819                                 plci->fax_connect_info_buffer[len] = 0;
3820                         len += 1 + plci->fax_connect_info_buffer[len];
3821                         if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3822                                 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3823                         plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3824                         for (i = 0; i < fax_parms[7].length; i++)
3825                                 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
3826                 }
3827                 plci->fax_connect_info_length = len;
3828                 plci->fax_edata_ack_length = plci->fax_connect_info_length;
3829                 start_internal_command(Id, plci, fax_edata_ack_command);
3830                 break;
3831
3832         }
3833         return false;
3834 }
3835
3836 /*------------------------------------------------------------------*/
3837 /* IDI callback function                                            */
3838 /*------------------------------------------------------------------*/
3839
3840 void callback(ENTITY *e)
3841 {
3842         DIVA_CAPI_ADAPTER *a;
3843         APPL *appl;
3844         PLCI *plci;
3845         CAPI_MSG *m;
3846         word i, j;
3847         byte rc;
3848         byte ch;
3849         byte req;
3850         byte global_req;
3851         int no_cancel_rc;
3852
3853         dbug(1, dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3854                         (e->user[0] + 1) & 0x7fff, e->Id, e->Req, e->Rc, e->Ind));
3855
3856         a = &(adapter[(byte)e->user[0]]);
3857         plci = &(a->plci[e->user[1]]);
3858         no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3859
3860         /*
3861           If new protocol code and new XDI is used then CAPI should work
3862           fully in accordance with IDI cpec an look on callback field instead
3863           of Rc field for return codes.
3864         */
3865         if (((e->complete == 0xff) && no_cancel_rc) ||
3866             (e->Rc && !no_cancel_rc)) {
3867                 rc = e->Rc;
3868                 ch = e->RcCh;
3869                 req = e->Req;
3870                 e->Rc = 0;
3871
3872                 if (e->user[0] & 0x8000)
3873                 {
3874                         /*
3875                           If REMOVE request was sent then we have to wait until
3876                           return code with Id set to zero arrives.
3877                           All other return codes should be ignored.
3878                         */
3879                         if (req == REMOVE)
3880                         {
3881                                 if (e->Id)
3882                                 {
3883                                         dbug(1, dprintf("cancel RC in REMOVE state"));
3884                                         return;
3885                                 }
3886                                 channel_flow_control_remove(plci);
3887                                 for (i = 0; i < 256; i++)
3888                                 {
3889                                         if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3890                                                 a->FlowControlIdTable[i] = 0;
3891                                 }
3892                                 plci->nl_remove_id = 0;
3893                                 if (plci->rx_dma_descriptor > 0) {
3894                                         diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3895                                         plci->rx_dma_descriptor = 0;
3896                                 }
3897                         }
3898                         if (rc == OK_FC)
3899                         {
3900                                 a->FlowControlIdTable[ch] = e->Id;
3901                                 a->FlowControlSkipTable[ch] = 0;
3902
3903                                 a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3904                                 a->ch_flow_plci[ch] = plci->Id;
3905                                 plci->nl_req = 0;
3906                         }
3907                         else
3908                         {
3909                                 /*
3910                                   Cancel return codes self, if feature was requested
3911                                 */
3912                                 if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3913                                         a->FlowControlIdTable[ch] = 0;
3914                                         if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3915                                                 dbug(3, dprintf("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3916                                                 return;
3917                                         }
3918                                 }
3919
3920                                 if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3921                                 {
3922                                         a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3923                                         if (ch == e->ReqCh)
3924                                                 plci->nl_req = 0;
3925                                 }
3926                                 else
3927                                         plci->nl_req = 0;
3928                         }
3929                         if (plci->nl_req)
3930                                 control_rc(plci, 0, rc, ch, 0, true);
3931                         else
3932                         {
3933                                 if (req == N_XON)
3934                                 {
3935                                         channel_x_on(plci, ch);
3936                                         if (plci->internal_command)
3937                                                 control_rc(plci, req, rc, ch, 0, true);
3938                                 }
3939                                 else
3940                                 {
3941                                         if (plci->nl_global_req)
3942                                         {
3943                                                 global_req = plci->nl_global_req;
3944                                                 plci->nl_global_req = 0;
3945                                                 if (rc != ASSIGN_OK) {
3946                                                         e->Id = 0;
3947                                                         if (plci->rx_dma_descriptor > 0) {
3948                                                                 diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3949                                                                 plci->rx_dma_descriptor = 0;
3950                                                         }
3951                                                 }
3952                                                 channel_xmit_xon(plci);
3953                                                 control_rc(plci, 0, rc, ch, global_req, true);
3954                                         }
3955                                         else if (plci->data_sent)
3956                                         {
3957                                                 channel_xmit_xon(plci);
3958                                                 plci->data_sent = false;
3959                                                 plci->NL.XNum = 1;
3960                                                 data_rc(plci, ch);
3961                                                 if (plci->internal_command)
3962                                                         control_rc(plci, req, rc, ch, 0, true);
3963                                         }
3964                                         else
3965                                         {
3966                                                 channel_xmit_xon(plci);
3967                                                 control_rc(plci, req, rc, ch, 0, true);
3968                                         }
3969                                 }
3970                         }
3971                 }
3972                 else
3973                 {
3974                         /*
3975                           If REMOVE request was sent then we have to wait until
3976                           return code with Id set to zero arrives.
3977                           All other return codes should be ignored.
3978                         */
3979                         if (req == REMOVE)
3980                         {
3981                                 if (e->Id)
3982                                 {
3983                                         dbug(1, dprintf("cancel RC in REMOVE state"));
3984                                         return;
3985                                 }
3986                                 plci->sig_remove_id = 0;
3987                         }
3988                         plci->sig_req = 0;
3989                         if (plci->sig_global_req)
3990                         {
3991                                 global_req = plci->sig_global_req;
3992                                 plci->sig_global_req = 0;
3993                                 if (rc != ASSIGN_OK)
3994                                         e->Id = 0;
3995                                 channel_xmit_xon(plci);
3996                                 control_rc(plci, 0, rc, ch, global_req, false);
3997                         }
3998                         else
3999                         {
4000                                 channel_xmit_xon(plci);
4001                                 control_rc(plci, req, rc, ch, 0, false);
4002                         }
4003                 }
4004                 /*
4005                   Again: in accordance with IDI spec Rc and Ind can't be delivered in the
4006                   same callback. Also if new XDI and protocol code used then jump
4007                   direct to finish.
4008                 */
4009                 if (no_cancel_rc) {
4010                         channel_xmit_xon(plci);
4011                         goto capi_callback_suffix;
4012                 }
4013         }
4014
4015         channel_xmit_xon(plci);
4016
4017         if (e->Ind) {
4018                 if (e->user[0] & 0x8000) {
4019                         byte Ind = e->Ind & 0x0f;
4020                         byte Ch = e->IndCh;
4021                         if (((Ind == N_DISC) || (Ind == N_DISC_ACK)) &&
4022                             (a->ch_flow_plci[Ch] == plci->Id)) {
4023                                 if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4024                                         dbug(3, dprintf("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4025                                 }
4026                                 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4027                         }
4028                         nl_ind(plci);
4029                         if ((e->RNR != 1) &&
4030                             (a->ch_flow_plci[Ch] == plci->Id) &&
4031                             (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4032                                 a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4033                                 dbug(3, dprintf("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4034                         }
4035                 } else {
4036                         sig_ind(plci);
4037                 }
4038                 e->Ind = 0;
4039         }
4040
4041 capi_callback_suffix:
4042
4043         while (!plci->req_in
4044                && !plci->internal_command
4045                && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4046         {
4047                 j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4048
4049                 i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4050
4051                 m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4052                 appl = *((APPL **)(&((byte *)(plci->msg_in_queue))[j + i]));
4053                 dbug(1, dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4054                                 m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4055                 if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4056                 {
4057                         plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4058                         plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4059                 }
4060                 else
4061                 {
4062                         plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4063                 }
4064                 if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4065                 {
4066                         plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4067                         plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4068                 }
4069                 else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4070                 {
4071                         plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4072                         plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4073                 }
4074                 i = api_put(appl, m);
4075                 if (i != 0)
4076                 {
4077                         if (m->header.command == _DATA_B3_R)
4078
4079                                 TransmitBufferFree(appl, (byte *)(long)(m->info.data_b3_req.Data));
4080
4081                         dbug(1, dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4082                         break;
4083                 }
4084
4085                 if (plci->li_notify_update)
4086                 {
4087                         plci->li_notify_update = false;
4088                         mixer_notify_update(plci, false);
4089                 }
4090
4091         }
4092         send_data(plci);
4093         send_req(plci);
4094 }
4095
4096
4097 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4098                        byte nl_rc)
4099 {
4100         dword Id;
4101         dword rId;
4102         word Number;
4103         word Info = 0;
4104         word i;
4105         word ncci;
4106         DIVA_CAPI_ADAPTER *a;
4107         APPL *appl;
4108         PLCI *rplci;
4109         byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4110         byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4111
4112         if (!plci) {
4113                 dbug(0, dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4114                 return;
4115         }
4116         dbug(1, dprintf("req0_in/out=%d/%d", plci->req_in, plci->req_out));
4117         if (plci->req_in != plci->req_out)
4118         {
4119                 if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4120                 {
4121                         dbug(1, dprintf("req_1return"));
4122                         return;
4123                 }
4124                 /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4125         }
4126         plci->req_in = plci->req_in_start = plci->req_out = 0;
4127         dbug(1, dprintf("control_rc"));
4128
4129         appl = plci->appl;
4130         a = plci->adapter;
4131         ncci = a->ch_ncci[ch];
4132         if (appl)
4133         {
4134                 Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4135                 if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4136                 Number = plci->number;
4137                 dbug(1, dprintf("Contr_RC-Id=%08lx,plci=%x,tel=%x, entity=0x%x, command=0x%x, int_command=0x%x", Id, plci->Id, plci->tel, plci->Sig.Id, plci->command, plci->internal_command));
4138                 dbug(1, dprintf("channels=0x%x", plci->channels));
4139                 if (plci_remove_check(plci))
4140                         return;
4141                 if (req == REMOVE && rc == ASSIGN_OK)
4142                 {
4143                         sig_req(plci, HANGUP, 0);
4144                         sig_req(plci, REMOVE, 0);
4145                         send_req(plci);
4146                 }
4147                 if (plci->command)
4148                 {
4149                         switch (plci->command)
4150                         {
4151                         case C_HOLD_REQ:
4152                                 dbug(1, dprintf("HoldRC=0x%x", rc));
4153                                 SSparms[1] = (byte)S_HOLD;
4154                                 if (rc != OK)
4155                                 {
4156                                         plci->SuppState = IDLE;
4157                                         Info = 0x2001;
4158                                 }
4159                                 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4160                                 break;
4161
4162                         case C_RETRIEVE_REQ:
4163                                 dbug(1, dprintf("RetrieveRC=0x%x", rc));
4164                                 SSparms[1] = (byte)S_RETRIEVE;
4165                                 if (rc != OK)
4166                                 {
4167                                         plci->SuppState = CALL_HELD;
4168                                         Info = 0x2001;
4169                                 }
4170                                 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4171                                 break;
4172
4173                         case _INFO_R:
4174                                 dbug(1, dprintf("InfoRC=0x%x", rc));
4175                                 if (rc != OK) Info = _WRONG_STATE;
4176                                 sendf(appl, _INFO_R | CONFIRM, Id, Number, "w", Info);
4177                                 break;
4178
4179                         case _CONNECT_R:
4180                                 dbug(1, dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x", req, rc, global_req, nl_rc));
4181                                 if (plci->State == INC_DIS_PENDING)
4182                                         break;
4183                                 if (plci->Sig.Id != 0xff)
4184                                 {
4185                                         if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4186                                             || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4187                                         {
4188                                                 dbug(1, dprintf("No more IDs/Call_Req failed"));
4189                                                 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4190                                                 plci_remove(plci);
4191                                                 plci->State = IDLE;
4192                                                 break;
4193                                         }
4194                                         if (plci->State != LOCAL_CONNECT) plci->State = OUTG_CON_PENDING;
4195                                         sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4196                                 }
4197                                 else /* D-ch activation */
4198                                 {
4199                                         if (rc != ASSIGN_OK)
4200                                         {
4201                                                 dbug(1, dprintf("No more IDs/X.25 Call_Req failed"));
4202                                                 sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4203                                                 plci_remove(plci);
4204                                                 plci->State = IDLE;
4205                                                 break;
4206                                         }
4207                                         sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4208                                         sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "sss", "", "", "");
4209                                         plci->State = INC_ACT_PENDING;
4210                                 }
4211                                 break;
4212
4213                         case _CONNECT_I | RESPONSE:
4214                                 if (plci->State != INC_DIS_PENDING)
4215                                         plci->State = INC_CON_ACCEPT;
4216                                 break;
4217
4218                         case _DISCONNECT_R:
4219                                 if (plci->State == INC_DIS_PENDING)
4220                                         break;
4221                                 if (plci->Sig.Id != 0xff)
4222                                 {
4223                                         plci->State = OUTG_DIS_PENDING;
4224                                         sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
4225                                 }
4226                                 break;
4227
4228                         case SUSPEND_REQ:
4229                                 break;
4230
4231                         case RESUME_REQ:
4232                                 break;
4233
4234                         case _CONNECT_B3_R:
4235                                 if (rc != OK)
4236                                 {
4237                                         sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
4238                                         break;
4239                                 }
4240                                 ncci = get_ncci(plci, ch, 0);
4241                                 Id = (Id & 0xffff) | (((dword) ncci) << 16);
4242                                 plci->channels++;
4243                                 if (req == N_RESET)
4244                                 {
4245                                         a->ncci_state[ncci] = INC_ACT_PENDING;
4246                                         sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4247                                         sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
4248                                 }
4249                                 else
4250                                 {
4251                                         a->ncci_state[ncci] = OUTG_CON_PENDING;
4252                                         sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4253                                 }
4254                                 break;
4255
4256                         case _CONNECT_B3_I | RESPONSE:
4257                                 break;
4258
4259                         case _RESET_B3_R:
4260 /*        sendf(appl, _RESET_B3_R | CONFIRM, Id, Number, "w", 0);*/
4261                                 break;
4262
4263                         case _DISCONNECT_B3_R:
4264                                 sendf(appl, _DISCONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4265                                 break;
4266
4267                         case _MANUFACTURER_R:
4268                                 break;
4269
4270                         case PERM_LIST_REQ:
4271                                 if (rc != OK)
4272                                 {
4273                                         Info = _WRONG_IDENTIFIER;
4274                                         sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4275                                         plci_remove(plci);
4276                                 }
4277                                 else
4278                                         sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4279                                 break;
4280
4281                         default:
4282                                 break;
4283                         }
4284                         plci->command = 0;
4285                 }
4286                 else if (plci->internal_command)
4287                 {
4288                         switch (plci->internal_command)
4289                         {
4290                         case BLOCK_PLCI:
4291                                 return;
4292
4293                         case GET_MWI_STATE:
4294                                 if (rc == OK) /* command supported, wait for indication */
4295                                 {
4296                                         return;
4297                                 }
4298                                 plci_remove(plci);
4299                                 break;
4300
4301                                 /* Get Supported Services */
4302                         case GETSERV_REQ_PEND:
4303                                 if (rc == OK) /* command supported, wait for indication */
4304                                 {
4305                                         break;
4306                                 }
4307                                 PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4308                                 sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", 0, 3, SSstruct);
4309                                 plci_remove(plci);
4310                                 break;
4311
4312                         case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
4313                         case INTERR_NUMBERS_REQ_PEND:
4314                         case CF_START_PEND:                  /* Call Forwarding Start pending */
4315                         case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
4316                         case CCBS_REQUEST_REQ_PEND:
4317                         case CCBS_DEACTIVATE_REQ_PEND:
4318                         case CCBS_INTERROGATE_REQ_PEND:
4319                                 switch (plci->internal_command)
4320                                 {
4321                                 case INTERR_DIVERSION_REQ_PEND:
4322                                         SSparms[1] = S_INTERROGATE_DIVERSION;
4323                                         break;
4324                                 case INTERR_NUMBERS_REQ_PEND:
4325                                         SSparms[1] = S_INTERROGATE_NUMBERS;
4326                                         break;
4327                                 case CF_START_PEND:
4328                                         SSparms[1] = S_CALL_FORWARDING_START;
4329                                         break;
4330                                 case CF_STOP_PEND:
4331                                         SSparms[1] = S_CALL_FORWARDING_STOP;
4332                                         break;
4333                                 case CCBS_REQUEST_REQ_PEND:
4334                                         SSparms[1] = S_CCBS_REQUEST;
4335                                         break;
4336                                 case CCBS_DEACTIVATE_REQ_PEND:
4337                                         SSparms[1] = S_CCBS_DEACTIVATE;
4338                                         break;
4339                                 case CCBS_INTERROGATE_REQ_PEND:
4340                                         SSparms[1] = S_CCBS_INTERROGATE;
4341                                         break;
4342                                 }
4343                                 if (global_req == ASSIGN)
4344                                 {
4345                                         dbug(1, dprintf("AssignDiversion_RC=0x%x/0x%x", req, rc));
4346                                         return;
4347                                 }
4348                                 if (!plci->appl) break;
4349                                 if (rc == ISDN_GUARD_REJ)
4350                                 {
4351                                         Info = _CAPI_GUARD_ERROR;
4352                                 }
4353                                 else if (rc != OK)
4354                                 {
4355                                         Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4356                                 }
4357                                 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7,
4358                                       plci->number, "wws", Info, (word)3, SSparms);
4359                                 if (Info) plci_remove(plci);
4360                                 break;
4361
4362                                 /* 3pty conference pending */
4363                         case PTY_REQ_PEND:
4364                                 if (!plci->relatedPTYPLCI) break;
4365                                 rplci = plci->relatedPTYPLCI;
4366                                 SSparms[1] = plci->ptyState;
4367                                 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4368                                 if (rplci->tel) rId |= EXT_CONTROLLER;
4369                                 if (rc != OK)
4370                                 {
4371                                         Info = 0x300E; /* not supported */
4372                                         plci->relatedPTYPLCI = NULL;
4373                                         plci->ptyState = 0;
4374                                 }
4375                                 sendf(rplci->appl,
4376                                       _FACILITY_R | CONFIRM,
4377                                       rId,
4378                                       plci->number,
4379                                       "wws", Info, (word)3, SSparms);
4380                                 break;
4381
4382                                 /* Explicit Call Transfer pending */
4383                         case ECT_REQ_PEND:
4384                                 dbug(1, dprintf("ECT_RC=0x%x/0x%x", req, rc));
4385                                 if (!plci->relatedPTYPLCI) break;
4386                                 rplci = plci->relatedPTYPLCI;
4387                                 SSparms[1] = S_ECT;
4388                                 rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4389                                 if (rplci->tel) rId |= EXT_CONTROLLER;
4390                                 if (rc != OK)
4391                                 {
4392                                         Info = 0x300E; /* not supported */
4393                                         plci->relatedPTYPLCI = NULL;
4394                                         plci->ptyState = 0;
4395                                 }
4396                                 sendf(rplci->appl,
4397                                       _FACILITY_R | CONFIRM,
4398                                       rId,
4399                                       plci->number,
4400                                       "wws", Info, (word)3, SSparms);
4401                                 break;
4402
4403                         case _MANUFACTURER_R:
4404                                 dbug(1, dprintf("_Manufacturer_R=0x%x/0x%x", req, rc));
4405                                 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4406                                 {
4407                                         dbug(1, dprintf("No more IDs"));
4408                                         sendf(appl, _MANUFACTURER_R | CONFIRM, Id, Number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
4409                                         plci_remove(plci);  /* after codec init, internal codec commands pending */
4410                                 }
4411                                 break;
4412
4413                         case _CONNECT_R:
4414                                 dbug(1, dprintf("_Connect_R=0x%x/0x%x", req, rc));
4415                                 if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4416                                 {
4417                                         dbug(1, dprintf("No more IDs"));
4418                                         sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4419                                         plci_remove(plci);  /* after codec init, internal codec commands pending */
4420                                 }
4421                                 break;
4422
4423                         case PERM_COD_HOOK:                     /* finished with Hook_Ind */
4424                                 return;
4425
4426                         case PERM_COD_CALL:
4427                                 dbug(1, dprintf("***Codec Connect_Pending A, Rc = 0x%x", rc));
4428                                 plci->internal_command = PERM_COD_CONN_PEND;
4429                                 return;
4430
4431                         case PERM_COD_ASSIGN:
4432                                 dbug(1, dprintf("***Codec Assign A, Rc = 0x%x", rc));
4433                                 if (rc != ASSIGN_OK) break;
4434                                 sig_req(plci, CALL_REQ, 0);
4435                                 send_req(plci);
4436                                 plci->internal_command = PERM_COD_CALL;
4437                                 return;
4438
4439                                 /* Null Call Reference Request pending */
4440                         case C_NCR_FAC_REQ:
4441                                 dbug(1, dprintf("NCR_FAC=0x%x/0x%x", req, rc));
4442                                 if (global_req == ASSIGN)
4443                                 {
4444                                         if (rc == ASSIGN_OK)
4445                                         {
4446                                                 return;
4447                                         }
4448                                         else
4449                                         {
4450                                                 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4451                                                 appl->NullCREnable = false;
4452                                                 plci_remove(plci);
4453                                         }
4454                                 }
4455                                 else if (req == NCR_FACILITY)
4456                                 {
4457                                         if (rc == OK)
4458                                         {
4459                                                 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", 0);
4460                                         }
4461                                         else
4462                                         {
4463                                                 sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4464                                                 appl->NullCREnable = false;
4465                                         }
4466                                         plci_remove(plci);
4467                                 }
4468                                 break;
4469
4470                         case HOOK_ON_REQ:
4471                                 if (plci->channels)
4472                                 {
4473                                         if (a->ncci_state[ncci] == CONNECTED)
4474                                         {
4475                                                 a->ncci_state[ncci] = OUTG_DIS_PENDING;
4476                                                 cleanup_ncci_data(plci, ncci);
4477                                                 nl_req_ncci(plci, N_DISC, (byte)ncci);
4478                                         }
4479                                         break;
4480                                 }
4481                                 break;
4482
4483                         case HOOK_OFF_REQ:
4484                                 if (plci->State == INC_DIS_PENDING)
4485                                         break;
4486                                 sig_req(plci, CALL_REQ, 0);
4487                                 send_req(plci);
4488                                 plci->State = OUTG_CON_PENDING;
4489                                 break;
4490
4491
4492                         case MWI_ACTIVATE_REQ_PEND:
4493                         case MWI_DEACTIVATE_REQ_PEND:
4494                                 if (global_req == ASSIGN && rc == ASSIGN_OK)
4495                                 {
4496                                         dbug(1, dprintf("MWI_REQ assigned"));
4497                                         return;
4498                                 }
4499                                 else if (rc != OK)
4500                                 {
4501                                         if (rc == WRONG_IE)
4502                                         {
4503                                                 Info = 0x2007; /* Illegal message parameter coding */
4504                                                 dbug(1, dprintf("MWI_REQ invalid parameter"));
4505                                         }
4506                                         else
4507                                         {
4508                                                 Info = 0x300B; /* not supported */
4509                                                 dbug(1, dprintf("MWI_REQ not supported"));
4510                                         }
4511                                         /* 0x3010: Request not allowed in this state */
4512                                         PUT_WORD(&SSparms[4], 0x300E); /* SS not supported */
4513
4514                                 }
4515                                 if (plci->internal_command == MWI_ACTIVATE_REQ_PEND)
4516                                 {
4517                                         PUT_WORD(&SSparms[1], S_MWI_ACTIVATE);
4518                                 }
4519                                 else PUT_WORD(&SSparms[1], S_MWI_DEACTIVATE);
4520
4521                                 if (plci->cr_enquiry)
4522                                 {
4523                                         sendf(plci->appl,
4524                                               _FACILITY_R | CONFIRM,
4525                                               Id & 0xf,
4526                                               plci->number,
4527                                               "wws", Info, (word)3, SSparms);
4528                                         if (rc != OK) plci_remove(plci);
4529                                 }
4530                                 else
4531                                 {
4532                                         sendf(plci->appl,
4533                                               _FACILITY_R | CONFIRM,
4534                                               Id,
4535                                               plci->number,
4536                                               "wws", Info, (word)3, SSparms);
4537                                 }
4538                                 break;
4539
4540                         case CONF_BEGIN_REQ_PEND:
4541                         case CONF_ADD_REQ_PEND:
4542                         case CONF_SPLIT_REQ_PEND:
4543                         case CONF_DROP_REQ_PEND:
4544                         case CONF_ISOLATE_REQ_PEND:
4545                         case CONF_REATTACH_REQ_PEND:
4546                                 dbug(1, dprintf("CONF_RC=0x%x/0x%x", req, rc));
4547                                 if ((plci->internal_command == CONF_ADD_REQ_PEND) && (!plci->relatedPTYPLCI)) break;
4548                                 rplci = plci;
4549                                 rId = Id;
4550                                 switch (plci->internal_command)
4551                                 {
4552                                 case CONF_BEGIN_REQ_PEND:
4553                                         SSparms[1] = S_CONF_BEGIN;
4554                                         break;
4555                                 case CONF_ADD_REQ_PEND:
4556                                         SSparms[1] = S_CONF_ADD;
4557                                         rplci = plci->relatedPTYPLCI;
4558                                         rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4559                                         break;
4560                                 case CONF_SPLIT_REQ_PEND:
4561                                         SSparms[1] = S_CONF_SPLIT;
4562                                         break;
4563                                 case CONF_DROP_REQ_PEND:
4564                                         SSparms[1] = S_CONF_DROP;
4565                                         break;
4566                                 case CONF_ISOLATE_REQ_PEND:
4567                                         SSparms[1] = S_CONF_ISOLATE;
4568                                         break;
4569                                 case CONF_REATTACH_REQ_PEND:
4570                                         SSparms[1] = S_CONF_REATTACH;
4571                                         break;
4572                                 }
4573
4574                                 if (rc != OK)
4575                                 {
4576                                         Info = 0x300E; /* not supported */
4577                                         plci->relatedPTYPLCI = NULL;
4578                                         plci->ptyState = 0;
4579                                 }
4580                                 sendf(rplci->appl,
4581                                       _FACILITY_R | CONFIRM,
4582                                       rId,
4583                                       plci->number,
4584                                       "wws", Info, (word)3, SSparms);
4585                                 break;
4586
4587                         case VSWITCH_REQ_PEND:
4588                                 if (rc != OK)
4589                                 {
4590                                         if (plci->relatedPTYPLCI)
4591                                         {
4592                                                 plci->relatedPTYPLCI->vswitchstate = 0;
4593                                                 plci->relatedPTYPLCI->vsprot = 0;
4594                                                 plci->relatedPTYPLCI->vsprotdialect = 0;
4595                                         }
4596                                         plci->vswitchstate = 0;
4597                                         plci->vsprot = 0;
4598                                         plci->vsprotdialect = 0;
4599                                 }
4600                                 else
4601                                 {
4602                                         if (plci->relatedPTYPLCI &&
4603                                             plci->vswitchstate == 1 &&
4604                                             plci->relatedPTYPLCI->vswitchstate == 3) /* join complete */
4605                                                 plci->vswitchstate = 3;
4606                                 }
4607                                 break;
4608
4609                                 /* Call Deflection Request pending (SSCT) */
4610                         case CD_REQ_PEND:
4611                                 SSparms[1] = S_CALL_DEFLECTION;
4612                                 if (rc != OK)
4613                                 {
4614                                         Info = 0x300E; /* not supported */
4615                                         plci->appl->CDEnable = 0;
4616                                 }
4617                                 sendf(plci->appl, _FACILITY_R | CONFIRM, Id,
4618                                       plci->number, "wws", Info, (word)3, SSparms);
4619                                 break;
4620
4621                         case RTP_CONNECT_B3_REQ_COMMAND_2:
4622                                 if (rc == OK)
4623                                 {
4624                                         ncci = get_ncci(plci, ch, 0);
4625                                         Id = (Id & 0xffff) | (((dword) ncci) << 16);
4626                                         plci->channels++;
4627                                         a->ncci_state[ncci] = OUTG_CON_PENDING;
4628                                 }
4629
4630                         default:
4631                                 if (plci->internal_command_queue[0])
4632                                 {
4633                                         (*(plci->internal_command_queue[0]))(Id, plci, rc);
4634                                         if (plci->internal_command)
4635                                                 return;
4636                                 }
4637                                 break;
4638                         }
4639                         next_internal_command(Id, plci);
4640                 }
4641         }
4642         else /* appl==0 */
4643         {
4644                 Id = ((word)plci->Id << 8) | plci->adapter->Id;
4645                 if (plci->tel) Id |= EXT_CONTROLLER;
4646
4647                 switch (plci->internal_command)
4648                 {
4649                 case BLOCK_PLCI:
4650                         return;
4651
4652                 case START_L1_SIG_ASSIGN_PEND:
4653                 case REM_L1_SIG_ASSIGN_PEND:
4654                         if (global_req == ASSIGN)
4655                         {
4656                                 break;
4657                         }
4658                         else
4659                         {
4660                                 dbug(1, dprintf("***L1 Req rem PLCI"));
4661                                 plci->internal_command = 0;
4662                                 sig_req(plci, REMOVE, 0);
4663                                 send_req(plci);
4664                         }
4665                         break;
4666
4667                         /* Call Deflection Request pending, just no appl ptr assigned */
4668                 case CD_REQ_PEND:
4669                         SSparms[1] = S_CALL_DEFLECTION;
4670                         if (rc != OK)
4671                         {
4672                                 Info = 0x300E; /* not supported */
4673                         }
4674                         for (i = 0; i < max_appl; i++)
4675                         {
4676                                 if (application[i].CDEnable)
4677                                 {
4678                                         if (!application[i].Id) application[i].CDEnable = 0;
4679                                         else
4680                                         {
4681                                                 sendf(&application[i], _FACILITY_R | CONFIRM, Id,
4682                                                       plci->number, "wws", Info, (word)3, SSparms);
4683                                                 if (Info) application[i].CDEnable = 0;
4684                                         }
4685                                 }
4686                         }
4687                         plci->internal_command = 0;
4688                         break;
4689
4690                 case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4691                         return;
4692
4693                 case PERM_COD_CALL:
4694                         plci->internal_command = PERM_COD_CONN_PEND;
4695                         dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc));
4696                         return;
4697
4698                 case PERM_COD_ASSIGN:
4699                         dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc));
4700                         plci->internal_command = 0;
4701                         if (rc != ASSIGN_OK) break;
4702                         plci->internal_command = PERM_COD_CALL;
4703                         sig_req(plci, CALL_REQ, 0);
4704                         send_req(plci);
4705                         return;
4706
4707                 case LISTEN_SIG_ASSIGN_PEND:
4708                         if (rc == ASSIGN_OK)
4709                         {
4710                                 plci->internal_command = 0;
4711                                 dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci->Sig.Id));
4712                                 add_p(plci, ESC, "\x02\x18\x00");             /* support call waiting */
4713                                 sig_req(plci, INDICATE_REQ, 0);
4714                                 send_req(plci);
4715                         }
4716                         else
4717                         {
4718                                 dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc));
4719                                 a->listen_active--;
4720                                 plci_remove(plci);
4721                                 plci->State = IDLE;
4722                         }
4723                         break;
4724
4725                 case USELAW_REQ:
4726                         if (global_req == ASSIGN)
4727                         {
4728                                 if (rc == ASSIGN_OK)
4729                                 {
4730                                         sig_req(plci, LAW_REQ, 0);
4731                                         send_req(plci);
4732                                         dbug(1, dprintf("Auto-Law assigned"));
4733                                 }
4734                                 else
4735                                 {
4736                                         dbug(1, dprintf("Auto-Law assign failed"));
4737                                         a->automatic_law = 3;
4738                                         plci->internal_command = 0;
4739                                         a->automatic_lawPLCI = NULL;
4740                                 }
4741                                 break;
4742                         }
4743                         else if (req == LAW_REQ && rc == OK)
4744                         {
4745                                 dbug(1, dprintf("Auto-Law initiated"));
4746                                 a->automatic_law = 2;
4747                                 plci->internal_command = 0;
4748                         }
4749                         else
4750                         {
4751                                 dbug(1, dprintf("Auto-Law not supported"));
4752                                 a->automatic_law = 3;
4753                                 plci->internal_command = 0;
4754                                 sig_req(plci, REMOVE, 0);
4755                                 send_req(plci);
4756                                 a->automatic_lawPLCI = NULL;
4757                         }
4758                         break;
4759                 }
4760                 plci_remove_check(plci);
4761         }
4762 }
4763
4764 static void data_rc(PLCI *plci, byte ch)
4765 {
4766         dword Id;
4767         DIVA_CAPI_ADAPTER *a;
4768         NCCI *ncci_ptr;
4769         DATA_B3_DESC *data;
4770         word ncci;
4771
4772         if (plci->appl)
4773         {
4774                 TransmitBufferFree(plci->appl, plci->data_sent_ptr);
4775                 a = plci->adapter;
4776                 ncci = a->ch_ncci[ch];
4777                 if (ncci && (a->ncci_plci[ncci] == plci->Id))
4778                 {
4779                         ncci_ptr = &(a->ncci[ncci]);
4780                         dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr->data_out, ncci_ptr->data_pending));
4781                         if (ncci_ptr->data_pending)
4782                         {
4783                                 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4784                                 if (!(data->Flags & 4) && a->ncci_state[ncci])
4785                                 {
4786                                         Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4787                                         if (plci->tel) Id |= EXT_CONTROLLER;
4788                                         sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, data->Number,
4789                                               "ww", data->Handle, 0);
4790                                 }
4791                                 (ncci_ptr->data_out)++;
4792                                 if (ncci_ptr->data_out == MAX_DATA_B3)
4793                                         ncci_ptr->data_out = 0;
4794                                 (ncci_ptr->data_pending)--;
4795                         }
4796                 }
4797         }
4798 }
4799
4800 static void data_ack(PLCI *plci, byte ch)
4801 {
4802         dword Id;
4803         DIVA_CAPI_ADAPTER *a;
4804         NCCI *ncci_ptr;
4805         word ncci;
4806
4807         a = plci->adapter;
4808         ncci = a->ch_ncci[ch];
4809         ncci_ptr = &(a->ncci[ncci]);
4810         if (ncci_ptr->data_ack_pending)
4811         {
4812                 if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4813                 {
4814                         Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4815                         if (plci->tel) Id |= EXT_CONTROLLER;
4816                         sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4817                               "ww", ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle, 0);
4818                 }
4819                 (ncci_ptr->data_ack_out)++;
4820                 if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4821                         ncci_ptr->data_ack_out = 0;
4822                 (ncci_ptr->data_ack_pending)--;
4823         }
4824 }
4825
4826 static void sig_ind(PLCI *plci)
4827 {
4828         dword x_Id;
4829         dword Id;
4830         dword rId;
4831         word i;
4832         word cip;
4833         dword cip_mask;
4834         byte *ie;
4835         DIVA_CAPI_ADAPTER *a;
4836         API_PARSE saved_parms[MAX_MSG_PARMS + 1];
4837 #define MAXPARMSIDS 31
4838         byte *parms[MAXPARMSIDS];
4839         byte *add_i[4];
4840         byte *multi_fac_parms[MAX_MULTI_IE];
4841         byte *multi_pi_parms[MAX_MULTI_IE];
4842         byte *multi_ssext_parms[MAX_MULTI_IE];
4843         byte *multi_CiPN_parms[MAX_MULTI_IE];
4844
4845         byte *multi_vswitch_parms[MAX_MULTI_IE];
4846
4847         byte ai_len;
4848         byte *esc_chi = "";
4849         byte *esc_law = "";
4850         byte *pty_cai = "";
4851         byte *esc_cr  = "";
4852         byte *esc_profile = "";
4853
4854         byte facility[256];
4855         PLCI *tplci = NULL;
4856         byte chi[] = "\x02\x18\x01";
4857         byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4858         byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4859         /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4860         /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4861         /* SMSG is situated at the end because its 0 (for compatibility reasons */
4862         /* (see Info_Mask Bit 4, first IE. then the message type)           */
4863         word parms_id[] =
4864                 {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4865                  UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4866                  RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4867                  CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4868         /* 14 FTY repl by ESC_CHI */
4869         /* 18 PI  repl by ESC_LAW */
4870         /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4871         word multi_fac_id[] = {1, FTY};
4872         word multi_pi_id[]  = {1, PI};
4873         word multi_CiPN_id[]  = {1, OAD};
4874         word multi_ssext_id[]  = {1, ESC_SSEXT};
4875
4876         word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4877
4878         byte *cau;
4879         word ncci;
4880         byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4881         byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4882         byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4883         byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\x00\x00\x00\x00";
4884         byte force_mt_info = false;
4885         byte dir;
4886         dword d;
4887         word w;
4888
4889         a = plci->adapter;
4890         Id = ((word)plci->Id << 8) | a->Id;
4891         PUT_WORD(&SS_Ind[4], 0x0000);
4892
4893         if (plci->sig_remove_id)
4894         {
4895                 plci->Sig.RNR = 2; /* discard */
4896                 dbug(1, dprintf("SIG discard while remove pending"));
4897                 return;
4898         }
4899         if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4900         dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4901                         Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4902         if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4903         {
4904                 plci->Sig.RNR = 1;
4905                 return;
4906         }
4907         if (plci->Sig.Ind == HANGUP && plci->channels)
4908         {
4909                 plci->Sig.RNR = 1;
4910                 plci->hangup_flow_ctrl_timer++;
4911                 /* recover the network layer after timeout */
4912                 if (plci->hangup_flow_ctrl_timer == 100)
4913                 {
4914                         dbug(1, dprintf("Exceptional disc"));
4915                         plci->Sig.RNR = 0;
4916                         plci->hangup_flow_ctrl_timer = 0;
4917                         for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4918                         {
4919                                 if (a->ncci_plci[ncci] == plci->Id)
4920                                 {
4921                                         cleanup_ncci_data(plci, ncci);
4922                                         if (plci->channels)plci->channels--;
4923                                         if (plci->appl)
4924                                                 sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4925                                 }
4926                         }
4927                         if (plci->appl)
4928                                 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4929                         plci_remove(plci);
4930                         plci->State = IDLE;
4931                 }
4932                 return;
4933         }
4934
4935         /* do first parse the info with no OAD in, because OAD will be converted */
4936         /* first the multiple facility IE, then mult. progress ind.              */
4937         /* then the parameters for the info_ind + conn_ind                       */
4938         IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4939         IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4940         IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4941
4942         IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4943
4944         IndParse(plci, parms_id, parms, 0);
4945         IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4946         esc_chi  = parms[14];
4947         esc_law  = parms[18];
4948         pty_cai  = parms[24];
4949         esc_cr   = parms[25];
4950         esc_profile = parms[27];
4951         if (esc_cr[0] && plci)
4952         {
4953                 if (plci->cr_enquiry && plci->appl)
4954                 {
4955                         plci->cr_enquiry = false;
4956                         /* d = MANU_ID            */
4957                         /* w = m_command          */
4958                         /* b = total length       */
4959                         /* b = indication type    */
4960                         /* b = length of all IEs  */
4961                         /* b = IE1                */
4962                         /* S = IE1 length + cont. */
4963                         /* b = IE2                */
4964                         /* S = IE2 length + cont. */
4965                         sendf(plci->appl,
4966                               _MANUFACTURER_I,
4967                               Id,
4968                               0,
4969                               "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4970                               2 + 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], plci->Sig.Ind, 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], ESC, esc_cr, ESC, esc_law);
4971                 }
4972         }
4973         /* create the additional info structure                                  */
4974         add_i[1] = parms[15]; /* KEY of additional info */
4975         add_i[2] = parms[11]; /* UUI of additional info */
4976         ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4977
4978         /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4979         /* indication returns by the card if requested by the function           */
4980         /* AutomaticLaw() after driver init                                      */
4981         if (a->automatic_law < 4)
4982         {
4983                 if (esc_law[0]) {
4984                         if (esc_law[2]) {
4985                                 dbug(0, dprintf("u-Law selected"));
4986                                 a->u_law = 1;
4987                         }
4988                         else {
4989                                 dbug(0, dprintf("a-Law selected"));
4990                                 a->u_law = 0;
4991                         }
4992                         a->automatic_law = 4;
4993                         if (plci == a->automatic_lawPLCI) {
4994                                 plci->internal_command = 0;
4995                                 sig_req(plci, REMOVE, 0);
4996                                 send_req(plci);
4997                                 a->automatic_lawPLCI = NULL;
4998                         }
4999                 }
5000                 if (esc_profile[0])
5001                 {
5002                         dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
5003                                         UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
5004                                         GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
5005                                         GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
5006
5007                         a->profile.Global_Options &= 0x000000ffL;
5008                         a->profile.B1_Protocols &= 0x000003ffL;
5009                         a->profile.B2_Protocols &= 0x00001fdfL;
5010                         a->profile.B3_Protocols &= 0x000000b7L;
5011
5012                         a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
5013                                 GL_BCHANNEL_OPERATION_SUPPORTED;
5014                         a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
5015                         a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
5016                         a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
5017                         a->manufacturer_features = GET_DWORD(&esc_profile[46]);
5018                         a->man_profile.private_options = 0;
5019
5020                         if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5021                         {
5022                                 a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5023                                 a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5024                         }
5025
5026
5027                         if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5028                                 a->man_profile.private_options |= 1L << PRIVATE_RTP;
5029                         a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
5030                         a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
5031
5032
5033                         if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5034                                 a->man_profile.private_options |= 1L << PRIVATE_T38;
5035
5036
5037                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5038                                 a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5039
5040
5041                         if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5042                                 a->man_profile.private_options |= 1L << PRIVATE_V18;
5043
5044
5045                         if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5046                                 a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5047
5048
5049                         if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5050                                 a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5051
5052
5053                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5054                                 a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5055
5056
5057                         if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5058                                 a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5059
5060
5061                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5062                                 a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5063
5064                 }
5065                 else
5066                 {
5067                         a->profile.Global_Options &= 0x0000007fL;
5068                         a->profile.B1_Protocols &= 0x000003dfL;
5069                         a->profile.B2_Protocols &= 0x00001adfL;
5070                         a->profile.B3_Protocols &= 0x000000b7L;
5071                         a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5072                 }
5073                 if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5074                                                 MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5075                 {
5076                         a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5077                 }
5078                 a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5079                 dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
5080                                 UnMapController(a->Id), a->profile.Global_Options,
5081                                 a->profile.B1_Protocols, a->profile.B2_Protocols,
5082                                 a->profile.B3_Protocols, a->manufacturer_features));
5083         }
5084         /* codec plci for the handset/hook state support is just an internal id  */
5085         if (plci != a->AdvCodecPLCI)
5086         {
5087                 force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
5088                 force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
5089                 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5090                 SendInfo(plci, Id, parms, force_mt_info);
5091
5092                 VSwitchReqInd(plci, Id, multi_vswitch_parms);
5093
5094         }
5095
5096         /* switch the codec to the b-channel                                     */
5097         if (esc_chi[0] && plci && !plci->SuppState) {
5098                 plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5099                 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5100                 dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
5101                 if (plci->tel == ADV_VOICE && plci->appl) {
5102                         SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5103                 }
5104         }
5105
5106         if (plci->appl) plci->appl->Number++;
5107
5108         switch (plci->Sig.Ind) {
5109                 /* Response to Get_Supported_Services request */
5110         case S_SUPPORTED:
5111                 dbug(1, dprintf("S_Supported"));
5112                 if (!plci->appl) break;
5113                 if (pty_cai[0] == 4)
5114                 {
5115                         PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
5116                 }
5117                 else
5118                 {
5119                         PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5120                 }
5121                 PUT_WORD(&CF_Ind[1], 0);
5122                 PUT_WORD(&CF_Ind[4], 0);
5123                 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
5124                 plci_remove(plci);
5125                 break;
5126
5127                 /* Supplementary Service rejected */
5128         case S_SERVICE_REJ:
5129                 dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5130                 if (!pty_cai[0]) break;
5131                 switch (pty_cai[5])
5132                 {
5133                 case ECT_EXECUTE:
5134                 case THREE_PTY_END:
5135                 case THREE_PTY_BEGIN:
5136                         if (!plci->relatedPTYPLCI) break;
5137                         tplci = plci->relatedPTYPLCI;
5138                         rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5139                         if (tplci->tel) rId |= EXT_CONTROLLER;
5140                         if (pty_cai[5] == ECT_EXECUTE)
5141                         {
5142                                 PUT_WORD(&SS_Ind[1], S_ECT);
5143
5144                                 plci->vswitchstate = 0;
5145                                 plci->relatedPTYPLCI->vswitchstate = 0;
5146
5147                         }
5148                         else
5149                         {
5150                                 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5151                         }
5152                         if (pty_cai[2] != 0xff)
5153                         {
5154                                 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5155                         }
5156                         else
5157                         {
5158                                 PUT_WORD(&SS_Ind[4], 0x300E);
5159                         }
5160                         plci->relatedPTYPLCI = NULL;
5161                         plci->ptyState = 0;
5162                         sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5163                         break;
5164
5165                 case CALL_DEFLECTION:
5166                         if (pty_cai[2] != 0xff)
5167                         {
5168                                 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5169                         }
5170                         else
5171                         {
5172                                 PUT_WORD(&SS_Ind[4], 0x300E);
5173                         }
5174                         PUT_WORD(&SS_Ind[1], pty_cai[5]);
5175                         for (i = 0; i < max_appl; i++)
5176                         {
5177                                 if (application[i].CDEnable)
5178                                 {
5179                                         if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5180                                         application[i].CDEnable = false;
5181                                 }
5182                         }
5183                         break;
5184
5185                 case DEACTIVATION_DIVERSION:
5186                 case ACTIVATION_DIVERSION:
5187                 case DIVERSION_INTERROGATE_CFU:
5188                 case DIVERSION_INTERROGATE_CFB:
5189                 case DIVERSION_INTERROGATE_CFNR:
5190                 case DIVERSION_INTERROGATE_NUM:
5191                 case CCBS_REQUEST:
5192                 case CCBS_DEACTIVATE:
5193                 case CCBS_INTERROGATE:
5194                         if (!plci->appl) break;
5195                         if (pty_cai[2] != 0xff)
5196                         {
5197                                 PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5198                         }
5199                         else
5200                         {
5201                                 PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5202                         }
5203                         switch (pty_cai[5])
5204                         {
5205                         case DEACTIVATION_DIVERSION:
5206                                 dbug(1, dprintf("Deact_Div"));
5207                                 Interr_Err_Ind[0] = 0x9;
5208                                 Interr_Err_Ind[3] = 0x6;
5209                                 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5210                                 break;
5211                         case ACTIVATION_DIVERSION:
5212                                 dbug(1, dprintf("Act_Div"));
5213                                 Interr_Err_Ind[0] = 0x9;
5214                                 Interr_Err_Ind[3] = 0x6;
5215                                 PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5216                                 break;
5217                         case DIVERSION_INTERROGATE_CFU:
5218                         case DIVERSION_INTERROGATE_CFB:
5219                         case DIVERSION_INTERROGATE_CFNR:
5220                                 dbug(1, dprintf("Interr_Div"));
5221                                 Interr_Err_Ind[0] = 0xa;
5222                                 Interr_Err_Ind[3] = 0x7;
5223                                 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5224                                 break;
5225                         case DIVERSION_INTERROGATE_NUM:
5226                                 dbug(1, dprintf("Interr_Num"));
5227                                 Interr_Err_Ind[0] = 0xa;
5228                                 Interr_Err_Ind[3] = 0x7;
5229                                 PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5230                                 break;
5231                         case CCBS_REQUEST:
5232                                 dbug(1, dprintf("CCBS Request"));
5233                                 Interr_Err_Ind[0] = 0xd;
5234                                 Interr_Err_Ind[3] = 0xa;
5235                                 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5236                                 break;
5237                         case CCBS_DEACTIVATE:
5238                                 dbug(1, dprintf("CCBS Deactivate"));
5239                                 Interr_Err_Ind[0] = 0x9;
5240                                 Interr_Err_Ind[3] = 0x6;
5241                                 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5242                                 break;
5243                         case CCBS_INTERROGATE:
5244                                 dbug(1, dprintf("CCBS Interrogate"));
5245                                 Interr_Err_Ind[0] = 0xb;
5246                                 Interr_Err_Ind[3] = 0x8;
5247                                 PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5248                                 break;
5249                         }
5250                         PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5251                         sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5252                         plci_remove(plci);
5253                         break;
5254                 case ACTIVATION_MWI:
5255                 case DEACTIVATION_MWI:
5256                         if (pty_cai[5] == ACTIVATION_MWI)
5257                         {
5258                                 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5259                         }
5260                         else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5261
5262                         if (pty_cai[2] != 0xff)
5263                         {
5264                                 PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5265                         }
5266                         else
5267                         {
5268                                 PUT_WORD(&SS_Ind[4], 0x300E);
5269                         }
5270
5271                         if (plci->cr_enquiry)
5272                         {
5273                                 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5274                                 plci_remove(plci);
5275                         }
5276                         else
5277                         {
5278                                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5279                         }
5280                         break;
5281                 case CONF_ADD: /* ERROR */
5282                 case CONF_BEGIN:
5283                 case CONF_DROP:
5284                 case CONF_ISOLATE:
5285                 case CONF_REATTACH:
5286                         CONF_Ind[0] = 9;
5287                         CONF_Ind[3] = 6;
5288                         switch (pty_cai[5])
5289                         {
5290                         case CONF_BEGIN:
5291                                 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5292                                 plci->ptyState = 0;
5293                                 break;
5294                         case CONF_DROP:
5295                                 CONF_Ind[0] = 5;
5296                                 CONF_Ind[3] = 2;
5297                                 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5298                                 plci->ptyState = CONNECTED;
5299                                 break;
5300                         case CONF_ISOLATE:
5301                                 CONF_Ind[0] = 5;
5302                                 CONF_Ind[3] = 2;
5303                                 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5304                                 plci->ptyState = CONNECTED;
5305                                 break;
5306                         case CONF_REATTACH:
5307                                 CONF_Ind[0] = 5;
5308                                 CONF_Ind[3] = 2;
5309                                 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5310                                 plci->ptyState = CONNECTED;
5311                                 break;
5312                         case CONF_ADD:
5313                                 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5314                                 plci->relatedPTYPLCI = NULL;
5315                                 tplci = plci->relatedPTYPLCI;
5316                                 if (tplci) tplci->ptyState = CONNECTED;
5317                                 plci->ptyState = CONNECTED;
5318                                 break;
5319                         }
5320
5321                         if (pty_cai[2] != 0xff)
5322                         {
5323                                 PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5324                         }
5325                         else
5326                         {
5327                                 PUT_WORD(&CONF_Ind[4], 0x3303); /* Time-out: network did not respond
5328                                                                   within the required time */
5329                         }
5330
5331                         PUT_DWORD(&CONF_Ind[6], 0x0);
5332                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5333                         break;
5334                 }
5335                 break;
5336
5337                 /* Supplementary Service indicates success */
5338         case S_SERVICE:
5339                 dbug(1, dprintf("Service_Ind"));
5340                 PUT_WORD(&CF_Ind[4], 0);
5341                 switch (pty_cai[5])
5342                 {
5343                 case THREE_PTY_END:
5344                 case THREE_PTY_BEGIN:
5345                 case ECT_EXECUTE:
5346                         if (!plci->relatedPTYPLCI) break;
5347                         tplci = plci->relatedPTYPLCI;
5348                         rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5349                         if (tplci->tel) rId |= EXT_CONTROLLER;
5350                         if (pty_cai[5] == ECT_EXECUTE)
5351                         {
5352                                 PUT_WORD(&SS_Ind[1], S_ECT);
5353
5354                                 if (plci->vswitchstate != 3)
5355                                 {
5356
5357                                         plci->ptyState = IDLE;
5358                                         plci->relatedPTYPLCI = NULL;
5359                                         plci->ptyState = 0;
5360
5361                                 }
5362
5363                                 dbug(1, dprintf("ECT OK"));
5364                                 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5365
5366
5367
5368                         }
5369                         else
5370                         {
5371                                 switch (plci->ptyState)
5372                                 {
5373                                 case S_3PTY_BEGIN:
5374                                         plci->ptyState = CONNECTED;
5375                                         dbug(1, dprintf("3PTY ON"));
5376                                         break;
5377
5378                                 case S_3PTY_END:
5379                                         plci->ptyState = IDLE;
5380                                         plci->relatedPTYPLCI = NULL;
5381                                         plci->ptyState = 0;
5382                                         dbug(1, dprintf("3PTY OFF"));
5383                                         break;
5384                                 }
5385                                 PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5386                                 sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5387                         }
5388                         break;
5389
5390                 case CALL_DEFLECTION:
5391                         PUT_WORD(&SS_Ind[1], pty_cai[5]);
5392                         for (i = 0; i < max_appl; i++)
5393                         {
5394                                 if (application[i].CDEnable)
5395                                 {
5396                                         if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5397                                         application[i].CDEnable = false;
5398                                 }
5399                         }
5400                         break;
5401
5402                 case DEACTIVATION_DIVERSION:
5403                 case ACTIVATION_DIVERSION:
5404                         if (!plci->appl) break;
5405                         PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5406                         PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5407                         sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5408                         plci_remove(plci);
5409                         break;
5410
5411                 case DIVERSION_INTERROGATE_CFU:
5412                 case DIVERSION_INTERROGATE_CFB:
5413                 case DIVERSION_INTERROGATE_CFNR:
5414                 case DIVERSION_INTERROGATE_NUM:
5415                 case CCBS_REQUEST:
5416                 case CCBS_DEACTIVATE:
5417                 case CCBS_INTERROGATE:
5418                         if (!plci->appl) break;
5419                         switch (pty_cai[5])
5420                         {
5421                         case DIVERSION_INTERROGATE_CFU:
5422                         case DIVERSION_INTERROGATE_CFB:
5423                         case DIVERSION_INTERROGATE_CFNR:
5424                                 dbug(1, dprintf("Interr_Div"));
5425                                 PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5426                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5427                                 break;
5428                         case DIVERSION_INTERROGATE_NUM:
5429                                 dbug(1, dprintf("Interr_Num"));
5430                                 PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5431                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5432                                 break;
5433                         case CCBS_REQUEST:
5434                                 dbug(1, dprintf("CCBS Request"));
5435                                 PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5436                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5437                                 break;
5438                         case CCBS_DEACTIVATE:
5439                                 dbug(1, dprintf("CCBS Deactivate"));
5440                                 PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5441                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5442                                 break;
5443                         case CCBS_INTERROGATE:
5444                                 dbug(1, dprintf("CCBS Interrogate"));
5445                                 PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5446                                 pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5447                                 break;
5448                         }
5449                         PUT_WORD(&pty_cai[4], 0); /* Supplementary Service Reason */
5450                         PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5451                         sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5452                         plci_remove(plci);
5453                         break;
5454
5455                 case ACTIVATION_MWI:
5456                 case DEACTIVATION_MWI:
5457                         if (pty_cai[5] == ACTIVATION_MWI)
5458                         {
5459                                 PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5460                         }
5461                         else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5462                         if (plci->cr_enquiry)
5463                         {
5464                                 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5465                                 plci_remove(plci);
5466                         }
5467                         else
5468                         {
5469                                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5470                         }
5471                         break;
5472                 case MWI_INDICATION:
5473                         if (pty_cai[0] >= 0x12)
5474                         {
5475                                 PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5476                                 pty_cai[2] = pty_cai[0] - 2; /* len Parameter */
5477                                 pty_cai[5] = pty_cai[0] - 5; /* Supplementary Service-specific parameter len */
5478                                 if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5479                                 {
5480                                         if (plci->internal_command == GET_MWI_STATE) /* result on Message Waiting Listen */
5481                                         {
5482                                                 sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5483                                                 plci_remove(plci);
5484                                                 return;
5485                                         }
5486                                         else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5487                                         pty_cai[0] = 0;
5488                                 }
5489                                 else
5490                                 {
5491                                         for (i = 0; i < max_appl; i++)
5492                                         {
5493                                                 if (a->Notification_Mask[i]&SMASK_MWI)
5494                                                 {
5495                                                         sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5496                                                         pty_cai[0] = 0;
5497                                                 }
5498                                         }
5499                                 }
5500
5501                                 if (!pty_cai[0])
5502                                 { /* acknowledge */
5503                                         facility[2] = 0; /* returncode */
5504                                 }
5505                                 else facility[2] = 0xff;
5506                         }
5507                         else
5508                         {
5509                                 /* reject */
5510                                 facility[2] = 0xff; /* returncode */
5511                         }
5512                         facility[0] = 2;
5513                         facility[1] = MWI_RESPONSE; /* Function */
5514                         add_p(plci, CAI, facility);
5515                         add_p(plci, ESC, multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5516                         sig_req(plci, S_SERVICE, 0);
5517                         send_req(plci);
5518                         plci->command = 0;
5519                         next_internal_command(Id, plci);
5520                         break;
5521                 case CONF_ADD: /* OK */
5522                 case CONF_BEGIN:
5523                 case CONF_DROP:
5524                 case CONF_ISOLATE:
5525                 case CONF_REATTACH:
5526                 case CONF_PARTYDISC:
5527                         CONF_Ind[0] = 9;
5528                         CONF_Ind[3] = 6;
5529                         switch (pty_cai[5])
5530                         {
5531                         case CONF_BEGIN:
5532                                 PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5533                                 if (pty_cai[0] == 6)
5534                                 {
5535                                         d = pty_cai[6];
5536                                         PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5537                                 }
5538                                 else
5539                                 {
5540                                         PUT_DWORD(&CONF_Ind[6], 0x0);
5541                                 }
5542                                 break;
5543                         case CONF_ISOLATE:
5544                                 PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5545                                 CONF_Ind[0] = 5;
5546                                 CONF_Ind[3] = 2;
5547                                 break;
5548                         case CONF_REATTACH:
5549                                 PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5550                                 CONF_Ind[0] = 5;
5551                                 CONF_Ind[3] = 2;
5552                                 break;
5553                         case CONF_DROP:
5554                                 PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5555                                 CONF_Ind[0] = 5;
5556                                 CONF_Ind[3] = 2;
5557                                 break;
5558                         case CONF_ADD:
5559                                 PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5560                                 d = pty_cai[6];
5561                                 PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5562                                 tplci = plci->relatedPTYPLCI;
5563                                 if (tplci) tplci->ptyState = CONNECTED;
5564                                 break;
5565                         case CONF_PARTYDISC:
5566                                 CONF_Ind[0] = 7;
5567                                 CONF_Ind[3] = 4;
5568                                 PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5569                                 d = pty_cai[6];
5570                                 PUT_DWORD(&CONF_Ind[4], d); /* PartyID */
5571                                 break;
5572                         }
5573                         plci->ptyState = CONNECTED;
5574                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5575                         break;
5576                 case CCBS_INFO_RETAIN:
5577                 case CCBS_ERASECALLLINKAGEID:
5578                 case CCBS_STOP_ALERTING:
5579                         CONF_Ind[0] = 5;
5580                         CONF_Ind[3] = 2;
5581                         switch (pty_cai[5])
5582                         {
5583                         case CCBS_INFO_RETAIN:
5584                                 PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5585                                 break;
5586                         case CCBS_STOP_ALERTING:
5587                                 PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5588                                 break;
5589                         case CCBS_ERASECALLLINKAGEID:
5590                                 PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5591                                 CONF_Ind[0] = 7;
5592                                 CONF_Ind[3] = 4;
5593                                 CONF_Ind[6] = 0;
5594                                 CONF_Ind[7] = 0;
5595                                 break;
5596                         }
5597                         w = pty_cai[6];
5598                         PUT_WORD(&CONF_Ind[4], w); /* PartyID */
5599
5600                         if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5601                         {
5602                                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5603                         }
5604                         else
5605                         {
5606                                 for (i = 0; i < max_appl; i++)
5607                                         if (a->Notification_Mask[i] & SMASK_CCBS)
5608                                                 sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5609                         }
5610                         break;
5611                 }
5612                 break;
5613         case CALL_HOLD_REJ:
5614                 cau = parms[7];
5615                 if (cau)
5616                 {
5617                         i = _L3_CAUSE | cau[2];
5618                         if (cau[2] == 0) i = 0x3603;
5619                 }
5620                 else
5621                 {
5622                         i = 0x3603;
5623                 }
5624                 PUT_WORD(&SS_Ind[1], S_HOLD);
5625                 PUT_WORD(&SS_Ind[4], i);
5626                 if (plci->SuppState == HOLD_REQUEST)
5627                 {
5628                         plci->SuppState = IDLE;
5629                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5630                 }
5631                 break;
5632
5633         case CALL_HOLD_ACK:
5634                 if (plci->SuppState == HOLD_REQUEST)
5635                 {
5636                         plci->SuppState = CALL_HELD;
5637                         CodecIdCheck(a, plci);
5638                         start_internal_command(Id, plci, hold_save_command);
5639                 }
5640                 break;
5641
5642         case CALL_RETRIEVE_REJ:
5643                 cau = parms[7];
5644                 if (cau)
5645                 {
5646                         i = _L3_CAUSE | cau[2];
5647                         if (cau[2] == 0) i = 0x3603;
5648                 }
5649                 else
5650                 {
5651                         i = 0x3603;
5652                 }
5653                 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5654                 PUT_WORD(&SS_Ind[4], i);
5655                 if (plci->SuppState == RETRIEVE_REQUEST)
5656                 {
5657                         plci->SuppState = CALL_HELD;
5658                         CodecIdCheck(a, plci);
5659                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5660                 }
5661                 break;
5662
5663         case CALL_RETRIEVE_ACK:
5664                 PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5665                 if (plci->SuppState == RETRIEVE_REQUEST)
5666                 {
5667                         plci->SuppState = IDLE;
5668                         plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5669                         plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5670                         if (plci->tel)
5671                         {
5672                                 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5673                                 dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5674                                 SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5675                                 if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5676                                 {
5677                                         dbug(1, dprintf("Get B-ch"));
5678                                         start_internal_command(Id, plci, retrieve_restore_command);
5679                                 }
5680                                 else
5681                                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5682                         }
5683                         else
5684                                 start_internal_command(Id, plci, retrieve_restore_command);
5685                 }
5686                 break;
5687
5688         case INDICATE_IND:
5689                 if (plci->State != LISTENING) {
5690                         sig_req(plci, HANGUP, 0);
5691                         send_req(plci);
5692                         break;
5693                 }
5694                 cip = find_cip(a, parms[4], parms[6]);
5695                 cip_mask = 1L << cip;
5696                 dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5697                 clear_c_ind_mask(plci);
5698                 if (!remove_started && !a->adapter_disabled)
5699                 {
5700                         set_c_ind_mask_bit(plci, MAX_APPL);
5701                         group_optimization(a, plci);
5702                         for (i = 0; i < max_appl; i++) {
5703                                 if (application[i].Id
5704                                     && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5705                                     && CPN_filter_ok(parms[0], a, i)
5706                                     && test_group_ind_mask_bit(plci, i)) {
5707                                         dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5708                                         set_c_ind_mask_bit(plci, i);
5709                                         dump_c_ind_mask(plci);
5710                                         plci->State = INC_CON_PENDING;
5711                                         plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5712                                                 CALL_DIR_IN | CALL_DIR_ANSWER;
5713                                         if (esc_chi[0]) {
5714                                                 plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5715                                                 mixer_set_bchannel_id_esc(plci, plci->b_channel);
5716                                         }
5717                                         /* if a listen on the ext controller is done, check if hook states */
5718                                         /* are supported or if just a on board codec must be activated     */
5719                                         if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5720                                                 if (a->profile.Global_Options & HANDSET)
5721                                                         plci->tel = ADV_VOICE;
5722                                                 else if (a->profile.Global_Options & ON_BOARD_CODEC)
5723                                                         plci->tel = CODEC;
5724                                                 if (plci->tel) Id |= EXT_CONTROLLER;
5725                                                 a->codec_listen[i] = plci;
5726                                         }
5727
5728                                         sendf(&application[i], _CONNECT_I, Id, 0,
5729                                               "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5730                                               parms[0],    /* CalledPartyNumber   */
5731                                               multi_CiPN_parms[0],    /* CallingPartyNumber  */
5732                                               parms[2],    /* CalledPartySubad    */
5733                                               parms[3],    /* CallingPartySubad   */
5734                                               parms[4],    /* BearerCapability    */
5735                                               parms[5],    /* LowLC               */
5736                                               parms[6],    /* HighLC              */
5737                                               ai_len,      /* nested struct add_i */
5738                                               add_i[0],    /* B channel info    */
5739                                               add_i[1],    /* keypad facility   */
5740                                               add_i[2],    /* user user data    */
5741                                               add_i[3],    /* nested facility   */
5742                                               multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5743                                                 );
5744                                         SendSSExtInd(&application[i],
5745                                                      plci,
5746                                                      Id,
5747                                                      multi_ssext_parms);
5748                                         SendSetupInfo(&application[i],
5749                                                       plci,
5750                                                       Id,
5751                                                       parms,
5752                                                       SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5753                                 }
5754                         }
5755                         clear_c_ind_mask_bit(plci, MAX_APPL);
5756                         dump_c_ind_mask(plci);
5757                 }
5758                 if (c_ind_mask_empty(plci)) {
5759                         sig_req(plci, HANGUP, 0);
5760                         send_req(plci);
5761                         plci->State = IDLE;
5762                 }
5763                 plci->notifiedcall = 0;
5764                 a->listen_active--;
5765                 listen_check(a);
5766                 break;
5767
5768         case CALL_PEND_NOTIFY:
5769                 plci->notifiedcall = 1;
5770                 listen_check(a);
5771                 break;
5772
5773         case CALL_IND:
5774         case CALL_CON:
5775                 if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5776                 {
5777                         if (plci->internal_command == PERM_COD_CONN_PEND)
5778                         {
5779                                 if (plci->State == ADVANCED_VOICE_NOSIG)
5780                                 {
5781                                         dbug(1, dprintf("***Codec OK"));
5782                                         if (a->AdvSignalPLCI)
5783                                         {
5784                                                 tplci = a->AdvSignalPLCI;
5785                                                 if (tplci->spoofed_msg)
5786                                                 {
5787                                                         dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5788                                                         tplci->command = 0;
5789                                                         tplci->internal_command = 0;
5790                                                         x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5791                                                         switch (tplci->spoofed_msg)
5792                                                         {
5793                                                         case CALL_RES:
5794                                                                 tplci->command = _CONNECT_I | RESPONSE;
5795                                                                 api_load_msg(&tplci->saved_msg, saved_parms);
5796                                                                 add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5797                                                                 if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5798                                                                 {
5799                                                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
5800                                                                         add_p(tplci, LLI, "\x01\x01");
5801                                                                 }
5802                                                                 add_s(tplci, CONN_NR, &saved_parms[2]);
5803                                                                 add_s(tplci, LLC, &saved_parms[4]);
5804                                                                 add_ai(tplci, &saved_parms[5]);
5805                                                                 tplci->State = INC_CON_ACCEPT;
5806                                                                 sig_req(tplci, CALL_RES, 0);
5807                                                                 send_req(tplci);
5808                                                                 break;
5809
5810                                                         case AWAITING_SELECT_B:
5811                                                                 dbug(1, dprintf("Select_B continue"));
5812                                                                 start_internal_command(x_Id, tplci, select_b_command);
5813                                                                 break;
5814
5815                                                         case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5816                                                                 if (!tplci->Sig.Id)
5817                                                                 {
5818                                                                         dbug(1, dprintf("No SigID!"));
5819                                                                         sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5820                                                                         plci_remove(tplci);
5821                                                                         break;
5822                                                                 }
5823                                                                 tplci->command = _MANUFACTURER_R;
5824                                                                 api_load_msg(&tplci->saved_msg, saved_parms);
5825                                                                 dir = saved_parms[2].info[0];
5826                                                                 if (dir == 1) {
5827                                                                         sig_req(tplci, CALL_REQ, 0);
5828                                                                 }
5829                                                                 else if (!dir) {
5830                                                                         sig_req(tplci, LISTEN_REQ, 0);
5831                                                                 }
5832                                                                 send_req(tplci);
5833                                                                 sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5834                                                                 break;
5835
5836                                                         case (CALL_REQ | AWAITING_MANUF_CON):
5837                                                                 sig_req(tplci, CALL_REQ, 0);
5838                                                                 send_req(tplci);
5839                                                                 break;
5840
5841                                                         case CALL_REQ:
5842                                                                 if (!tplci->Sig.Id)
5843                                                                 {
5844                                                                         dbug(1, dprintf("No SigID!"));
5845                                                                         sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5846                                                                         plci_remove(tplci);
5847                                                                         break;
5848                                                                 }
5849                                                                 tplci->command = _CONNECT_R;
5850                                                                 api_load_msg(&tplci->saved_msg, saved_parms);
5851                                                                 add_s(tplci, CPN, &saved_parms[1]);
5852                                                                 add_s(tplci, DSA, &saved_parms[3]);
5853                                                                 add_ai(tplci, &saved_parms[9]);
5854                                                                 sig_req(tplci, CALL_REQ, 0);
5855                                                                 send_req(tplci);
5856                                                                 break;
5857
5858                                                         case CALL_RETRIEVE:
5859                                                                 tplci->command = C_RETRIEVE_REQ;
5860                                                                 sig_req(tplci, CALL_RETRIEVE, 0);
5861                                                                 send_req(tplci);
5862                                                                 break;
5863                                                         }
5864                                                         tplci->spoofed_msg = 0;
5865                                                         if (tplci->internal_command == 0)
5866                                                                 next_internal_command(x_Id, tplci);
5867                                                 }
5868                                         }
5869                                         next_internal_command(Id, plci);
5870                                         break;
5871                                 }
5872                                 dbug(1, dprintf("***Codec Hook Init Req"));
5873                                 plci->internal_command = PERM_COD_HOOK;
5874                                 add_p(plci, FTY, "\x01\x09");             /* Get Hook State*/
5875                                 sig_req(plci, TEL_CTRL, 0);
5876                                 send_req(plci);
5877                         }
5878                 }
5879                 else if (plci->command != _MANUFACTURER_R  /* old style permanent connect */
5880                          && plci->State != INC_ACT_PENDING)
5881                 {
5882                         mixer_set_bchannel_id_esc(plci, plci->b_channel);
5883                         if (plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5884                         {
5885                                 chi[2] = plci->b_channel;
5886                                 SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5887                         }
5888                         sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5889                         plci->State = INC_ACT_PENDING;
5890                 }
5891                 break;
5892
5893         case TEL_CTRL:
5894                 ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5895                 if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5896                         switch (ie[1] & 0x91) {
5897                         case 0x80:   /* hook off */
5898                         case 0x81:
5899                                 if (plci->internal_command == PERM_COD_HOOK)
5900                                 {
5901                                         dbug(1, dprintf("init:hook_off"));
5902                                         plci->hook_state = ie[1];
5903                                         next_internal_command(Id, plci);
5904                                         break;
5905                                 }
5906                                 else /* ignore doubled hook indications */
5907                                 {
5908                                         if (((plci->hook_state) & 0xf0) == 0x80)
5909                                         {
5910                                                 dbug(1, dprintf("ignore hook"));
5911                                                 break;
5912                                         }
5913                                         plci->hook_state = ie[1]&0x91;
5914                                 }
5915                                 /* check for incoming call pending */
5916                                 /* and signal '+'.Appl must decide */
5917                                 /* with connect_res if call must   */
5918                                 /* accepted or not                 */
5919                                 for (i = 0, tplci = NULL; i < max_appl; i++) {
5920                                         if (a->codec_listen[i]
5921                                             && (a->codec_listen[i]->State == INC_CON_PENDING
5922                                                 || a->codec_listen[i]->State == INC_CON_ALERT)) {
5923                                                 tplci = a->codec_listen[i];
5924                                                 tplci->appl = &application[i];
5925                                         }
5926                                 }
5927                                 /* no incoming call, do outgoing call */
5928                                 /* and signal '+' if outg. setup   */
5929                                 if (!a->AdvSignalPLCI && !tplci) {
5930                                         if ((i = get_plci(a))) {
5931                                                 a->AdvSignalPLCI = &a->plci[i - 1];
5932                                                 tplci = a->AdvSignalPLCI;
5933                                                 tplci->tel  = ADV_VOICE;
5934                                                 PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5935                                                 if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5936                                                         /* early B3 connect (CIP mask bit 9) no release after a disc */
5937                                                         add_p(tplci, LLI, "\x01\x01");
5938                                                 }
5939                                                 add_p(tplci, CAI, voice_cai);
5940                                                 add_p(tplci, OAD, a->TelOAD);
5941                                                 add_p(tplci, OSA, a->TelOSA);
5942                                                 add_p(tplci, SHIFT | 6, NULL);
5943                                                 add_p(tplci, SIN, "\x02\x01\x00");
5944                                                 add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5945                                                 sig_req(tplci, ASSIGN, DSIG_ID);
5946                                                 a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5947                                                 a->AdvSignalPLCI->command = 0;
5948                                                 tplci->appl = a->AdvSignalAppl;
5949                                                 tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5950                                                 send_req(tplci);
5951                                         }
5952
5953                                 }
5954
5955                                 if (!tplci) break;
5956                                 Id = ((word)tplci->Id << 8) | a->Id;
5957                                 Id |= EXT_CONTROLLER;
5958                                 sendf(tplci->appl,
5959                                       _FACILITY_I,
5960                                       Id,
5961                                       0,
5962                                       "ws", (word)0, "\x01+");
5963                                 break;
5964
5965                         case 0x90:   /* hook on  */
5966                         case 0x91:
5967                                 if (plci->internal_command == PERM_COD_HOOK)
5968                                 {
5969                                         dbug(1, dprintf("init:hook_on"));
5970                                         plci->hook_state = ie[1] & 0x91;
5971                                         next_internal_command(Id, plci);
5972                                         break;
5973                                 }
5974                                 else /* ignore doubled hook indications */
5975                                 {
5976                                         if (((plci->hook_state) & 0xf0) == 0x90) break;
5977                                         plci->hook_state = ie[1] & 0x91;
5978                                 }
5979                                 /* hangup the adv. voice call and signal '-' to the appl */
5980                                 if (a->AdvSignalPLCI) {
5981                                         Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5982                                         if (plci->tel) Id |= EXT_CONTROLLER;
5983                                         sendf(a->AdvSignalAppl,
5984                                               _FACILITY_I,
5985                                               Id,
5986                                               0,
5987                                               "ws", (word)0, "\x01-");
5988                                         a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5989                                         a->AdvSignalPLCI->command = 0;
5990                                         sig_req(a->AdvSignalPLCI, HANGUP, 0);
5991                                         send_req(a->AdvSignalPLCI);
5992                                 }
5993                                 break;
5994                         }
5995                 }
5996                 break;
5997
5998         case RESUME:
5999                 clear_c_ind_mask_bit(plci, (word)(plci->appl->Id - 1));
6000                 PUT_WORD(&resume_cau[4], GOOD);
6001                 sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6002                 break;
6003
6004         case SUSPEND:
6005                 clear_c_ind_mask(plci);
6006
6007                 if (plci->NL.Id && !plci->nl_remove_id) {
6008                         mixer_remove(plci);
6009                         nl_req_ncci(plci, REMOVE, 0);
6010                 }
6011                 if (!plci->sig_remove_id) {
6012                         plci->internal_command = 0;
6013                         sig_req(plci, REMOVE, 0);
6014                 }
6015                 send_req(plci);
6016                 if (!plci->channels) {
6017                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6018                         sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6019                 }
6020                 break;
6021
6022         case SUSPEND_REJ:
6023                 break;
6024
6025         case HANGUP:
6026                 plci->hangup_flow_ctrl_timer = 0;
6027                 if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
6028                 cau = parms[7];
6029                 if (cau) {
6030                         i = _L3_CAUSE | cau[2];
6031                         if (cau[2] == 0) i = 0;
6032                         else if (cau[2] == 8) i = _L1_ERROR;
6033                         else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
6034                         else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
6035                 }
6036                 else {
6037                         i = _L3_ERROR;
6038                 }
6039
6040                 if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
6041                 {
6042                         for (i = 0; i < max_appl; i++)
6043                         {
6044                                 if (test_c_ind_mask_bit(plci, i))
6045                                         sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6046                         }
6047                 }
6048                 else
6049                 {
6050                         clear_c_ind_mask(plci);
6051                 }
6052                 if (!plci->appl)
6053                 {
6054                         if (plci->State == LISTENING)
6055                         {
6056                                 plci->notifiedcall = 0;
6057                                 a->listen_active--;
6058                         }
6059                         plci->State = INC_DIS_PENDING;
6060                         if (c_ind_mask_empty(plci))
6061                         {
6062                                 plci->State = IDLE;
6063                                 if (plci->NL.Id && !plci->nl_remove_id)
6064                                 {
6065                                         mixer_remove(plci);
6066                                         nl_req_ncci(plci, REMOVE, 0);
6067                                 }
6068                                 if (!plci->sig_remove_id)
6069                                 {
6070                                         plci->internal_command = 0;
6071                                         sig_req(plci, REMOVE, 0);
6072                                 }
6073                                 send_req(plci);
6074                         }
6075                 }
6076                 else
6077                 {
6078                         /* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
6079                         /* result in a second HANGUP! Don't generate another        */
6080                         /* DISCONNECT                                               */
6081                         if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
6082                         {
6083                                 if (plci->State == RESUMING)
6084                                 {
6085                                         PUT_WORD(&resume_cau[4], i);
6086                                         sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6087                                 }
6088                                 plci->State = INC_DIS_PENDING;
6089                                 sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
6090                         }
6091                 }
6092                 break;
6093
6094         case SSEXT_IND:
6095                 SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
6096                 break;
6097
6098         case VSWITCH_REQ:
6099                 VSwitchReqInd(plci, Id, multi_vswitch_parms);
6100                 break;
6101         case VSWITCH_IND:
6102                 if (plci->relatedPTYPLCI &&
6103                     plci->vswitchstate == 3 &&
6104                     plci->relatedPTYPLCI->vswitchstate == 3 &&
6105                     parms[MAXPARMSIDS - 1][0])
6106                 {
6107                         add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
6108                         sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
6109                         send_req(plci->relatedPTYPLCI);
6110                 }
6111                 else VSwitchReqInd(plci, Id, multi_vswitch_parms);
6112                 break;
6113
6114         }
6115 }
6116
6117
6118 static void SendSetupInfo(APPL *appl, PLCI *plci, dword Id, byte **parms, byte Info_Sent_Flag)
6119 {
6120         word i;
6121         byte *ie;
6122         word Info_Number;
6123         byte *Info_Element;
6124         word Info_Mask = 0;
6125
6126         dbug(1, dprintf("SetupInfo"));
6127
6128         for (i = 0; i < MAXPARMSIDS; i++) {
6129                 ie = parms[i];
6130                 Info_Number = 0;
6131                 Info_Element = ie;
6132                 if (ie[0]) {
6133                         switch (i) {
6134                         case 0:
6135                                 dbug(1, dprintf("CPN "));
6136                                 Info_Number = 0x0070;
6137                                 Info_Mask = 0x80;
6138                                 Info_Sent_Flag = true;
6139                                 break;
6140                         case 8:  /* display      */
6141                                 dbug(1, dprintf("display(%d)", i));
6142                                 Info_Number = 0x0028;
6143                                 Info_Mask = 0x04;
6144                                 Info_Sent_Flag = true;
6145                                 break;
6146                         case 16: /* Channel Id */
6147                                 dbug(1, dprintf("CHI"));
6148                                 Info_Number = 0x0018;
6149                                 Info_Mask = 0x100;
6150                                 Info_Sent_Flag = true;
6151                                 mixer_set_bchannel_id(plci, Info_Element);
6152                                 break;
6153                         case 19: /* Redirected Number */
6154                                 dbug(1, dprintf("RDN"));
6155                                 Info_Number = 0x0074;
6156                                 Info_Mask = 0x400;
6157                                 Info_Sent_Flag = true;
6158                                 break;
6159                         case 20: /* Redirected Number extended */
6160                                 dbug(1, dprintf("RDX"));
6161                                 Info_Number = 0x0073;
6162                                 Info_Mask = 0x400;
6163                                 Info_Sent_Flag = true;
6164                                 break;
6165                         case 22: /* Redirecing Number  */
6166                                 dbug(1, dprintf("RIN"));
6167                                 Info_Number = 0x0076;
6168                                 Info_Mask = 0x400;
6169                                 Info_Sent_Flag = true;
6170                                 break;
6171                         default:
6172                                 Info_Number = 0;
6173                                 break;
6174                         }
6175                 }
6176
6177                 if (i == MAXPARMSIDS - 2) { /* to indicate the message type "Setup" */
6178                         Info_Number = 0x8000 | 5;
6179                         Info_Mask = 0x10;
6180                         Info_Element = "";
6181                 }
6182
6183                 if (Info_Sent_Flag && Info_Number) {
6184                         if (plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask) {
6185                                 sendf(appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6186                         }
6187                 }
6188         }
6189 }
6190
6191
6192 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6193 {
6194         word i;
6195         word j;
6196         word k;
6197         byte *ie;
6198         word Info_Number;
6199         byte *Info_Element;
6200         word Info_Mask = 0;
6201         static byte charges[5] = {4, 0, 0, 0, 0};
6202         static byte cause[] = {0x02, 0x80, 0x00};
6203         APPL *appl;
6204
6205         dbug(1, dprintf("InfoParse "));
6206
6207         if (
6208                 !plci->appl
6209                 && !plci->State
6210                 && plci->Sig.Ind != NCR_FACILITY
6211                 )
6212         {
6213                 dbug(1, dprintf("NoParse "));
6214                 return;
6215         }
6216         cause[2] = 0;
6217         for (i = 0; i < MAXPARMSIDS; i++) {
6218                 ie = parms[i];
6219                 Info_Number = 0;
6220                 Info_Element = ie;
6221                 if (ie[0]) {
6222                         switch (i) {
6223                         case 0:
6224                                 dbug(1, dprintf("CPN "));
6225                                 Info_Number = 0x0070;
6226                                 Info_Mask   = 0x80;
6227                                 break;
6228                         case 7: /* ESC_CAU */
6229                                 dbug(1, dprintf("cau(0x%x)", ie[2]));
6230                                 Info_Number = 0x0008;
6231                                 Info_Mask = 0x00;
6232                                 cause[2] = ie[2];
6233                                 Info_Element = NULL;
6234                                 break;
6235                         case 8:  /* display      */
6236                                 dbug(1, dprintf("display(%d)", i));
6237                                 Info_Number = 0x0028;
6238                                 Info_Mask = 0x04;
6239                                 break;
6240                         case 9:  /* Date display */
6241                                 dbug(1, dprintf("date(%d)", i));
6242                                 Info_Number = 0x0029;
6243                                 Info_Mask = 0x02;
6244                                 break;
6245                         case 10: /* charges */
6246                                 for (j = 0; j < 4; j++) charges[1 + j] = 0;
6247                                 for (j = 0; j < ie[0] && !(ie[1 + j] & 0x80); j++);
6248                                 for (k = 1, j++; j < ie[0] && k <= 4; j++, k++) charges[k] = ie[1 + j];
6249                                 Info_Number = 0x4000;
6250                                 Info_Mask = 0x40;
6251                                 Info_Element = charges;
6252                                 break;
6253                         case 11: /* user user info */
6254                                 dbug(1, dprintf("uui"));
6255                                 Info_Number = 0x007E;
6256                                 Info_Mask = 0x08;
6257                                 break;
6258                         case 12: /* congestion receiver ready */
6259                                 dbug(1, dprintf("clRDY"));
6260                                 Info_Number = 0x00B0;
6261                                 Info_Mask = 0x08;
6262                                 Info_Element = "";
6263                                 break;
6264                         case 13: /* congestion receiver not ready */
6265                                 dbug(1, dprintf("clNRDY"));
6266                                 Info_Number = 0x00BF;
6267                                 Info_Mask = 0x08;
6268                                 Info_Element = "";
6269                                 break;
6270                         case 15: /* Keypad Facility */
6271                                 dbug(1, dprintf("KEY"));
6272                                 Info_Number = 0x002C;
6273                                 Info_Mask = 0x20;
6274                                 break;
6275                         case 16: /* Channel Id */
6276                                 dbug(1, dprintf("CHI"));
6277                                 Info_Number = 0x0018;
6278                                 Info_Mask = 0x100;
6279                                 mixer_set_bchannel_id(plci, Info_Element);
6280                                 break;
6281                         case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6282                                 dbug(1, dprintf("q9cau(0x%x)", ie[2]));
6283                                 if (!cause[2] || cause[2] < 0x80) break;  /* eg. layer 1 error */
6284                                 Info_Number = 0x0008;
6285                                 Info_Mask = 0x01;
6286                                 if (cause[2] != ie[2]) Info_Element = cause;
6287                                 break;
6288                         case 19: /* Redirected Number */
6289                                 dbug(1, dprintf("RDN"));
6290                                 Info_Number = 0x0074;
6291                                 Info_Mask = 0x400;
6292                                 break;
6293                         case 22: /* Redirecing Number  */
6294                                 dbug(1, dprintf("RIN"));
6295                                 Info_Number = 0x0076;
6296                                 Info_Mask = 0x400;
6297                                 break;
6298                         case 23: /* Notification Indicator  */
6299                                 dbug(1, dprintf("NI"));
6300                                 Info_Number = (word)NI;
6301                                 Info_Mask = 0x210;
6302                                 break;
6303                         case 26: /* Call State  */
6304                                 dbug(1, dprintf("CST"));
6305                                 Info_Number = (word)CST;
6306                                 Info_Mask = 0x01; /* do with cause i.e. for now */
6307                                 break;
6308                         case MAXPARMSIDS - 2:  /* Escape Message Type, must be the last indication */
6309                                 dbug(1, dprintf("ESC/MT[0x%x]", ie[3]));
6310                                 Info_Number = 0x8000 | ie[3];
6311                                 if (iesent) Info_Mask = 0xffff;
6312                                 else  Info_Mask = 0x10;
6313                                 Info_Element = "";
6314                                 break;
6315                         default:
6316                                 Info_Number  = 0;
6317                                 Info_Mask    = 0;
6318                                 Info_Element = "";
6319                                 break;
6320                         }
6321                 }
6322
6323                 if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6324                 {
6325                         for (j = 0; j < max_appl; j++)
6326                         {
6327                                 appl = &application[j];
6328                                 if (Info_Number
6329                                     && appl->Id
6330                                     && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6331                                 {
6332                                         dbug(1, dprintf("NCR_Ind"));
6333                                         iesent = true;
6334                                         sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6335                                 }
6336                         }
6337                 }
6338                 else if (!plci->appl)
6339                 { /* overlap receiving broadcast */
6340                         if (Info_Number == CPN
6341                             || Info_Number == KEY
6342                             || Info_Number == NI
6343                             || Info_Number == DSP
6344                             || Info_Number == UUI)
6345                         {
6346                                 for (j = 0; j < max_appl; j++)
6347                                 {
6348                                         if (test_c_ind_mask_bit(plci, j))
6349                                         {
6350                                                 dbug(1, dprintf("Ovl_Ind"));
6351                                                 iesent = true;
6352                                                 sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6353                                         }
6354                                 }
6355                         }
6356                 }               /* all other signalling states */
6357                 else if (Info_Number
6358                          && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6359                 {
6360                         dbug(1, dprintf("Std_Ind"));
6361                         iesent = true;
6362                         sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6363                 }
6364         }
6365 }
6366
6367
6368 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6369                         dword info_mask, byte setupParse)
6370 {
6371         word i;
6372         word j;
6373         byte *ie;
6374         word Info_Number;
6375         byte *Info_Element;
6376         APPL *appl;
6377         word Info_Mask = 0;
6378         byte iesent = 0;
6379
6380         if (
6381                 !plci->appl
6382                 && !plci->State
6383                 && plci->Sig.Ind != NCR_FACILITY
6384                 && !setupParse
6385                 )
6386         {
6387                 dbug(1, dprintf("NoM-IEParse "));
6388                 return 0;
6389         }
6390         dbug(1, dprintf("M-IEParse "));
6391
6392         for (i = 0; i < MAX_MULTI_IE; i++)
6393         {
6394                 ie = parms[i];
6395                 Info_Number = 0;
6396                 Info_Element = ie;
6397                 if (ie[0])
6398                 {
6399                         dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci->Sig.Ind, ie_type));
6400                         Info_Number = (word)ie_type;
6401                         Info_Mask = (word)info_mask;
6402                 }
6403
6404                 if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6405                 {
6406                         for (j = 0; j < max_appl; j++)
6407                         {
6408                                 appl = &application[j];
6409                                 if (Info_Number
6410                                     && appl->Id
6411                                     && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6412                                 {
6413                                         iesent = true;
6414                                         dbug(1, dprintf("Mlt_NCR_Ind"));
6415                                         sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6416                                 }
6417                         }
6418                 }
6419                 else if (!plci->appl && Info_Number)
6420                 {                                        /* overlap receiving broadcast */
6421                         for (j = 0; j < max_appl; j++)
6422                         {
6423                                 if (test_c_ind_mask_bit(plci, j))
6424                                 {
6425                                         iesent = true;
6426                                         dbug(1, dprintf("Mlt_Ovl_Ind"));
6427                                         sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6428                                 }
6429                         }
6430                 }                                        /* all other signalling states */
6431                 else if (Info_Number
6432                          && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6433                 {
6434                         iesent = true;
6435                         dbug(1, dprintf("Mlt_Std_Ind"));
6436                         sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6437                 }
6438         }
6439         return iesent;
6440 }
6441
6442 static void SendSSExtInd(APPL *appl, PLCI *plci, dword Id, byte **parms)
6443 {
6444         word i;
6445         /* Format of multi_ssext_parms[i][]:
6446            0 byte length
6447            1 byte SSEXTIE
6448            2 byte SSEXT_REQ/SSEXT_IND
6449            3 byte length
6450            4 word SSExtCommand
6451            6... Params
6452         */
6453         if (
6454                 plci
6455                 && plci->State
6456                 && plci->Sig.Ind != NCR_FACILITY
6457                 )
6458                 for (i = 0; i < MAX_MULTI_IE; i++)
6459                 {
6460                         if (parms[i][0] < 6) continue;
6461                         if (parms[i][2] == SSEXT_REQ) continue;
6462
6463                         if (appl)
6464                         {
6465                                 parms[i][0] = 0; /* kill it */
6466                                 sendf(appl, _MANUFACTURER_I,
6467                                       Id,
6468                                       0,
6469                                       "dwS",
6470                                       _DI_MANU_ID,
6471                                       _DI_SSEXT_CTRL,
6472                                       &parms[i][3]);
6473                         }
6474                         else if (plci->appl)
6475                         {
6476                                 parms[i][0] = 0; /* kill it */
6477                                 sendf(plci->appl, _MANUFACTURER_I,
6478                                       Id,
6479                                       0,
6480                                       "dwS",
6481                                       _DI_MANU_ID,
6482                                       _DI_SSEXT_CTRL,
6483                                       &parms[i][3]);
6484                         }
6485                 }
6486 };
6487
6488 static void nl_ind(PLCI *plci)
6489 {
6490         byte ch;
6491         word ncci;
6492         dword Id;
6493         DIVA_CAPI_ADAPTER *a;
6494         word NCCIcode;
6495         APPL *APPLptr;
6496         word count;
6497         word Num;
6498         word i, ncpi_state;
6499         byte len, ncci_state;
6500         word msg;
6501         word info = 0;
6502         word fax_feature_bits;
6503         byte fax_send_edata_ack;
6504         static byte v120_header_buffer[2 + 3];
6505         static word fax_info[] = {
6506                 0,                     /* T30_SUCCESS                        */
6507                 _FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
6508                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
6509                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
6510                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
6511                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
6512                 _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
6513                 _FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
6514                 _FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
6515                 _FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
6516                 _FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
6517                 _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
6518                 _FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
6519                 _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
6520                 _FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
6521                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
6522                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
6523                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
6524                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
6525                 _FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
6526                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
6527                 _FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
6528                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
6529                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
6530                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
6531                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
6532                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
6533                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
6534                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
6535                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
6536                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
6537                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
6538                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
6539                 0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
6540                 0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
6541                 0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
6542                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
6543                 _FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
6544                 _FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
6545                 _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
6546                 _FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
6547                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6548                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
6549                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
6550                 _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
6551                 _FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
6552                 _FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
6553         };
6554
6555         byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6556
6557
6558         static word rtp_info[] = {
6559                 GOOD,                  /* RTP_SUCCESS                       */
6560                 0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
6561         };
6562
6563         static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6564                 {
6565                         0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6566                         0x00000000, 0x00000000, 0x00000000, 0x00000000
6567                 };
6568
6569         ch = plci->NL.IndCh;
6570         a = plci->adapter;
6571         ncci = a->ch_ncci[ch];
6572         Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6573         if (plci->tel) Id |= EXT_CONTROLLER;
6574         APPLptr = plci->appl;
6575         dbug(1, dprintf("NL_IND-Id(NL:0x%x)=0x%08lx,plci=%x,tel=%x,state=0x%x,ch=0x%x,chs=%d,Ind=%x",
6576                         plci->NL.Id, Id, plci->Id, plci->tel, plci->State, ch, plci->channels, plci->NL.Ind & 0x0f));
6577
6578         /* in the case if no connect_active_Ind was sent to the appl we wait for */
6579
6580         if (plci->nl_remove_id)
6581         {
6582                 plci->NL.RNR = 2; /* discard */
6583                 dbug(1, dprintf("NL discard while remove pending"));
6584                 return;
6585         }
6586         if ((plci->NL.Ind & 0x0f) == N_CONNECT)
6587         {
6588                 if (plci->State == INC_DIS_PENDING
6589                     || plci->State == OUTG_DIS_PENDING
6590                     || plci->State == IDLE)
6591                 {
6592                         plci->NL.RNR = 2; /* discard */
6593                         dbug(1, dprintf("discard n_connect"));
6594                         return;
6595                 }
6596                 if (plci->State < INC_ACT_PENDING)
6597                 {
6598                         plci->NL.RNR = 1; /* flow control */
6599                         channel_x_off(plci, ch, N_XON_CONNECT_IND);
6600                         return;
6601                 }
6602         }
6603
6604         if (!APPLptr)                         /* no application or invalid data */
6605         {                                    /* while reloading the DSP        */
6606                 dbug(1, dprintf("discard1"));
6607                 plci->NL.RNR = 2;
6608                 return;
6609         }
6610
6611         if (((plci->NL.Ind & 0x0f) == N_UDATA)
6612             && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6613                 || (plci->B2_prot == 7)
6614                 || (plci->B3_prot == 7)))
6615         {
6616                 plci->ncpi_buffer[0] = 0;
6617
6618                 ncpi_state = plci->ncpi_state;
6619                 if (plci->NL.complete == 1)
6620                 {
6621                         byte *data = &plci->NL.RBuffer->P[0];
6622
6623                         if ((plci->NL.RBuffer->length >= 12)
6624                             && ((*data == DSP_UDATA_INDICATION_DCD_ON)
6625                                 || (*data == DSP_UDATA_INDICATION_CTS_ON)))
6626                         {
6627                                 word conn_opt, ncpi_opt = 0x00;
6628 /*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6629
6630                                 if (*data == DSP_UDATA_INDICATION_DCD_ON)
6631                                         plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6632                                 if (*data == DSP_UDATA_INDICATION_CTS_ON)
6633                                         plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6634
6635                                 data++;    /* indication code */
6636                                 data += 2; /* timestamp */
6637                                 if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6638                                         ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6639                                 data++;    /* connected norm */
6640                                 conn_opt = GET_WORD(data);
6641                                 data += 2; /* connected options */
6642
6643                                 PUT_WORD(&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6644
6645                                 if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6646                                 {
6647                                         ncpi_opt |= MDM_NCPI_ECM_V42;
6648                                 }
6649                                 else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6650                                 {
6651                                         ncpi_opt |= MDM_NCPI_ECM_MNP;
6652                                 }
6653                                 else
6654                                 {
6655                                         ncpi_opt |= MDM_NCPI_TRANSPARENT;
6656                                 }
6657                                 if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6658                                 {
6659                                         ncpi_opt |= MDM_NCPI_COMPRESSED;
6660                                 }
6661                                 PUT_WORD(&(plci->ncpi_buffer[3]), ncpi_opt);
6662                                 plci->ncpi_buffer[0] = 4;
6663
6664                                 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6665                         }
6666                 }
6667                 if (plci->B3_prot == 7)
6668                 {
6669                         if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6670                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6671                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6672                         {
6673                                 a->ncci_state[ncci] = INC_ACT_PENDING;
6674                                 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6675                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6676                         }
6677                 }
6678
6679                 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
6680                       & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6681                     || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6682                     || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6683
6684                 {
6685                         plci->NL.RNR = 2;
6686                         return;
6687                 }
6688         }
6689
6690         if (plci->NL.complete == 2)
6691         {
6692                 if (((plci->NL.Ind & 0x0f) == N_UDATA)
6693                     && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6694                 {
6695                         switch (plci->RData[0].P[0])
6696                         {
6697
6698                         case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6699                                 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6700                                         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01X");
6701                                 break;
6702                         case DTMF_UDATA_INDICATION_ANSWER_TONE:
6703                                 if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6704                                         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01Y");
6705                                 break;
6706                         case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6707                                 dtmf_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6708                                 break;
6709                         case DTMF_UDATA_INDICATION_DIGITS_SENT:
6710                                 dtmf_confirmation(Id, plci);
6711                                 break;
6712
6713
6714                         case UDATA_INDICATION_MIXER_TAP_DATA:
6715                                 capidtmf_recv_process_block(&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6716                                 i = capidtmf_indication(&(plci->capidtmf_state), dtmf_code_buffer + 1);
6717                                 if (i != 0)
6718                                 {
6719                                         dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6720                                         dtmf_indication(Id, plci, dtmf_code_buffer, (word)(i + 1));
6721                                 }
6722                                 break;
6723
6724
6725                         case UDATA_INDICATION_MIXER_COEFS_SET:
6726                                 mixer_indication_coefs_set(Id, plci);
6727                                 break;
6728                         case UDATA_INDICATION_XCONNECT_FROM:
6729                                 mixer_indication_xconnect_from(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6730                                 break;
6731                         case UDATA_INDICATION_XCONNECT_TO:
6732                                 mixer_indication_xconnect_to(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6733                                 break;
6734
6735
6736                         case LEC_UDATA_INDICATION_DISABLE_DETECT:
6737                                 ec_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6738                                 break;
6739
6740
6741
6742                         default:
6743                                 break;
6744                         }
6745                 }
6746                 else
6747                 {
6748                         if ((plci->RData[0].PLength != 0)
6749                             && ((plci->B2_prot == B2_V120_ASYNC)
6750                                 || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6751                                 || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6752                         {
6753
6754                                 sendf(plci->appl, _DATA_B3_I, Id, 0,
6755                                       "dwww",
6756                                       plci->RData[1].P,
6757                                       (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6758                                       plci->RNum,
6759                                       plci->RFlags);
6760
6761                         }
6762                         else
6763                         {
6764
6765                                 sendf(plci->appl, _DATA_B3_I, Id, 0,
6766                                       "dwww",
6767                                       plci->RData[0].P,
6768                                       plci->RData[0].PLength,
6769                                       plci->RNum,
6770                                       plci->RFlags);
6771
6772                         }
6773                 }
6774                 return;
6775         }
6776
6777         fax_feature_bits = 0;
6778         if ((plci->NL.Ind & 0x0f) == N_CONNECT ||
6779             (plci->NL.Ind & 0x0f) == N_CONNECT_ACK ||
6780             (plci->NL.Ind & 0x0f) == N_DISC ||
6781             (plci->NL.Ind & 0x0f) == N_EDATA ||
6782             (plci->NL.Ind & 0x0f) == N_DISC_ACK)
6783         {
6784                 info = 0;
6785                 plci->ncpi_buffer[0] = 0;
6786                 switch (plci->B3_prot) {
6787                 case  0: /*XPARENT*/
6788                 case  1: /*T.90 NL*/
6789                         break;    /* no network control protocol info - jfr */
6790                 case  2: /*ISO8202*/
6791                 case  3: /*X25 DCE*/
6792                         for (i = 0; i < plci->NL.RLength; i++) plci->ncpi_buffer[4 + i] = plci->NL.RBuffer->P[i];
6793                         plci->ncpi_buffer[0] = (byte)(i + 3);
6794                         plci->ncpi_buffer[1] = (byte)(plci->NL.Ind & N_D_BIT ? 1 : 0);
6795                         plci->ncpi_buffer[2] = 0;
6796                         plci->ncpi_buffer[3] = 0;
6797                         break;
6798                 case  4: /*T.30 - FAX*/
6799                 case  5: /*T.30 - FAX*/
6800                         if (plci->NL.RLength >= sizeof(T30_INFO))
6801                         {
6802                                 dbug(1, dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6803                                 len = 9;
6804                                 PUT_WORD(&(plci->ncpi_buffer[1]), ((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6805                                 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6806                                 i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6807                                 if (plci->B3_prot == 5)
6808                                 {
6809                                         if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6810                                                 i |= 0x8000; /* This is not an ECM connection */
6811                                         if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6812                                                 i |= 0x4000; /* This is a connection with MMR compression */
6813                                         if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6814                                                 i |= 0x2000; /* This is a connection with MR compression */
6815                                         if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6816                                                 i |= 0x0004; /* More documents */
6817                                         if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6818                                                 i |= 0x0002; /* Fax-polling indication */
6819                                 }
6820                                 dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits, i));
6821                                 PUT_WORD(&(plci->ncpi_buffer[3]), i);
6822                                 PUT_WORD(&(plci->ncpi_buffer[5]), ((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6823                                 plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6824                                 plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6825                                 plci->ncpi_buffer[len] = 0;
6826                                 if (((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6827                                 {
6828                                         plci->ncpi_buffer[len] = 20;
6829                                         for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6830                                                 plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6831                                 }
6832                                 if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6833                                 {
6834                                         if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6835                                                 info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6836                                         else
6837                                                 info = _FAX_PROTOCOL_ERROR;
6838                                 }
6839
6840                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6841                                     & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6842                                 {
6843                                         i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6844                                         while (i < plci->NL.RBuffer->length)
6845                                                 plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6846                                 }
6847
6848                                 plci->ncpi_buffer[0] = len;
6849                                 fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6850                                 PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6851
6852                                 plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6853                                 if (((plci->NL.Ind & 0x0f) == N_CONNECT_ACK)
6854                                     || (((plci->NL.Ind & 0x0f) == N_CONNECT)
6855                                         && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6856                                     || (((plci->NL.Ind & 0x0f) == N_EDATA)
6857                                         && ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6858                                             || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6859                                             || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6860                                 {
6861                                         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6862                                 }
6863                                 if (((plci->NL.Ind & 0x0f) == N_DISC)
6864                                     || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)
6865                                     || (((plci->NL.Ind & 0x0f) == N_EDATA)
6866                                         && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6867                                 {
6868                                         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6869                                 }
6870                         }
6871                         break;
6872
6873                 case B3_RTP:
6874                         if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6875                         {
6876                                 if (plci->NL.RLength != 0)
6877                                 {
6878                                         info = rtp_info[plci->NL.RBuffer->P[0]];
6879                                         plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6880                                         for (i = 1; i < plci->NL.RLength; i++)
6881                                                 plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6882                                 }
6883                         }
6884                         break;
6885
6886                 }
6887                 plci->NL.RNR = 2;
6888         }
6889         switch (plci->NL.Ind & 0x0f) {
6890         case N_EDATA:
6891                 if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6892                 {
6893                         dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6894                                         ((T30_INFO *)plci->NL.RBuffer->P)->code));
6895                         fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6896
6897                         if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6898                             && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6899                             && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6900                             && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6901                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6902                             && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6903                         {
6904                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6905                                 sendf(plci->appl, _MANUFACTURER_I, Id, 0, "dwbS", _DI_MANU_ID, _DI_NEGOTIATE_B3,
6906                                       (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6907                                 plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6908                                 if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6909                                         fax_send_edata_ack = false;
6910                         }
6911
6912                         if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6913                         {
6914                                 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6915                                 {
6916                                 case EDATA_T30_DIS:
6917                                         if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6918                                             && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6919                                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6920                                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6921                                         {
6922                                                 a->ncci_state[ncci] = INC_ACT_PENDING;
6923                                                 if (plci->B3_prot == 4)
6924                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6925                                                 else
6926                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6927                                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6928                                         }
6929                                         break;
6930
6931                                 case EDATA_T30_TRAIN_OK:
6932                                         if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6933                                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6934                                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6935                                         {
6936                                                 if (plci->B3_prot == 4)
6937                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6938                                                 else
6939                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6940                                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6941                                         }
6942                                         break;
6943
6944                                 case EDATA_T30_EOP_CAPI:
6945                                         if (a->ncci_state[ncci] == CONNECTED)
6946                                         {
6947                                                 sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", GOOD, plci->ncpi_buffer);
6948                                                 a->ncci_state[ncci] = INC_DIS_PENDING;
6949                                                 plci->ncpi_state = 0;
6950                                                 fax_send_edata_ack = false;
6951                                         }
6952                                         break;
6953                                 }
6954                         }
6955                         else
6956                         {
6957                                 switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6958                                 {
6959                                 case EDATA_T30_TRAIN_OK:
6960                                         if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6961                                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6962                                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6963                                         {
6964                                                 if (plci->B3_prot == 4)
6965                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6966                                                 else
6967                                                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6968                                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6969                                         }
6970                                         break;
6971                                 }
6972                         }
6973                         if (fax_send_edata_ack)
6974                         {
6975                                 ((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6976                                 plci->fax_edata_ack_length = 1;
6977                                 start_internal_command(Id, plci, fax_edata_ack_command);
6978                         }
6979                 }
6980                 else
6981                 {
6982                         dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6983                 }
6984                 break;
6985         case N_CONNECT:
6986                 if (!a->ch_ncci[ch])
6987                 {
6988                         ncci = get_ncci(plci, ch, 0);
6989                         Id = (Id & 0xffff) | (((dword) ncci) << 16);
6990                 }
6991                 dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6992                                 ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6993
6994                 msg = _CONNECT_B3_I;
6995                 if (a->ncci_state[ncci] == IDLE)
6996                         plci->channels++;
6997                 else if (plci->B3_prot == 1)
6998                         msg = _CONNECT_B3_T90_ACTIVE_I;
6999
7000                 a->ncci_state[ncci] = INC_CON_PENDING;
7001                 if (plci->B3_prot == 4)
7002                         sendf(plci->appl, msg, Id, 0, "s", "");
7003                 else
7004                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7005                 break;
7006         case N_CONNECT_ACK:
7007                 dbug(1, dprintf("N_connect_Ack"));
7008                 if (plci->internal_command_queue[0]
7009                     && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
7010                         || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
7011                         || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
7012                 {
7013                         (*(plci->internal_command_queue[0]))(Id, plci, 0);
7014                         if (!plci->internal_command)
7015                                 next_internal_command(Id, plci);
7016                         break;
7017                 }
7018                 msg = _CONNECT_B3_ACTIVE_I;
7019                 if (plci->B3_prot == 1)
7020                 {
7021                         if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7022                                 msg = _CONNECT_B3_T90_ACTIVE_I;
7023                         a->ncci_state[ncci] = INC_ACT_PENDING;
7024                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7025                 }
7026                 else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7027                 {
7028                         if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7029                             && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7030                             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7031                         {
7032                                 a->ncci_state[ncci] = INC_ACT_PENDING;
7033                                 if (plci->B3_prot == 4)
7034                                         sendf(plci->appl, msg, Id, 0, "s", "");
7035                                 else
7036                                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7037                                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7038                         }
7039                 }
7040                 else
7041                 {
7042                         a->ncci_state[ncci] = INC_ACT_PENDING;
7043                         sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7044                 }
7045                 if (plci->adjust_b_restore)
7046                 {
7047                         plci->adjust_b_restore = false;
7048                         start_internal_command(Id, plci, adjust_b_restore);
7049                 }
7050                 break;
7051         case N_DISC:
7052         case N_DISC_ACK:
7053                 if (plci->internal_command_queue[0]
7054                     && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7055                         || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7056                         || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7057                 {
7058                         (*(plci->internal_command_queue[0]))(Id, plci, 0);
7059                         if (!plci->internal_command)
7060                                 next_internal_command(Id, plci);
7061                 }
7062                 ncci_state = a->ncci_state[ncci];
7063                 ncci_remove(plci, ncci, false);
7064
7065                 /* with N_DISC or N_DISC_ACK the IDI frees the respective   */
7066                 /* channel, so we cannot store the state in ncci_state! The */
7067                 /* information which channel we received a N_DISC is thus   */
7068                 /* stored in the inc_dis_ncci_table buffer.                 */
7069                 for (i = 0; plci->inc_dis_ncci_table[i]; i++);
7070                 plci->inc_dis_ncci_table[i] = (byte) ncci;
7071
7072                 /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7073                 if (!plci->channels
7074                     && (plci->B1_resource == 16)
7075                     && (plci->State <= CONNECTED))
7076                 {
7077                         len = 9;
7078                         i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7079                         PUT_WORD(&plci->ncpi_buffer[1], i);
7080                         PUT_WORD(&plci->ncpi_buffer[3], 0);
7081                         i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7082                         PUT_WORD(&plci->ncpi_buffer[5], i);
7083                         PUT_WORD(&plci->ncpi_buffer[7], 0);
7084                         plci->ncpi_buffer[len] = 0;
7085                         plci->ncpi_buffer[0] = len;
7086                         if (plci->B3_prot == 4)
7087                                 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "s", "");
7088                         else
7089                         {
7090
7091                                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
7092                                     & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7093                                 {
7094                                         plci->ncpi_buffer[++len] = 0;
7095                                         plci->ncpi_buffer[++len] = 0;
7096                                         plci->ncpi_buffer[++len] = 0;
7097                                         plci->ncpi_buffer[0] = len;
7098                                 }
7099
7100                                 sendf(plci->appl, _CONNECT_B3_I, Id, 0, "S", plci->ncpi_buffer);
7101                         }
7102                         sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7103                         plci->ncpi_state = 0;
7104                         sig_req(plci, HANGUP, 0);
7105                         send_req(plci);
7106                         plci->State = OUTG_DIS_PENDING;
7107                         /* disc here */
7108                 }
7109                 else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7110                          && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7111                          && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7112                 {
7113                         if (ncci_state == IDLE)
7114                         {
7115                                 if (plci->channels)
7116                                         plci->channels--;
7117                                 if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
7118                                         if (plci->State == SUSPENDING) {
7119                                                 sendf(plci->appl,
7120                                                       _FACILITY_I,
7121                                                       Id & 0xffffL,
7122                                                       0,
7123                                                       "ws", (word)3, "\x03\x04\x00\x00");
7124                                                 sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7125                                         }
7126                                         plci_remove(plci);
7127                                         plci->State = IDLE;
7128                                 }
7129                         }
7130                 }
7131                 else if (plci->channels)
7132                 {
7133                         sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7134                         plci->ncpi_state = 0;
7135                         if ((ncci_state == OUTG_REJ_PENDING)
7136                             && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7137                         {
7138                                 sig_req(plci, HANGUP, 0);
7139                                 send_req(plci);
7140                                 plci->State = OUTG_DIS_PENDING;
7141                         }
7142                 }
7143                 break;
7144         case N_RESET:
7145                 a->ncci_state[ncci] = INC_RES_PENDING;
7146                 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7147                 break;
7148         case N_RESET_ACK:
7149                 a->ncci_state[ncci] = CONNECTED;
7150                 sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7151                 break;
7152
7153         case N_UDATA:
7154                 if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7155                 {
7156                         plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7157                         plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7158                         plci->NL.R = plci->RData;
7159                         plci->NL.RNum = 1;
7160                         return;
7161                 }
7162         case N_BDATA:
7163         case N_DATA:
7164                 if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7165                     || (a->ncci_state[ncci] == IDLE)
7166                     || (a->ncci_state[ncci] == INC_DIS_PENDING))
7167                 {
7168                         plci->NL.RNR = 2;
7169                         break;
7170                 }
7171                 if ((a->ncci_state[ncci] != CONNECTED)
7172                     && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7173                     && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7174                 {
7175                         dbug(1, dprintf("flow control"));
7176                         plci->NL.RNR = 1; /* flow control  */
7177                         channel_x_off(plci, ch, 0);
7178                         break;
7179                 }
7180
7181                 NCCIcode = ncci | (((word)a->Id) << 8);
7182
7183                 /* count all buffers within the Application pool    */
7184                 /* belonging to the same NCCI. If this is below the */
7185                 /* number of buffers available per NCCI we accept   */
7186                 /* this packet, otherwise we reject it              */
7187                 count = 0;
7188                 Num = 0xffff;
7189                 for (i = 0; i < APPLptr->MaxBuffer; i++) {
7190                         if (NCCIcode == APPLptr->DataNCCI[i]) count++;
7191                         if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
7192                 }
7193
7194                 if (count >= APPLptr->MaxNCCIData || Num == 0xffff)
7195                 {
7196                         dbug(3, dprintf("Flow-Control"));
7197                         plci->NL.RNR = 1;
7198                         if (++(APPLptr->NCCIDataFlowCtrlTimer) >=
7199                             (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7200                         {
7201                                 plci->NL.RNR = 2;
7202                                 dbug(3, dprintf("DiscardData"));
7203                         } else {
7204                                 channel_x_off(plci, ch, 0);
7205                         }
7206                         break;
7207                 }
7208                 else
7209                 {
7210                         APPLptr->NCCIDataFlowCtrlTimer = 0;
7211                 }
7212
7213                 plci->RData[0].P = ReceiveBufferGet(APPLptr, Num);
7214                 if (!plci->RData[0].P) {
7215                         plci->NL.RNR = 1;
7216                         channel_x_off(plci, ch, 0);
7217                         break;
7218                 }
7219
7220                 APPLptr->DataNCCI[Num] = NCCIcode;
7221                 APPLptr->DataFlags[Num] = (plci->Id << 8) | (plci->NL.Ind >> 4);
7222                 dbug(3, dprintf("Buffer(%d), Max = %d", Num, APPLptr->MaxBuffer));
7223
7224                 plci->RNum = Num;
7225                 plci->RFlags = plci->NL.Ind >> 4;
7226                 plci->RData[0].PLength = APPLptr->MaxDataLength;
7227                 plci->NL.R = plci->RData;
7228                 if ((plci->NL.RLength != 0)
7229                     && ((plci->B2_prot == B2_V120_ASYNC)
7230                         || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7231                         || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7232                 {
7233                         plci->RData[1].P = plci->RData[0].P;
7234                         plci->RData[1].PLength = plci->RData[0].PLength;
7235                         plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7236                         if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7237                                 plci->RData[0].PLength = 1;
7238                         else
7239                                 plci->RData[0].PLength = 2;
7240                         if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7241                                 plci->RFlags |= 0x0010;
7242                         if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7243                                 plci->RFlags |= 0x8000;
7244                         plci->NL.RNum = 2;
7245                 }
7246                 else
7247                 {
7248                         if ((plci->NL.Ind & 0x0f) == N_UDATA)
7249                                 plci->RFlags |= 0x0010;
7250
7251                         else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7252                                 plci->RFlags |= 0x0001;
7253
7254                         plci->NL.RNum = 1;
7255                 }
7256                 break;
7257         case N_DATA_ACK:
7258                 data_ack(plci, ch);
7259                 break;
7260         default:
7261                 plci->NL.RNR = 2;
7262                 break;
7263         }
7264 }
7265
7266 /*------------------------------------------------------------------*/
7267 /* find a free PLCI */
7268 /*------------------------------------------------------------------*/
7269
7270 static word get_plci(DIVA_CAPI_ADAPTER *a)
7271 {
7272         word i, j;
7273         PLCI *plci;
7274
7275         dump_plcis(a);
7276         for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
7277         if (i == a->max_plci) {
7278                 dbug(1, dprintf("get_plci: out of PLCIs"));
7279                 return 0;
7280         }
7281         plci = &a->plci[i];
7282         plci->Id = (byte)(i + 1);
7283
7284         plci->Sig.Id = 0;
7285         plci->NL.Id = 0;
7286         plci->sig_req = 0;
7287         plci->nl_req = 0;
7288
7289         plci->appl = NULL;
7290         plci->relatedPTYPLCI = NULL;
7291         plci->State = IDLE;
7292         plci->SuppState = IDLE;
7293         plci->channels = 0;
7294         plci->tel = 0;
7295         plci->B1_resource = 0;
7296         plci->B2_prot = 0;
7297         plci->B3_prot = 0;
7298
7299         plci->command = 0;
7300         plci->m_command = 0;
7301         init_internal_command_queue(plci);
7302         plci->number = 0;
7303         plci->req_in_start = 0;
7304         plci->req_in = 0;
7305         plci->req_out = 0;
7306         plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7307         plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7308         plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7309
7310         plci->data_sent = false;
7311         plci->send_disc = 0;
7312         plci->sig_global_req = 0;
7313         plci->sig_remove_id = 0;
7314         plci->nl_global_req = 0;
7315         plci->nl_remove_id = 0;
7316         plci->adv_nl = 0;
7317         plci->manufacturer = false;
7318         plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7319         plci->spoofed_msg = 0;
7320         plci->ptyState = 0;
7321         plci->cr_enquiry = false;
7322         plci->hangup_flow_ctrl_timer = 0;
7323
7324         plci->ncci_ring_list = 0;
7325         for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
7326         clear_c_ind_mask(plci);
7327         set_group_ind_mask(plci);
7328         plci->fax_connect_info_length = 0;
7329         plci->nsf_control_bits = 0;
7330         plci->ncpi_state = 0x00;
7331         plci->ncpi_buffer[0] = 0;
7332
7333         plci->requested_options_conn = 0;
7334         plci->requested_options = 0;
7335         plci->notifiedcall = 0;
7336         plci->vswitchstate = 0;
7337         plci->vsprot = 0;
7338         plci->vsprotdialect = 0;
7339         init_b1_config(plci);
7340         dbug(1, dprintf("get_plci(%x)", plci->Id));
7341         return i + 1;
7342 }
7343
7344 /*------------------------------------------------------------------*/
7345 /* put a parameter in the parameter buffer                          */
7346 /*------------------------------------------------------------------*/
7347
7348 static void add_p(PLCI *plci, byte code, byte *p)
7349 {
7350         word p_length;
7351
7352         p_length = 0;
7353         if (p) p_length = p[0];
7354         add_ie(plci, code, p, p_length);
7355 }
7356
7357 /*------------------------------------------------------------------*/
7358 /* put a structure in the parameter buffer                          */
7359 /*------------------------------------------------------------------*/
7360 static void add_s(PLCI *plci, byte code, API_PARSE *p)
7361 {
7362         if (p) add_ie(plci, code, p->info, (word)p->length);
7363 }
7364
7365 /*------------------------------------------------------------------*/
7366 /* put multiple structures in the parameter buffer                  */
7367 /*------------------------------------------------------------------*/
7368 static void add_ss(PLCI *plci, byte code, API_PARSE *p)
7369 {
7370         byte i;
7371
7372         if (p) {
7373                 dbug(1, dprintf("add_ss(%x,len=%d)", code, p->length));
7374                 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7375                         dbug(1, dprintf("add_ss_ie(%x,len=%d)", p->info[i - 1], p->info[i]));
7376                         add_ie(plci, p->info[i - 1], (byte *)&(p->info[i]), (word)p->info[i]);
7377                 }
7378         }
7379 }
7380
7381 /*------------------------------------------------------------------*/
7382 /* return the channel number sent by the application in a esc_chi   */
7383 /*------------------------------------------------------------------*/
7384 static byte getChannel(API_PARSE *p)
7385 {
7386         byte i;
7387
7388         if (p) {
7389                 for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7390                         if (p->info[i] == 2) {
7391                                 if (p->info[i - 1] == ESC && p->info[i + 1] == CHI) return (p->info[i + 2]);
7392                         }
7393                 }
7394         }
7395         return 0;
7396 }
7397
7398
7399 /*------------------------------------------------------------------*/
7400 /* put an information element in the parameter buffer               */
7401 /*------------------------------------------------------------------*/
7402
7403 static void add_ie(PLCI *plci, byte code, byte *p, word p_length)
7404 {
7405         word i;
7406
7407         if (!(code & 0x80) && !p_length) return;
7408
7409         if (plci->req_in == plci->req_in_start) {
7410                 plci->req_in += 2;
7411         }
7412         else {
7413                 plci->req_in--;
7414         }
7415         plci->RBuffer[plci->req_in++] = code;
7416
7417         if (p) {
7418                 plci->RBuffer[plci->req_in++] = (byte)p_length;
7419                 for (i = 0; i < p_length; i++) plci->RBuffer[plci->req_in++] = p[1 + i];
7420         }
7421
7422         plci->RBuffer[plci->req_in++] = 0;
7423 }
7424
7425 /*------------------------------------------------------------------*/
7426 /* put a unstructured data into the buffer                          */
7427 /*------------------------------------------------------------------*/
7428
7429 static void add_d(PLCI *plci, word length, byte *p)
7430 {
7431         word i;
7432
7433         if (plci->req_in == plci->req_in_start) {
7434                 plci->req_in += 2;
7435         }
7436         else {
7437                 plci->req_in--;
7438         }
7439         for (i = 0; i < length; i++) plci->RBuffer[plci->req_in++] = p[i];
7440 }
7441
7442 /*------------------------------------------------------------------*/
7443 /* put parameters from the Additional Info parameter in the         */
7444 /* parameter buffer                                                 */
7445 /*------------------------------------------------------------------*/
7446
7447 static void add_ai(PLCI *plci, API_PARSE *ai)
7448 {
7449         word i;
7450         API_PARSE ai_parms[5];
7451
7452         for (i = 0; i < 5; i++) ai_parms[i].length = 0;
7453
7454         if (!ai->length)
7455                 return;
7456         if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7457                 return;
7458
7459         add_s(plci, KEY, &ai_parms[1]);
7460         add_s(plci, UUI, &ai_parms[2]);
7461         add_ss(plci, FTY, &ai_parms[3]);
7462 }
7463
7464 /*------------------------------------------------------------------*/
7465 /* put parameter for b1 protocol in the parameter buffer            */
7466 /*------------------------------------------------------------------*/
7467
7468 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7469                    word b1_facilities)
7470 {
7471         API_PARSE bp_parms[8];
7472         API_PARSE mdm_cfg[9];
7473         API_PARSE global_config[2];
7474         byte cai[256];
7475         byte resource[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7476         byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7477         word i;
7478
7479         API_PARSE mdm_cfg_v18[4];
7480         word j, n, w;
7481         dword d;
7482
7483
7484         for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7485         for (i = 0; i < 2; i++) global_config[i].length = 0;
7486
7487         dbug(1, dprintf("add_b1"));
7488         api_save_msg(bp, "s", &plci->B_protocol);
7489
7490         if (b_channel_info == 2) {
7491                 plci->B1_resource = 0;
7492                 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7493                 add_p(plci, CAI, "\x01\x00");
7494                 dbug(1, dprintf("Cai=1,0 (no resource)"));
7495                 return 0;
7496         }
7497
7498         if (plci->tel == CODEC_PERMANENT) return 0;
7499         else if (plci->tel == CODEC) {
7500                 plci->B1_resource = 1;
7501                 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7502                 add_p(plci, CAI, "\x01\x01");
7503                 dbug(1, dprintf("Cai=1,1 (Codec)"));
7504                 return 0;
7505         }
7506         else if (plci->tel == ADV_VOICE) {
7507                 plci->B1_resource = add_b1_facilities(plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7508                 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7509                 voice_cai[1] = plci->B1_resource;
7510                 PUT_WORD(&voice_cai[5], plci->appl->MaxDataLength);
7511                 add_p(plci, CAI, voice_cai);
7512                 dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai[1]));
7513                 return 0;
7514         }
7515         plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7516         if (plci->call_dir & CALL_DIR_OUT)
7517                 plci->call_dir |= CALL_DIR_ORIGINATE;
7518         else if (plci->call_dir & CALL_DIR_IN)
7519                 plci->call_dir |= CALL_DIR_ANSWER;
7520
7521         if (!bp->length) {
7522                 plci->B1_resource = 0x5;
7523                 adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7524                 add_p(plci, CAI, "\x01\x05");
7525                 return 0;
7526         }
7527
7528         dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7529         if (bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7530         if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7531         {
7532                 bp_parms[6].length = 0;
7533                 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7534                 {
7535                         dbug(1, dprintf("b-form.!"));
7536                         return _WRONG_MESSAGE_FORMAT;
7537                 }
7538         }
7539         else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7540         {
7541                 dbug(1, dprintf("b-form.!"));
7542                 return _WRONG_MESSAGE_FORMAT;
7543         }
7544
7545         if (bp_parms[6].length)
7546         {
7547                 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7548                 {
7549                         return _WRONG_MESSAGE_FORMAT;
7550                 }
7551                 switch (GET_WORD(global_config[0].info))
7552                 {
7553                 case 1:
7554                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7555                         break;
7556                 case 2:
7557                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7558                         break;
7559                 }
7560         }
7561         dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7562
7563
7564         if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7565             && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7566         {
7567                 plci->B1_resource = add_b1_facilities(plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7568                 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7569                 cai[1] = plci->B1_resource;
7570                 cai[2] = 0;
7571                 cai[3] = 0;
7572                 cai[4] = 0;
7573                 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7574                 for (i = 0; i < bp_parms[3].length; i++)
7575                         cai[7 + i] = bp_parms[3].info[1 + i];
7576                 cai[0] = 6 + bp_parms[3].length;
7577                 add_p(plci, CAI, cai);
7578                 return 0;
7579         }
7580
7581
7582         if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7583             && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7584         {
7585                 plci->B1_resource = add_b1_facilities(plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7586                 adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7587                 cai[1] = plci->B1_resource;
7588                 cai[2] = 0;
7589                 cai[3] = 0;
7590                 cai[4] = 0;
7591                 PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7592                 cai[0] = 6;
7593                 add_p(plci, CAI, cai);
7594                 return 0;
7595         }
7596
7597
7598         if ((GET_WORD(bp_parms[0].info) >= 32)
7599             || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7600                 && ((GET_WORD(bp_parms[0].info) != 3)
7601                     || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7602                     || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7603         {
7604                 return _B1_NOT_SUPPORTED;
7605         }
7606         plci->B1_resource = add_b1_facilities(plci, resource[GET_WORD(bp_parms[0].info)],
7607                                               (word)(b1_facilities & ~B1_FACILITY_VOICE));
7608         adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7609         cai[0] = 6;
7610         cai[1] = plci->B1_resource;
7611         for (i = 2; i < sizeof(cai); i++) cai[i] = 0;
7612
7613         if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7614             || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7615             || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7616         { /* B1 - modem */
7617                 for (i = 0; i < 7; i++) mdm_cfg[i].length = 0;
7618
7619                 if (bp_parms[3].length)
7620                 {
7621                         if (api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwww", mdm_cfg))
7622                         {
7623                                 return (_WRONG_MESSAGE_FORMAT);
7624                         }
7625
7626                         cai[2] = 0; /* Bit rate for adaptation */
7627
7628                         dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7629
7630                         PUT_WORD(&cai[13], 0);                          /* Min Tx speed */
7631                         PUT_WORD(&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7632                         PUT_WORD(&cai[17], 0);                          /* Min Rx speed */
7633                         PUT_WORD(&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7634
7635                         cai[3] = 0; /* Async framing parameters */
7636                         switch (GET_WORD(mdm_cfg[2].info))
7637                         {       /* Parity     */
7638                         case 1: /* odd parity */
7639                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7640                                 dbug(1, dprintf("MDM: odd parity"));
7641                                 break;
7642
7643                         case 2: /* even parity */
7644                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7645                                 dbug(1, dprintf("MDM: even parity"));
7646                                 break;
7647
7648                         default:
7649                                 dbug(1, dprintf("MDM: no parity"));
7650                                 break;
7651                         }
7652
7653                         switch (GET_WORD(mdm_cfg[3].info))
7654                         {       /* stop bits   */
7655                         case 1: /* 2 stop bits */
7656                                 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7657                                 dbug(1, dprintf("MDM: 2 stop bits"));
7658                                 break;
7659
7660                         default:
7661                                 dbug(1, dprintf("MDM: 1 stop bit"));
7662                                 break;
7663                         }
7664
7665                         switch (GET_WORD(mdm_cfg[1].info))
7666                         {     /* char length */
7667                         case 5:
7668                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7669                                 dbug(1, dprintf("MDM: 5 bits"));
7670                                 break;
7671
7672                         case 6:
7673                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7674                                 dbug(1, dprintf("MDM: 6 bits"));
7675                                 break;
7676
7677                         case 7:
7678                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7679                                 dbug(1, dprintf("MDM: 7 bits"));
7680                                 break;
7681
7682                         default:
7683                                 dbug(1, dprintf("MDM: 8 bits"));
7684                                 break;
7685                         }
7686
7687                         cai[7] = 0; /* Line taking options */
7688                         cai[8] = 0; /* Modulation negotiation options */
7689                         cai[9] = 0; /* Modulation options */
7690
7691                         if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7692                         {
7693                                 cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7694                                 dbug(1, dprintf("MDM: Reverse direction"));
7695                         }
7696
7697                         if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7698                         {
7699                                 cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7700                                 dbug(1, dprintf("MDM: Disable retrain"));
7701                         }
7702
7703                         if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7704                         {
7705                                 cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7706                                 dbug(1, dprintf("MDM: Disable ring tone"));
7707                         }
7708
7709                         if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7710                         {
7711                                 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7712                                 dbug(1, dprintf("MDM: 1800 guard tone"));
7713                         }
7714                         else if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_550)
7715                         {
7716                                 cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7717                                 dbug(1, dprintf("MDM: 550 guard tone"));
7718                         }
7719
7720                         if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7721                         {
7722                                 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7723                                 dbug(1, dprintf("MDM: V100"));
7724                         }
7725                         else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7726                         {
7727                                 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7728                                 dbug(1, dprintf("MDM: IN CLASS"));
7729                         }
7730                         else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7731                         {
7732                                 cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7733                                 dbug(1, dprintf("MDM: DISABLED"));
7734                         }
7735                         cai[0] = 20;
7736
7737                         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7738                             && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7739                         {
7740                                 plci->requested_options |= 1L << PRIVATE_V18;
7741                         }
7742                         if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7743                                 plci->requested_options |= 1L << PRIVATE_VOWN;
7744
7745                         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
7746                             & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7747                         {
7748                                 if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwws", mdm_cfg))
7749                                 {
7750                                         i = 27;
7751                                         if (mdm_cfg[6].length >= 4)
7752                                         {
7753                                                 d = GET_DWORD(&mdm_cfg[6].info[1]);
7754                                                 cai[7] |= (byte) d;          /* line taking options */
7755                                                 cai[9] |= (byte)(d >> 8);    /* modulation options */
7756                                                 cai[++i] = (byte)(d >> 16);  /* vown modulation options */
7757                                                 cai[++i] = (byte)(d >> 24);
7758                                                 if (mdm_cfg[6].length >= 8)
7759                                                 {
7760                                                         d = GET_DWORD(&mdm_cfg[6].info[5]);
7761                                                         cai[10] |= (byte) d;        /* disabled modulations mask */
7762                                                         cai[11] |= (byte)(d >> 8);
7763                                                         if (mdm_cfg[6].length >= 12)
7764                                                         {
7765                                                                 d = GET_DWORD(&mdm_cfg[6].info[9]);
7766                                                                 cai[12] = (byte) d;          /* enabled modulations mask */
7767                                                                 cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */
7768                                                                 cai[++i] = (byte)(d >> 16);
7769                                                                 cai[++i] = (byte)(d >> 24);
7770                                                                 cai[++i] = 0;
7771                                                                 if (mdm_cfg[6].length >= 14)
7772                                                                 {
7773                                                                         w = GET_WORD(&mdm_cfg[6].info[13]);
7774                                                                         if (w != 0)
7775                                                                                 PUT_WORD(&cai[13], w);  /* min tx speed */
7776                                                                         if (mdm_cfg[6].length >= 16)
7777                                                                         {
7778                                                                                 w = GET_WORD(&mdm_cfg[6].info[15]);
7779                                                                                 if (w != 0)
7780                                                                                         PUT_WORD(&cai[15], w);  /* max tx speed */
7781                                                                                 if (mdm_cfg[6].length >= 18)
7782                                                                                 {
7783                                                                                         w = GET_WORD(&mdm_cfg[6].info[17]);
7784                                                                                         if (w != 0)
7785                                                                                                 PUT_WORD(&cai[17], w);  /* min rx speed */
7786                                                                                         if (mdm_cfg[6].length >= 20)
7787                                                                                         {
7788                                                                                                 w = GET_WORD(&mdm_cfg[6].info[19]);
7789                                                                                                 if (w != 0)
7790                                                                                                         PUT_WORD(&cai[19], w);  /* max rx speed */
7791                                                                                                 if (mdm_cfg[6].length >= 22)
7792                                                                                                 {
7793                                                                                                         w = GET_WORD(&mdm_cfg[6].info[21]);
7794                                                                                                         cai[23] = (byte)(-((short) w));  /* transmit level */
7795                                                                                                         if (mdm_cfg[6].length >= 24)
7796                                                                                                         {
7797                                                                                                                 w = GET_WORD(&mdm_cfg[6].info[23]);
7798                                                                                                                 cai[22] |= (byte) w;        /* info options mask */
7799                                                                                                                 cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */
7800                                                                                                         }
7801                                                                                                 }
7802                                                                                         }
7803                                                                                 }
7804                                                                         }
7805                                                                 }
7806                                                         }
7807                                                 }
7808                                         }
7809                                         cai[27] = i - 27;
7810                                         i++;
7811                                         if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwwss", mdm_cfg))
7812                                         {
7813                                                 if (!api_parse(&mdm_cfg[7].info[1], (word)mdm_cfg[7].length, "sss", mdm_cfg_v18))
7814                                                 {
7815                                                         for (n = 0; n < 3; n++)
7816                                                         {
7817                                                                 cai[i] = (byte)(mdm_cfg_v18[n].length);
7818                                                                 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7819                                                                         cai[i + j] = mdm_cfg_v18[n].info[j];
7820                                                                 i += cai[i] + 1;
7821                                                         }
7822                                                 }
7823                                         }
7824                                         cai[0] = (byte)(i - 1);
7825                                 }
7826                         }
7827
7828                 }
7829         }
7830         if (GET_WORD(bp_parms[0].info) == 2 ||                         /* V.110 async */
7831             GET_WORD(bp_parms[0].info) == 3)                           /* V.110 sync */
7832         {
7833                 if (bp_parms[3].length) {
7834                         dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms[3].info[1])));
7835                         switch (GET_WORD(&bp_parms[3].info[1])) {                 /* Rate */
7836                         case 0:
7837                         case 56000:
7838                                 if (GET_WORD(bp_parms[0].info) == 3) {                  /* V.110 sync 56k */
7839                                         dbug(1, dprintf("56k sync HSCX"));
7840                                         cai[1] = 8;
7841                                         cai[2] = 0;
7842                                         cai[3] = 0;
7843                                 }
7844                                 else if (GET_WORD(bp_parms[0].info) == 2) {
7845                                         dbug(1, dprintf("56k async DSP"));
7846                                         cai[2] = 9;
7847                                 }
7848                                 break;
7849                         case 50:     cai[2] = 1;  break;
7850                         case 75:     cai[2] = 1;  break;
7851                         case 110:    cai[2] = 1;  break;
7852                         case 150:    cai[2] = 1;  break;
7853                         case 200:    cai[2] = 1;  break;
7854                         case 300:    cai[2] = 1;  break;
7855                         case 600:    cai[2] = 1;  break;
7856                         case 1200:   cai[2] = 2;  break;
7857                         case 2400:   cai[2] = 3;  break;
7858                         case 4800:   cai[2] = 4;  break;
7859                         case 7200:   cai[2] = 10; break;
7860                         case 9600:   cai[2] = 5;  break;
7861                         case 12000:  cai[2] = 13; break;
7862                         case 24000:  cai[2] = 0;  break;
7863                         case 14400:  cai[2] = 11; break;
7864                         case 19200:  cai[2] = 6;  break;
7865                         case 28800:  cai[2] = 12; break;
7866                         case 38400:  cai[2] = 7;  break;
7867                         case 48000:  cai[2] = 8;  break;
7868                         case 76:     cai[2] = 15; break;  /* 75/1200     */
7869                         case 1201:   cai[2] = 14; break;  /* 1200/75     */
7870                         case 56001:  cai[2] = 9;  break;  /* V.110 56000 */
7871
7872                         default:
7873                                 return _B1_PARM_NOT_SUPPORTED;
7874                         }
7875                         cai[3] = 0;
7876                         if (cai[1] == 13)                                        /* v.110 async */
7877                         {
7878                                 if (bp_parms[3].length >= 8)
7879                                 {
7880                                         switch (GET_WORD(&bp_parms[3].info[3]))
7881                                         {       /* char length */
7882                                         case 5:
7883                                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7884                                                 break;
7885                                         case 6:
7886                                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7887                                                 break;
7888                                         case 7:
7889                                                 cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7890                                                 break;
7891                                         }
7892                                         switch (GET_WORD(&bp_parms[3].info[5]))
7893                                         {       /* Parity     */
7894                                         case 1: /* odd parity */
7895                                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7896                                                 break;
7897                                         case 2: /* even parity */
7898                                                 cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7899                                                 break;
7900                                         }
7901                                         switch (GET_WORD(&bp_parms[3].info[7]))
7902                                         {       /* stop bits   */
7903                                         case 1: /* 2 stop bits */
7904                                                 cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7905                                                 break;
7906                                         }
7907                                 }
7908                         }
7909                 }
7910                 else if (cai[1] == 8 || GET_WORD(bp_parms[0].info) == 3) {
7911                         dbug(1, dprintf("V.110 default 56k sync"));
7912                         cai[1] = 8;
7913                         cai[2] = 0;
7914                         cai[3] = 0;
7915                 }
7916                 else {
7917                         dbug(1, dprintf("V.110 default 9600 async"));
7918                         cai[2] = 5;
7919                 }
7920         }
7921         PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7922         dbug(1, dprintf("CAI[%d]=%x,%x,%x,%x,%x,%x", cai[0], cai[1], cai[2], cai[3], cai[4], cai[5], cai[6]));
7923 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7924
7925         add_p(plci, CAI, cai);
7926         return 0;
7927 }
7928
7929 /*------------------------------------------------------------------*/
7930 /* put parameter for b2 and B3  protocol in the parameter buffer    */
7931 /*------------------------------------------------------------------*/
7932
7933 static word add_b23(PLCI *plci, API_PARSE *bp)
7934 {
7935         word i, fax_control_bits;
7936         byte pos, len;
7937         byte SAPI = 0x40;  /* default SAPI 16 for x.31 */
7938         API_PARSE bp_parms[8];
7939         API_PARSE *b1_config;
7940         API_PARSE *b2_config;
7941         API_PARSE b2_config_parms[8];
7942         API_PARSE *b3_config;
7943         API_PARSE b3_config_parms[6];
7944         API_PARSE global_config[2];
7945
7946         static byte llc[3] = {2,0,0};
7947         static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7948         static byte nlc[256];
7949         static byte lli[12] = {1,1};
7950
7951         const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7952         const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7953
7954         const byte llc3[] = {4,3,2,2,6,6,0};
7955         const byte header[] = {0,2,3,3,0,0,0};
7956
7957         for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7958         for (i = 0; i < 6; i++) b2_config_parms[i].length = 0;
7959         for (i = 0; i < 5; i++) b3_config_parms[i].length = 0;
7960
7961         lli[0] = 1;
7962         lli[1] = 1;
7963         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7964                 lli[1] |= 2;
7965         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7966                 lli[1] |= 4;
7967
7968         if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7969                 lli[1] |= 0x10;
7970                 if (plci->rx_dma_descriptor <= 0) {
7971                         plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
7972                         if (plci->rx_dma_descriptor >= 0)
7973                                 plci->rx_dma_descriptor++;
7974                 }
7975                 if (plci->rx_dma_descriptor > 0) {
7976                         lli[0] = 6;
7977                         lli[1] |= 0x40;
7978                         lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7979                         lli[3] = (byte)plci->rx_dma_magic;
7980                         lli[4] = (byte)(plci->rx_dma_magic >>  8);
7981                         lli[5] = (byte)(plci->rx_dma_magic >> 16);
7982                         lli[6] = (byte)(plci->rx_dma_magic >> 24);
7983                 }
7984         }
7985
7986         if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7987                 lli[1] |= 0x20;
7988         }
7989
7990         dbug(1, dprintf("add_b23"));
7991         api_save_msg(bp, "s", &plci->B_protocol);
7992
7993         if (!bp->length && plci->tel)
7994         {
7995                 plci->adv_nl = true;
7996                 dbug(1, dprintf("Default adv.Nl"));
7997                 add_p(plci, LLI, lli);
7998                 plci->B2_prot = 1 /*XPARENT*/;
7999                 plci->B3_prot = 0 /*XPARENT*/;
8000                 llc[1] = 2;
8001                 llc[2] = 4;
8002                 add_p(plci, LLC, llc);
8003                 dlc[0] = 2;
8004                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8005                 add_p(plci, DLC, dlc);
8006                 return 0;
8007         }
8008
8009         if (!bp->length) /*default*/
8010         {
8011                 dbug(1, dprintf("ret default"));
8012                 add_p(plci, LLI, lli);
8013                 plci->B2_prot = 0 /*X.75   */;
8014                 plci->B3_prot = 0 /*XPARENT*/;
8015                 llc[1] = 1;
8016                 llc[2] = 4;
8017                 add_p(plci, LLC, llc);
8018                 dlc[0] = 2;
8019                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8020                 add_p(plci, DLC, dlc);
8021                 return 0;
8022         }
8023         dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
8024         if ((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT;
8025
8026         if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8027         {
8028                 bp_parms[6].length = 0;
8029                 if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8030                 {
8031                         dbug(1, dprintf("b-form.!"));
8032                         return _WRONG_MESSAGE_FORMAT;
8033                 }
8034         }
8035         else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8036         {
8037                 dbug(1, dprintf("b-form.!"));
8038                 return _WRONG_MESSAGE_FORMAT;
8039         }
8040
8041         if (plci->tel == ADV_VOICE) /* transparent B on advanced voice */
8042         {
8043                 if (GET_WORD(bp_parms[1].info) != 1
8044                     || GET_WORD(bp_parms[2].info) != 0) return _B2_NOT_SUPPORTED;
8045                 plci->adv_nl = true;
8046         }
8047         else if (plci->tel) return _B2_NOT_SUPPORTED;
8048
8049
8050         if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8051             && (GET_WORD(bp_parms[2].info) == B3_RTP)
8052             && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8053         {
8054                 add_p(plci, LLI, lli);
8055                 plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8056                 plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8057                 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8058                 llc[2] = 4;
8059                 add_p(plci, LLC, llc);
8060                 dlc[0] = 2;
8061                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8062                 dlc[3] = 3; /* Addr A */
8063                 dlc[4] = 1; /* Addr B */
8064                 dlc[5] = 7; /* modulo mode */
8065                 dlc[6] = 7; /* window size */
8066                 dlc[7] = 0; /* XID len Lo  */
8067                 dlc[8] = 0; /* XID len Hi  */
8068                 for (i = 0; i < bp_parms[4].length; i++)
8069                         dlc[9 + i] = bp_parms[4].info[1 + i];
8070                 dlc[0] = (byte)(8 + bp_parms[4].length);
8071                 add_p(plci, DLC, dlc);
8072                 for (i = 0; i < bp_parms[5].length; i++)
8073                         nlc[1 + i] = bp_parms[5].info[1 + i];
8074                 nlc[0] = (byte)(bp_parms[5].length);
8075                 add_p(plci, NLC, nlc);
8076                 return 0;
8077         }
8078
8079
8080
8081         if ((GET_WORD(bp_parms[1].info) >= 32)
8082             || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8083                 && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8084                     || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8085
8086         {
8087                 return _B2_NOT_SUPPORTED;
8088         }
8089         if ((GET_WORD(bp_parms[2].info) >= 32)
8090             || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8091         {
8092                 return _B3_NOT_SUPPORTED;
8093         }
8094         if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8095             && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8096                 || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8097                 || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8098         {
8099                 return (add_modem_b23(plci, bp_parms));
8100         }
8101
8102         add_p(plci, LLI, lli);
8103
8104         plci->B2_prot = (byte)GET_WORD(bp_parms[1].info);
8105         plci->B3_prot = (byte)GET_WORD(bp_parms[2].info);
8106         if (plci->B2_prot == 12) SAPI = 0; /* default SAPI D-channel */
8107
8108         if (bp_parms[6].length)
8109         {
8110                 if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8111                 {
8112                         return _WRONG_MESSAGE_FORMAT;
8113                 }
8114                 switch (GET_WORD(global_config[0].info))
8115                 {
8116                 case 1:
8117                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8118                         break;
8119                 case 2:
8120                         plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8121                         break;
8122                 }
8123         }
8124         dbug(1, dprintf("call_dir=%04x", plci->call_dir));
8125
8126
8127         if (plci->B2_prot == B2_PIAFS)
8128                 llc[1] = PIAFS_CRC;
8129         else
8130 /* IMPLEMENT_PIAFS */
8131         {
8132                 llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8133                         llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8134         }
8135         llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8136
8137         add_p(plci, LLC, llc);
8138
8139         dlc[0] = 2;
8140         PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8141                  header[GET_WORD(bp_parms[2].info)]);
8142
8143         b1_config = &bp_parms[3];
8144         nlc[0] = 0;
8145         if (plci->B3_prot == 4
8146             || plci->B3_prot == 5)
8147         {
8148                 for (i = 0; i < sizeof(T30_INFO); i++) nlc[i] = 0;
8149                 nlc[0] = sizeof(T30_INFO);
8150                 if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8151                         ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8152                 ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8153                 if (b1_config->length >= 2)
8154                 {
8155                         ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1]) / 2400);
8156                 }
8157         }
8158         b2_config = &bp_parms[4];
8159
8160
8161         if (llc[1] == PIAFS_CRC)
8162         {
8163                 if (plci->B3_prot != B3_TRANSPARENT)
8164                 {
8165                         return _B_STACK_NOT_SUPPORTED;
8166                 }
8167                 if (b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8168                         return _WRONG_MESSAGE_FORMAT;
8169                 }
8170                 PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8171                 dlc[3] = 0; /* Addr A */
8172                 dlc[4] = 0; /* Addr B */
8173                 dlc[5] = 0; /* modulo mode */
8174                 dlc[6] = 0; /* window size */
8175                 if (b2_config->length >= 7) {
8176                         dlc[7] = 7;
8177                         dlc[8] = 0;
8178                         dlc[9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8179                         dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8180                         dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8181                         dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8182                         dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8183                         dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8184                         dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8185                         dlc[0] = 15;
8186                         if (b2_config->length >= 8) { /* PIAFS control abilities */
8187                                 dlc[7] = 10;
8188                                 dlc[16] = 2; /* Length of PIAFS extension */
8189                                 dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8190                                 dlc[18] = b2_config_parms[4].info[0]; /* value */
8191                                 dlc[0] = 18;
8192                         }
8193                 }
8194                 else /* default values, 64K, variable, no compression */
8195                 {
8196                         dlc[7] = 7;
8197                         dlc[8] = 0;
8198                         dlc[9] = 0x03; /* PIAFS protocol Speed configuration */
8199                         dlc[10] = 0x03; /* V.42bis P0 */
8200                         dlc[11] = 0;    /* V.42bis P0 */
8201                         dlc[12] = 0;    /* V.42bis P1 */
8202                         dlc[13] = 0;    /* V.42bis P1 */
8203                         dlc[14] = 0;    /* V.42bis P2 */
8204                         dlc[15] = 0;    /* V.42bis P2 */
8205                         dlc[0] = 15;
8206                 }
8207                 add_p(plci, DLC, dlc);
8208         }
8209         else
8210
8211                 if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8212                 {
8213                         if (plci->B3_prot != B3_TRANSPARENT)
8214                                 return _B_STACK_NOT_SUPPORTED;
8215
8216                         dlc[0] = 6;
8217                         PUT_WORD(&dlc[1], GET_WORD(&dlc[1]) + 2);
8218                         dlc[3] = 0x08;
8219                         dlc[4] = 0x01;
8220                         dlc[5] = 127;
8221                         dlc[6] = 7;
8222                         if (b2_config->length != 0)
8223                         {
8224                                 if ((llc[1] == V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8225                                         return _WRONG_MESSAGE_FORMAT;
8226                                 }
8227                                 dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8228                                 dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8229                                 if (b2_config->info[3] != 128)
8230                                 {
8231                                         dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8232                                         return _B2_PARM_NOT_SUPPORTED;
8233                                 }
8234                                 dlc[5] = (byte)(b2_config->info[3] - 1);
8235                                 dlc[6] = b2_config->info[4];
8236                                 if (llc[1] == V120_V42BIS) {
8237                                         if (b2_config->length >= 10) {
8238                                                 dlc[7] = 6;
8239                                                 dlc[8] = 0;
8240                                                 dlc[9] = b2_config_parms[4].info[0];
8241                                                 dlc[10] = b2_config_parms[4].info[1];
8242                                                 dlc[11] = b2_config_parms[5].info[0];
8243                                                 dlc[12] = b2_config_parms[5].info[1];
8244                                                 dlc[13] = b2_config_parms[6].info[0];
8245                                                 dlc[14] = b2_config_parms[6].info[1];
8246                                                 dlc[0] = 14;
8247                                                 dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8248                                                 dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8249                                                 dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8250                                         }
8251                                         else {
8252                                                 dlc[6] = 14;
8253                                         }
8254                                 }
8255                         }
8256                 }
8257                 else
8258                 {
8259                         if (b2_config->length)
8260                         {
8261                                 dbug(1, dprintf("B2-Config"));
8262                                 if (llc[1] == X75_V42BIS) {
8263                                         if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8264                                         {
8265                                                 return _WRONG_MESSAGE_FORMAT;
8266                                         }
8267                                 }
8268                                 else {
8269                                         if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8270                                         {
8271                                                 return _WRONG_MESSAGE_FORMAT;
8272                                         }
8273                                 }
8274                                 /* if B2 Protocol is LAPD, b2_config structure is different */
8275                                 if (llc[1] == 6)
8276                                 {
8277                                         dlc[0] = 4;
8278                                         if (b2_config->length >= 1) dlc[2] = b2_config->info[1];      /* TEI */
8279                                         else dlc[2] = 0x01;
8280                                         if ((b2_config->length >= 2) && (plci->B2_prot == 12))
8281                                         {
8282                                                 SAPI = b2_config->info[2];    /* SAPI */
8283                                         }
8284                                         dlc[1] = SAPI;
8285                                         if ((b2_config->length >= 3) && (b2_config->info[3] == 128))
8286                                         {
8287                                                 dlc[3] = 127;      /* Mode */
8288                                         }
8289                                         else
8290                                         {
8291                                                 dlc[3] = 7;        /* Mode */
8292                                         }
8293
8294                                         if (b2_config->length >= 4) dlc[4] = b2_config->info[4];      /* Window */
8295                                         else dlc[4] = 1;
8296                                         dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8297                                         if (b2_config->length > 5) return _B2_PARM_NOT_SUPPORTED;
8298                                 }
8299                                 else
8300                                 {
8301                                         dlc[0] = (byte)(b2_config_parms[4].length + 6);
8302                                         dlc[3] = b2_config->info[1];
8303                                         dlc[4] = b2_config->info[2];
8304                                         if (b2_config->info[3] != 8 && b2_config->info[3] != 128) {
8305                                                 dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8306                                                 return _B2_PARM_NOT_SUPPORTED;
8307                                         }
8308
8309                                         dlc[5] = (byte)(b2_config->info[3] - 1);
8310                                         dlc[6] = b2_config->info[4];
8311                                         if (dlc[6] > dlc[5]) {
8312                                                 dbug(1, dprintf("2D-dlc= %x %x %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4], dlc[5], dlc[6]));
8313                                                 return _B2_PARM_NOT_SUPPORTED;
8314                                         }
8315
8316                                         if (llc[1] == X75_V42BIS) {
8317                                                 if (b2_config->length >= 10) {
8318                                                         dlc[7] = 6;
8319                                                         dlc[8] = 0;
8320                                                         dlc[9] = b2_config_parms[4].info[0];
8321                                                         dlc[10] = b2_config_parms[4].info[1];
8322                                                         dlc[11] = b2_config_parms[5].info[0];
8323                                                         dlc[12] = b2_config_parms[5].info[1];
8324                                                         dlc[13] = b2_config_parms[6].info[0];
8325                                                         dlc[14] = b2_config_parms[6].info[1];
8326                                                         dlc[0] = 14;
8327                                                         dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8328                                                         dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8329                                                         dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8330                                                 }
8331                                                 else {
8332                                                         dlc[6] = 14;
8333                                                 }
8334
8335                                         }
8336                                         else {
8337                                                 PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8338                                                 for (i = 0; i < b2_config_parms[4].length; i++)
8339                                                         dlc[11 + i] = b2_config_parms[4].info[1 + i];
8340                                         }
8341                                 }
8342                         }
8343                 }
8344         add_p(plci, DLC, dlc);
8345
8346         b3_config = &bp_parms[5];
8347         if (b3_config->length)
8348         {
8349                 if (plci->B3_prot == 4
8350                     || plci->B3_prot == 5)
8351                 {
8352                         if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8353                         {
8354                                 return _WRONG_MESSAGE_FORMAT;
8355                         }
8356                         i = GET_WORD((byte *)(b3_config_parms[0].info));
8357                         ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8358                                                                     ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8359                         ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8360                         fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8361                         if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8362                                 fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8363                         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8364                         {
8365
8366                                 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8367                                     & (1L << PRIVATE_FAX_PAPER_FORMATS))
8368                                 {
8369                                         ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8370                                                 T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8371                                                 T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8372                                 }
8373
8374                                 ((T30_INFO *)&nlc[1])->recording_properties =
8375                                         T30_RECORDING_WIDTH_ISO_A3 |
8376                                         (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8377                                         (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8378                         }
8379                         if (plci->B3_prot == 5)
8380                         {
8381                                 if (i & 0x0002) /* Accept incoming fax-polling requests */
8382                                         fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8383                                 if (i & 0x2000) /* Do not use MR compression */
8384                                         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8385                                 if (i & 0x4000) /* Do not use MMR compression */
8386                                         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8387                                 if (i & 0x8000) /* Do not use ECM */
8388                                         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8389                                 if (plci->fax_connect_info_length != 0)
8390                                 {
8391                                         ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8392                                         ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8393                                         ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8394                                         fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8395                                                 (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8396                                 }
8397                         }
8398                         /* copy station id to NLC */
8399                         for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
8400                         {
8401                                 if (i < b3_config_parms[2].length)
8402                                 {
8403                                         ((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1 + i];
8404                                 }
8405                                 else
8406                                 {
8407                                         ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8408                                 }
8409                         }
8410                         ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8411                         /* copy head line to NLC */
8412                         if (b3_config_parms[3].length)
8413                         {
8414
8415                                 pos = (byte)(fax_head_line_time(&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8416                                 if (pos != 0)
8417                                 {
8418                                         if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8419                                                 pos = 0;
8420                                         else
8421                                         {
8422                                                 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8423                                                 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8424                                                 len = (byte)b3_config_parms[2].length;
8425                                                 if (len > 20)
8426                                                         len = 20;
8427                                                 if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8428                                                 {
8429                                                         for (i = 0; i < len; i++)
8430                                                                 nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1 + i];
8431                                                         nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8432                                                         nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8433                                                 }
8434                                         }
8435                                 }
8436
8437                                 len = (byte)b3_config_parms[3].length;
8438                                 if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8439                                         len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8440                                 ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8441                                 nlc[0] += (byte)(pos + len);
8442                                 for (i = 0; i < len; i++)
8443                                         nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] =  ((byte *)b3_config_parms[3].info)[1 + i];
8444                         } else
8445                                 ((T30_INFO *)&nlc[1])->head_line_len = 0;
8446
8447                         plci->nsf_control_bits = 0;
8448                         if (plci->B3_prot == 5)
8449                         {
8450                                 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8451                                     && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8452                                 {
8453                                         plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8454                                 }
8455                                 if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8456                                     && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8457                                 {
8458                                         plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8459                                 }
8460                                 if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8461                                     & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8462                                 {
8463                                         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8464                                             & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8465                                         {
8466                                                 fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8467                                                 if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8468                                                         fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8469                                         }
8470                                         len = nlc[0];
8471                                         pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8472                                         if (pos < plci->fax_connect_info_length)
8473                                         {
8474                                                 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8475                                                         nlc[++len] = plci->fax_connect_info_buffer[pos++];
8476                                         }
8477                                         else
8478                                                 nlc[++len] = 0;
8479                                         if (pos < plci->fax_connect_info_length)
8480                                         {
8481                                                 for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8482                                                         nlc[++len] = plci->fax_connect_info_buffer[pos++];
8483                                         }
8484                                         else
8485                                                 nlc[++len] = 0;
8486                                         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8487                                             & (1L << PRIVATE_FAX_NONSTANDARD))
8488                                         {
8489                                                 if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8490                                                 {
8491                                                         if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos + 1] >= 2))
8492                                                                 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos + 2]);
8493                                                         for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8494                                                                 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8495                                                 }
8496                                                 else
8497                                                 {
8498                                                         if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8499                                                         {
8500                                                                 dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8501                                                                 nlc[++len] = 0;
8502                                                         }
8503                                                         else
8504                                                         {
8505                                                                 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8506                                                                         plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8507                                                                 nlc[++len] = (byte)(b3_config_parms[4].length);
8508                                                                 for (i = 0; i < b3_config_parms[4].length; i++)
8509                                                                         nlc[++len] = b3_config_parms[4].info[1 + i];
8510                                                         }
8511                                                 }
8512                                         }
8513                                         nlc[0] = len;
8514                                         if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8515                                             && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8516                                         {
8517                                                 ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8518                                         }
8519                                 }
8520                         }
8521
8522                         PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8523                         len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8524                         for (i = 0; i < len; i++)
8525                                 plci->fax_connect_info_buffer[i] = nlc[1 + i];
8526                         ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8527                         i += ((T30_INFO *)&nlc[1])->head_line_len;
8528                         while (i < nlc[0])
8529                                 plci->fax_connect_info_buffer[len++] = nlc[++i];
8530                         plci->fax_connect_info_length = len;
8531                 }
8532                 else
8533                 {
8534                         nlc[0] = 14;
8535                         if (b3_config->length != 16)
8536                                 return _B3_PARM_NOT_SUPPORTED;
8537                         for (i = 0; i < 12; i++) nlc[1 + i] = b3_config->info[1 + i];
8538                         if (GET_WORD(&b3_config->info[13]) != 8 && GET_WORD(&b3_config->info[13]) != 128)
8539                                 return _B3_PARM_NOT_SUPPORTED;
8540                         nlc[13] = b3_config->info[13];
8541                         if (GET_WORD(&b3_config->info[15]) >= nlc[13])
8542                                 return _B3_PARM_NOT_SUPPORTED;
8543                         nlc[14] = b3_config->info[15];
8544                 }
8545         }
8546         else
8547         {
8548                 if (plci->B3_prot == 4
8549                     || plci->B3_prot == 5 /*T.30 - FAX*/) return _B3_PARM_NOT_SUPPORTED;
8550         }
8551         add_p(plci, NLC, nlc);
8552         return 0;
8553 }
8554
8555 /*----------------------------------------------------------------*/
8556 /*      make the same as add_b23, but only for the modem related  */
8557 /*      L2 and L3 B-Chan protocol.                                */
8558 /*                                                                */
8559 /*      Enabled L2 and L3 Configurations:                         */
8560 /*        If L1 == Modem all negotiation                          */
8561 /*          only L2 == Modem with full negotiation is allowed     */
8562 /*        If L1 == Modem async or sync                            */
8563 /*          only L2 == Transparent is allowed                     */
8564 /*        L3 == Modem or L3 == Transparent are allowed            */
8565 /*      B2 Configuration for modem:                               */
8566 /*          word : enable/disable compression, bitoptions         */
8567 /*      B3 Configuration for modem:                               */
8568 /*          empty                                                 */
8569 /*----------------------------------------------------------------*/
8570 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms)
8571 {
8572         static byte lli[12] = {1,1};
8573         static byte llc[3] = {2,0,0};
8574         static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8575         API_PARSE mdm_config[2];
8576         word i;
8577         word b2_config = 0;
8578
8579         for (i = 0; i < 2; i++) mdm_config[i].length = 0;
8580         for (i = 0; i < sizeof(dlc); i++) dlc[i] = 0;
8581
8582         if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8583              && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8584             || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8585                 && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8586         {
8587                 return (_B_STACK_NOT_SUPPORTED);
8588         }
8589         if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8590             && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8591         {
8592                 return (_B_STACK_NOT_SUPPORTED);
8593         }
8594
8595         plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8596         plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8597
8598         if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8599         {
8600                 if (api_parse(&bp_parms[4].info[1],
8601                               (word)bp_parms[4].length, "w",
8602                               mdm_config))
8603                 {
8604                         return (_WRONG_MESSAGE_FORMAT);
8605                 }
8606                 b2_config = GET_WORD(mdm_config[0].info);
8607         }
8608
8609         /* OK, L2 is modem */
8610
8611         lli[0] = 1;
8612         lli[1] = 1;
8613         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8614                 lli[1] |= 2;
8615         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8616                 lli[1] |= 4;
8617
8618         if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8619                 lli[1] |= 0x10;
8620                 if (plci->rx_dma_descriptor <= 0) {
8621                         plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
8622                         if (plci->rx_dma_descriptor >= 0)
8623                                 plci->rx_dma_descriptor++;
8624                 }
8625                 if (plci->rx_dma_descriptor > 0) {
8626                         lli[1] |= 0x40;
8627                         lli[0] = 6;
8628                         lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8629                         lli[3] = (byte)plci->rx_dma_magic;
8630                         lli[4] = (byte)(plci->rx_dma_magic >>  8);
8631                         lli[5] = (byte)(plci->rx_dma_magic >> 16);
8632                         lli[6] = (byte)(plci->rx_dma_magic >> 24);
8633                 }
8634         }
8635
8636         if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8637                 lli[1] |= 0x20;
8638         }
8639
8640         llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8641                 /*V42*/ 10 : /*V42_IN*/ 9;
8642         llc[2] = 4;                      /* pass L3 always transparent */
8643         add_p(plci, LLI, lli);
8644         add_p(plci, LLC, llc);
8645         i =  1;
8646         PUT_WORD(&dlc[i], plci->appl->MaxDataLength);
8647         i += 2;
8648         if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8649         {
8650                 if (bp_parms[4].length)
8651                 {
8652                         dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8653                         dlc[i++] = 3; /* Addr A */
8654                         dlc[i++] = 1; /* Addr B */
8655                         dlc[i++] = 7; /* modulo mode */
8656                         dlc[i++] = 7; /* window size */
8657                         dlc[i++] = 0; /* XID len Lo  */
8658                         dlc[i++] = 0; /* XID len Hi  */
8659
8660                         if (b2_config & MDM_B2_DISABLE_V42bis)
8661                         {
8662                                 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8663                         }
8664                         if (b2_config & MDM_B2_DISABLE_MNP)
8665                         {
8666                                 dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8667                         }
8668                         if (b2_config & MDM_B2_DISABLE_TRANS)
8669                         {
8670                                 dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8671                         }
8672                         if (b2_config & MDM_B2_DISABLE_V42)
8673                         {
8674                                 dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8675                         }
8676                         if (b2_config & MDM_B2_DISABLE_COMP)
8677                         {
8678                                 dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8679                         }
8680                         i++;
8681                 }
8682         }
8683         else
8684         {
8685                 dlc[i++] = 3; /* Addr A */
8686                 dlc[i++] = 1; /* Addr B */
8687                 dlc[i++] = 7; /* modulo mode */
8688                 dlc[i++] = 7; /* window size */
8689                 dlc[i++] = 0; /* XID len Lo  */
8690                 dlc[i++] = 0; /* XID len Hi  */
8691                 dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8692                         DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8693                         DLC_MODEMPROT_DISABLE_V42_DETECT |
8694                         DLC_MODEMPROT_DISABLE_COMPRESSION;
8695         }
8696         dlc[0] = (byte)(i - 1);
8697 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8698         add_p(plci, DLC, dlc);
8699         return (0);
8700 }
8701
8702
8703 /*------------------------------------------------------------------*/
8704 /* send a request for the signaling entity                          */
8705 /*------------------------------------------------------------------*/
8706
8707 static void sig_req(PLCI *plci, byte req, byte Id)
8708 {
8709         if (!plci) return;
8710         if (plci->adapter->adapter_disabled) return;
8711         dbug(1, dprintf("sig_req(%x)", req));
8712         if (req == REMOVE)
8713                 plci->sig_remove_id = plci->Sig.Id;
8714         if (plci->req_in == plci->req_in_start) {
8715                 plci->req_in += 2;
8716                 plci->RBuffer[plci->req_in++] = 0;
8717         }
8718         PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8719         plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
8720         plci->RBuffer[plci->req_in++] = req;  /* request */
8721         plci->RBuffer[plci->req_in++] = 0;    /* channel */
8722         plci->req_in_start = plci->req_in;
8723 }
8724
8725 /*------------------------------------------------------------------*/
8726 /* send a request for the network layer entity                      */
8727 /*------------------------------------------------------------------*/
8728
8729 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8730 {
8731         if (!plci) return;
8732         if (plci->adapter->adapter_disabled) return;
8733         dbug(1, dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8734         if (req == REMOVE)
8735         {
8736                 plci->nl_remove_id = plci->NL.Id;
8737                 ncci_remove(plci, 0, (byte)(ncci != 0));
8738                 ncci = 0;
8739         }
8740         if (plci->req_in == plci->req_in_start) {
8741                 plci->req_in += 2;
8742                 plci->RBuffer[plci->req_in++] = 0;
8743         }
8744         PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8745         plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */
8746         plci->RBuffer[plci->req_in++] = req;  /* request */
8747         plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
8748         plci->req_in_start = plci->req_in;
8749 }
8750
8751 static void send_req(PLCI *plci)
8752 {
8753         ENTITY *e;
8754         word l;
8755 /*  word i; */
8756
8757         if (!plci) return;
8758         if (plci->adapter->adapter_disabled) return;
8759         channel_xmit_xon(plci);
8760
8761         /* if nothing to do, return */
8762         if (plci->req_in == plci->req_out) return;
8763         dbug(1, dprintf("send_req(in=%d,out=%d)", plci->req_in, plci->req_out));
8764
8765         if (plci->nl_req || plci->sig_req) return;
8766
8767         l = GET_WORD(&plci->RBuffer[plci->req_out]);
8768         plci->req_out += 2;
8769         plci->XData[0].P = &plci->RBuffer[plci->req_out];
8770         plci->req_out += l;
8771         if (plci->RBuffer[plci->req_out] == 1)
8772         {
8773                 e = &plci->NL;
8774                 plci->req_out++;
8775                 e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8776                 e->ReqCh = plci->RBuffer[plci->req_out++];
8777                 if (!(e->Id & 0x1f))
8778                 {
8779                         e->Id = NL_ID;
8780                         plci->RBuffer[plci->req_out - 4] = CAI;
8781                         plci->RBuffer[plci->req_out - 3] = 1;
8782                         plci->RBuffer[plci->req_out - 2] = (plci->Sig.Id == 0xff) ? 0 : plci->Sig.Id;
8783                         plci->RBuffer[plci->req_out - 1] = 0;
8784                         l += 3;
8785                         plci->nl_global_req = plci->nl_req;
8786                 }
8787                 dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8788         }
8789         else
8790         {
8791                 e = &plci->Sig;
8792                 if (plci->RBuffer[plci->req_out])
8793                         e->Id = plci->RBuffer[plci->req_out];
8794                 plci->req_out++;
8795                 e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8796                 e->ReqCh = plci->RBuffer[plci->req_out++];
8797                 if (!(e->Id & 0x1f))
8798                         plci->sig_global_req = plci->sig_req;
8799                 dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8800         }
8801         plci->XData[0].PLength = l;
8802         e->X = plci->XData;
8803         plci->adapter->request(e);
8804         dbug(1, dprintf("send_ok"));
8805 }
8806
8807 static void send_data(PLCI *plci)
8808 {
8809         DIVA_CAPI_ADAPTER *a;
8810         DATA_B3_DESC *data;
8811         NCCI   *ncci_ptr;
8812         word ncci;
8813
8814         if (!plci->nl_req && plci->ncci_ring_list)
8815         {
8816                 a = plci->adapter;
8817                 ncci = plci->ncci_ring_list;
8818                 do
8819                 {
8820                         ncci = a->ncci_next[ncci];
8821                         ncci_ptr = &(a->ncci[ncci]);
8822                         if (!(a->ncci_ch[ncci]
8823                               && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8824                         {
8825                                 if (ncci_ptr->data_pending)
8826                                 {
8827                                         if ((a->ncci_state[ncci] == CONNECTED)
8828                                             || (a->ncci_state[ncci] == INC_ACT_PENDING)
8829                                             || (plci->send_disc == ncci))
8830                                         {
8831                                                 data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8832                                                 if ((plci->B2_prot == B2_V120_ASYNC)
8833                                                     || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8834                                                     || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8835                                                 {
8836                                                         plci->NData[1].P = TransmitBufferGet(plci->appl, data->P);
8837                                                         plci->NData[1].PLength = data->Length;
8838                                                         if (data->Flags & 0x10)
8839                                                                 plci->NData[0].P = v120_break_header;
8840                                                         else
8841                                                                 plci->NData[0].P = v120_default_header;
8842                                                         plci->NData[0].PLength = 1;
8843                                                         plci->NL.XNum = 2;
8844                                                         plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8845                                                 }
8846                                                 else
8847                                                 {
8848                                                         plci->NData[0].P = TransmitBufferGet(plci->appl, data->P);
8849                                                         plci->NData[0].PLength = data->Length;
8850                                                         if (data->Flags & 0x10)
8851                                                                 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8852
8853                                                         else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8854                                                                 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8855
8856                                                         else
8857                                                                 plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8858                                                 }
8859                                                 plci->NL.X = plci->NData;
8860                                                 plci->NL.ReqCh = a->ncci_ch[ncci];
8861                                                 dbug(1, dprintf("%x:DREQ(%x:%x)", a->Id, plci->NL.Id, plci->NL.Req));
8862                                                 plci->data_sent = true;
8863                                                 plci->data_sent_ptr = data->P;
8864                                                 a->request(&plci->NL);
8865                                         }
8866                                         else {
8867                                                 cleanup_ncci_data(plci, ncci);
8868                                         }
8869                                 }
8870                                 else if (plci->send_disc == ncci)
8871                                 {
8872                                         /* dprintf("N_DISC"); */
8873                                         plci->NData[0].PLength = 0;
8874                                         plci->NL.ReqCh = a->ncci_ch[ncci];
8875                                         plci->NL.Req = plci->nl_req = N_DISC;
8876                                         a->request(&plci->NL);
8877                                         plci->command = _DISCONNECT_B3_R;
8878                                         plci->send_disc = 0;
8879                                 }
8880                         }
8881                 } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8882                 plci->ncci_ring_list = ncci;
8883         }
8884 }
8885
8886 static void listen_check(DIVA_CAPI_ADAPTER *a)
8887 {
8888         word i, j;
8889         PLCI *plci;
8890         byte activnotifiedcalls = 0;
8891
8892         dbug(1, dprintf("listen_check(%d,%d)", a->listen_active, a->max_listen));
8893         if (!remove_started && !a->adapter_disabled)
8894         {
8895                 for (i = 0; i < a->max_plci; i++)
8896                 {
8897                         plci = &(a->plci[i]);
8898                         if (plci->notifiedcall) activnotifiedcalls++;
8899                 }
8900                 dbug(1, dprintf("listen_check(%d)", activnotifiedcalls));
8901
8902                 for (i = a->listen_active; i < ((word)(a->max_listen + activnotifiedcalls)); i++) {
8903                         if ((j = get_plci(a))) {
8904                                 a->listen_active++;
8905                                 plci = &a->plci[j - 1];
8906                                 plci->State = LISTENING;
8907
8908                                 add_p(plci, OAD, "\x01\xfd");
8909
8910                                 add_p(plci, KEY, "\x04\x43\x41\x32\x30");
8911
8912                                 add_p(plci, CAI, "\x01\xc0");
8913                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
8914                                 add_p(plci, LLI, "\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */
8915                                 add_p(plci, SHIFT | 6, NULL);
8916                                 add_p(plci, SIN, "\x02\x00\x00");
8917                                 plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
8918                                 sig_req(plci, ASSIGN, DSIG_ID);
8919                                 send_req(plci);
8920                         }
8921                 }
8922         }
8923 }
8924
8925 /*------------------------------------------------------------------*/
8926 /* functions for all parameters sent in INDs                        */
8927 /*------------------------------------------------------------------*/
8928
8929 static void IndParse(PLCI *plci, word *parms_id, byte **parms, byte multiIEsize)
8930 {
8931         word ploc;            /* points to current location within packet */
8932         byte w;
8933         byte wlen;
8934         byte codeset, lock;
8935         byte *in;
8936         word i;
8937         word code;
8938         word mIEindex = 0;
8939         ploc = 0;
8940         codeset = 0;
8941         lock = 0;
8942
8943         in = plci->Sig.RBuffer->P;
8944         for (i = 0; i < parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
8945         {                            /* element but parms array is larger      */
8946                 parms[i] = (byte *)"";
8947         }
8948         for (i = 0; i < multiIEsize; i++)
8949         {
8950                 parms[i] = (byte *)"";
8951         }
8952
8953         while (ploc < plci->Sig.RBuffer->length - 1) {
8954
8955                 /* read information element id and length                   */
8956                 w = in[ploc];
8957
8958                 if (w & 0x80) {
8959 /*    w &=0xf0; removed, cannot detect congestion levels */
8960 /*    upper 4 bit masked with w==SHIFT now               */
8961                         wlen = 0;
8962                 }
8963                 else {
8964                         wlen = (byte)(in[ploc + 1] + 1);
8965                 }
8966                 /* check if length valid (not exceeding end of packet)      */
8967                 if ((ploc + wlen) > 270) return;
8968                 if (lock & 0x80) lock &= 0x7f;
8969                 else codeset = lock;
8970
8971                 if ((w & 0xf0) == SHIFT) {
8972                         codeset = in[ploc];
8973                         if (!(codeset & 0x08)) lock = (byte)(codeset & 7);
8974                         codeset &= 7;
8975                         lock |= 0x80;
8976                 }
8977                 else {
8978                         if (w == ESC && wlen >= 3) code = in[ploc + 2] | 0x800;
8979                         else code = w;
8980                         code |= (codeset << 8);
8981
8982                         for (i = 1; i < parms_id[0] + 1 && parms_id[i] != code; i++);
8983
8984                         if (i < parms_id[0] + 1) {
8985                                 if (!multiIEsize) { /* with multiIEs use next field index,          */
8986                                         mIEindex = i - 1;    /* with normal IEs use same index like parms_id */
8987                                 }
8988
8989                                 parms[mIEindex] = &in[ploc + 1];
8990                                 dbug(1, dprintf("mIE[%d]=0x%x", *parms[mIEindex], in[ploc]));
8991                                 if (parms_id[i] == OAD
8992                                     || parms_id[i] == CONN_NR
8993                                     || parms_id[i] == CAD) {
8994                                         if (in[ploc + 2] & 0x80) {
8995                                                 in[ploc + 0] = (byte)(in[ploc + 1] + 1);
8996                                                 in[ploc + 1] = (byte)(in[ploc + 2] & 0x7f);
8997                                                 in[ploc + 2] = 0x80;
8998                                                 parms[mIEindex] = &in[ploc];
8999                                         }
9000                                 }
9001                                 mIEindex++;       /* effects multiIEs only */
9002                         }
9003                 }
9004
9005                 ploc += (wlen + 1);
9006         }
9007         return;
9008 }
9009
9010 /*------------------------------------------------------------------*/
9011 /* try to match a cip from received BC and HLC                      */
9012 /*------------------------------------------------------------------*/
9013
9014 static byte ie_compare(byte *ie1, byte *ie2)
9015 {
9016         word i;
9017         if (!ie1 || !ie2) return false;
9018         if (!ie1[0]) return false;
9019         for (i = 0; i < (word)(ie1[0] + 1); i++) if (ie1[i] != ie2[i]) return false;
9020         return true;
9021 }
9022
9023 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
9024 {
9025         word i;
9026         word j;
9027
9028         for (i = 9; i && !ie_compare(bc, cip_bc[i][a->u_law]); i--);
9029
9030         for (j = 16; j < 29 &&
9031                      (!ie_compare(bc, cip_bc[j][a->u_law]) || !ie_compare(hlc, cip_hlc[j])); j++);
9032         if (j == 29) return i;
9033         return j;
9034 }
9035
9036
9037 static byte AddInfo(byte **add_i,
9038                     byte **fty_i,
9039                     byte *esc_chi,
9040                     byte *facility)
9041 {
9042         byte i;
9043         byte j;
9044         byte k;
9045         byte flen;
9046         byte len = 0;
9047         /* facility is a nested structure */
9048         /* FTY can be more than once      */
9049
9050         if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
9051         {
9052                 add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9053         }
9054
9055         else
9056         {
9057                 add_i[0] = (byte *)"";
9058         }
9059         if (!fty_i[0][0])
9060         {
9061                 add_i[3] = (byte *)"";
9062         }
9063         else
9064         {    /* facility array found  */
9065                 for (i = 0, j = 1; i < MAX_MULTI_IE && fty_i[i][0]; i++)
9066                 {
9067                         dbug(1, dprintf("AddIFac[%d]", fty_i[i][0]));
9068                         len += fty_i[i][0];
9069                         len += 2;
9070                         flen = fty_i[i][0];
9071                         facility[j++] = 0x1c; /* copy fac IE */
9072                         for (k = 0; k <= flen; k++, j++)
9073                         {
9074                                 facility[j] = fty_i[i][k];
9075 /*      dbug(1, dprintf("%x ",facility[j])); */
9076                         }
9077                 }
9078                 facility[0] = len;
9079                 add_i[3] = facility;
9080         }
9081 /*  dbug(1, dprintf("FacArrLen=%d ",len)); */
9082         len = add_i[0][0] + add_i[1][0] + add_i[2][0] + add_i[3][0];
9083         len += 4;                          /* calculate length of all */
9084         return (len);
9085 }
9086
9087 /*------------------------------------------------------------------*/
9088 /* voice and codec features                                         */
9089 /*------------------------------------------------------------------*/
9090
9091 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
9092 {
9093         byte voice_chi[] = "\x02\x18\x01";
9094         byte channel;
9095
9096         channel = chi[chi[0]] & 0x3;
9097         dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel));
9098         voice_chi[2] = (channel) ? channel : 1;
9099         add_p(plci, FTY, "\x02\x01\x07");             /* B On, default on 1 */
9100         add_p(plci, ESC, voice_chi);                  /* Channel */
9101         sig_req(plci, TEL_CTRL, 0);
9102         send_req(plci);
9103         if (a->AdvSignalPLCI)
9104         {
9105                 adv_voice_write_coefs(a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9106         }
9107 }
9108
9109 static void VoiceChannelOff(PLCI *plci)
9110 {
9111         dbug(1, dprintf("ExtDevOFF"));
9112         add_p(plci, FTY, "\x02\x01\x08");             /* B Off */
9113         sig_req(plci, TEL_CTRL, 0);
9114         send_req(plci);
9115         if (plci->adapter->AdvSignalPLCI)
9116         {
9117                 adv_voice_clear_config(plci->adapter->AdvSignalPLCI);
9118         }
9119 }
9120
9121
9122 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9123                             byte hook_listen)
9124 {
9125         word j;
9126         PLCI *splci;
9127
9128         /* check if hardware supports handset with hook states (adv.codec) */
9129         /* or if just a on board codec is supported                        */
9130         /* the advanced codec plci is just for internal use                */
9131
9132         /* diva Pro with on-board codec:                                   */
9133         if (a->profile.Global_Options & HANDSET)
9134         {
9135                 /* new call, but hook states are already signalled */
9136                 if (a->AdvCodecFLAG)
9137                 {
9138                         if (a->AdvSignalAppl != appl || a->AdvSignalPLCI)
9139                         {
9140                                 dbug(1, dprintf("AdvSigPlci=0x%x", a->AdvSignalPLCI));
9141                                 return 0x2001; /* codec in use by another application */
9142                         }
9143                         if (plci != NULL)
9144                         {
9145                                 a->AdvSignalPLCI = plci;
9146                                 plci->tel = ADV_VOICE;
9147                         }
9148                         return 0;                      /* adv codec still used */
9149                 }
9150                 if ((j = get_plci(a)))
9151                 {
9152                         splci = &a->plci[j - 1];
9153                         splci->tel = CODEC_PERMANENT;
9154                         /* hook_listen indicates if a facility_req with handset/hook support */
9155                         /* was sent. Otherwise if just a call on an external device was made */
9156                         /* the codec will be used but the hook info will be discarded (just  */
9157                         /* the external controller is in use                                 */
9158                         if (hook_listen) splci->State = ADVANCED_VOICE_SIG;
9159                         else
9160                         {
9161                                 splci->State = ADVANCED_VOICE_NOSIG;
9162                                 if (plci)
9163                                 {
9164                                         plci->spoofed_msg = SPOOFING_REQUIRED;
9165                                 }
9166                                 /* indicate D-ch connect if  */
9167                         }                                        /* codec is connected OK     */
9168                         if (plci != NULL)
9169                         {
9170                                 a->AdvSignalPLCI = plci;
9171                                 plci->tel = ADV_VOICE;
9172                         }
9173                         a->AdvSignalAppl = appl;
9174                         a->AdvCodecFLAG = true;
9175                         a->AdvCodecPLCI = splci;
9176                         add_p(splci, CAI, "\x01\x15");
9177                         add_p(splci, LLI, "\x01\x00");
9178                         add_p(splci, ESC, "\x02\x18\x00");
9179                         add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9180                         splci->internal_command = PERM_COD_ASSIGN;
9181                         dbug(1, dprintf("Codec Assign"));
9182                         sig_req(splci, ASSIGN, DSIG_ID);
9183                         send_req(splci);
9184                 }
9185                 else
9186                 {
9187                         return 0x2001; /* wrong state, no more plcis */
9188                 }
9189         }
9190         else if (a->profile.Global_Options & ON_BOARD_CODEC)
9191         {
9192                 if (hook_listen) return 0x300B;               /* Facility not supported */
9193                 /* no hook with SCOM      */
9194                 if (plci != NULL) plci->tel = CODEC;
9195                 dbug(1, dprintf("S/SCOM codec"));
9196                 /* first time we use the scom-s codec we must shut down the internal   */
9197                 /* handset application of the card. This can be done by an assign with */
9198                 /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9199                 if (!a->scom_appl_disable) {
9200                         if ((j = get_plci(a))) {
9201                                 splci = &a->plci[j - 1];
9202                                 add_p(splci, CAI, "\x01\x80");
9203                                 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9204                                 sig_req(splci, ASSIGN, 0xC0);  /* 0xc0 is the TEL_ID */
9205                                 send_req(splci);
9206                                 a->scom_appl_disable = true;
9207                         }
9208                         else{
9209                                 return 0x2001; /* wrong state, no more plcis */
9210                         }
9211                 }
9212         }
9213         else return 0x300B;               /* Facility not supported */
9214
9215         return 0;
9216 }
9217
9218
9219 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9220 {
9221
9222         dbug(1, dprintf("CodecIdCheck"));
9223
9224         if (a->AdvSignalPLCI == plci)
9225         {
9226                 dbug(1, dprintf("PLCI owns codec"));
9227                 VoiceChannelOff(a->AdvCodecPLCI);
9228                 if (a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9229                 {
9230                         dbug(1, dprintf("remove temp codec PLCI"));
9231                         plci_remove(a->AdvCodecPLCI);
9232                         a->AdvCodecFLAG  = 0;
9233                         a->AdvCodecPLCI  = NULL;
9234                         a->AdvSignalAppl = NULL;
9235                 }
9236                 a->AdvSignalPLCI = NULL;
9237         }
9238 }
9239
9240 /* -------------------------------------------------------------------
9241    Ask for physical address of card on PCI bus
9242    ------------------------------------------------------------------- */
9243 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *a,
9244                                        IDI_SYNC_REQ *preq) {
9245         a->sdram_bar = 0;
9246         if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9247                 ENTITY *e = (ENTITY *)preq;
9248
9249                 e->user[0] = a->Id - 1;
9250                 preq->xdi_sdram_bar.info.bar    = 0;
9251                 preq->xdi_sdram_bar.Req         = 0;
9252                 preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9253
9254                 (*(a->request))(e);
9255
9256                 a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9257                 dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9258         }
9259 }
9260
9261 /* -------------------------------------------------------------------
9262    Ask XDI about extended features
9263    ------------------------------------------------------------------- */
9264 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a) {
9265         IDI_SYNC_REQ *preq;
9266         char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
9267
9268         char features[4];
9269         preq = (IDI_SYNC_REQ *)&buffer[0];
9270
9271         if (!diva_xdi_extended_features) {
9272                 ENTITY *e = (ENTITY *)preq;
9273                 diva_xdi_extended_features |= 0x80000000;
9274
9275                 e->user[0] = a->Id - 1;
9276                 preq->xdi_extended_features.Req = 0;
9277                 preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9278                 preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9279                 preq->xdi_extended_features.info.features = &features[0];
9280
9281                 (*(a->request))(e);
9282
9283                 if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9284                         /*
9285                           Check features located in the byte '0'
9286                         */
9287                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9288                                 diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9289                         }
9290                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9291                                 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9292                                 dbug(1, dprintf("XDI provides RxDMA"));
9293                         }
9294                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9295                                 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9296                         }
9297                         if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9298                                 diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9299                                 dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9300                         }
9301
9302                 }
9303         }
9304
9305         diva_ask_for_xdi_sdram_bar(a, preq);
9306 }
9307
9308 /*------------------------------------------------------------------*/
9309 /* automatic law                                                    */
9310 /*------------------------------------------------------------------*/
9311 /* called from OS specific part after init time to get the Law              */
9312 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9313 void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9314 {
9315         word j;
9316         PLCI *splci;
9317
9318         if (a->automatic_law) {
9319                 return;
9320         }
9321         if ((j = get_plci(a))) {
9322                 diva_get_extended_adapter_features(a);
9323                 splci = &a->plci[j - 1];
9324                 a->automatic_lawPLCI = splci;
9325                 a->automatic_law = 1;
9326                 add_p(splci, CAI, "\x01\x80");
9327                 add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9328                 splci->internal_command = USELAW_REQ;
9329                 splci->command = 0;
9330                 splci->number = 0;
9331                 sig_req(splci, ASSIGN, DSIG_ID);
9332                 send_req(splci);
9333         }
9334 }
9335
9336 /* called from OS specific part if an application sends an Capi20Release */
9337 word CapiRelease(word Id)
9338 {
9339         word i, j, appls_found;
9340         PLCI *plci;
9341         APPL   *this;
9342         DIVA_CAPI_ADAPTER *a;
9343
9344         if (!Id)
9345         {
9346                 dbug(0, dprintf("A: CapiRelease(Id==0)"));
9347                 return (_WRONG_APPL_ID);
9348         }
9349
9350         this = &application[Id - 1];               /* get application pointer */
9351
9352         for (i = 0, appls_found = 0; i < max_appl; i++)
9353         {
9354                 if (application[i].Id)       /* an application has been found        */
9355                 {
9356                         appls_found++;
9357                 }
9358         }
9359
9360         for (i = 0; i < max_adapter; i++)             /* scan all adapters...    */
9361         {
9362                 a = &adapter[i];
9363                 if (a->request)
9364                 {
9365                         a->Info_Mask[Id - 1] = 0;
9366                         a->CIP_Mask[Id - 1] = 0;
9367                         a->Notification_Mask[Id - 1] = 0;
9368                         a->codec_listen[Id - 1] = NULL;
9369                         a->requested_options_table[Id - 1] = 0;
9370                         for (j = 0; j < a->max_plci; j++)           /* and all PLCIs connected */
9371                         {                                      /* with this application   */
9372                                 plci = &a->plci[j];
9373                                 if (plci->Id)                         /* if plci owns no application */
9374                                 {                                    /* it may be not jet connected */
9375                                         if (plci->State == INC_CON_PENDING
9376                                             || plci->State == INC_CON_ALERT)
9377                                         {
9378                                                 if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9379                                                 {
9380                                                         clear_c_ind_mask_bit(plci, (word)(Id - 1));
9381                                                         if (c_ind_mask_empty(plci))
9382                                                         {
9383                                                                 sig_req(plci, HANGUP, 0);
9384                                                                 send_req(plci);
9385                                                                 plci->State = OUTG_DIS_PENDING;
9386                                                         }
9387                                                 }
9388                                         }
9389                                         if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9390                                         {
9391                                                 clear_c_ind_mask_bit(plci, (word)(Id - 1));
9392                                                 if (c_ind_mask_empty(plci))
9393                                                 {
9394                                                         if (!plci->appl)
9395                                                         {
9396                                                                 plci_remove(plci);
9397                                                                 plci->State = IDLE;
9398                                                         }
9399                                                 }
9400                                         }
9401                                         if (plci->appl == this)
9402                                         {
9403                                                 plci->appl = NULL;
9404                                                 plci_remove(plci);
9405                                                 plci->State = IDLE;
9406                                         }
9407                                 }
9408                         }
9409                         listen_check(a);
9410
9411                         if (a->flag_dynamic_l1_down)
9412                         {
9413                                 if (appls_found == 1)            /* last application does a capi release */
9414                                 {
9415                                         if ((j = get_plci(a)))
9416                                         {
9417                                                 plci = &a->plci[j - 1];
9418                                                 plci->command = 0;
9419                                                 add_p(plci, OAD, "\x01\xfd");
9420                                                 add_p(plci, CAI, "\x01\x80");
9421                                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9422                                                 add_p(plci, SHIFT | 6, NULL);
9423                                                 add_p(plci, SIN, "\x02\x00\x00");
9424                                                 plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9425                                                 sig_req(plci, ASSIGN, DSIG_ID);
9426                                                 add_p(plci, FTY, "\x02\xff\x06"); /* l1 down */
9427                                                 sig_req(plci, SIG_CTRL, 0);
9428                                                 send_req(plci);
9429                                         }
9430                                 }
9431                         }
9432                         if (a->AdvSignalAppl == this)
9433                         {
9434                                 this->NullCREnable = false;
9435                                 if (a->AdvCodecPLCI)
9436                                 {
9437                                         plci_remove(a->AdvCodecPLCI);
9438                                         a->AdvCodecPLCI->tel = 0;
9439                                         a->AdvCodecPLCI->adv_nl = 0;
9440                                 }
9441                                 a->AdvSignalAppl = NULL;
9442                                 a->AdvSignalPLCI = NULL;
9443                                 a->AdvCodecFLAG = 0;
9444                                 a->AdvCodecPLCI = NULL;
9445                         }
9446                 }
9447         }
9448
9449         this->Id = 0;
9450
9451         return GOOD;
9452 }
9453
9454 static word plci_remove_check(PLCI *plci)
9455 {
9456         if (!plci) return true;
9457         if (!plci->NL.Id && c_ind_mask_empty(plci))
9458         {
9459                 if (plci->Sig.Id == 0xff)
9460                         plci->Sig.Id = 0;
9461                 if (!plci->Sig.Id)
9462                 {
9463                         dbug(1, dprintf("plci_remove_complete(%x)", plci->Id));
9464                         dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci->tel, plci->Sig.Id));
9465                         if (plci->Id)
9466                         {
9467                                 CodecIdCheck(plci->adapter, plci);
9468                                 clear_b1_config(plci);
9469                                 ncci_remove(plci, 0, false);
9470                                 plci_free_msg_in_queue(plci);
9471                                 channel_flow_control_remove(plci);
9472                                 plci->Id = 0;
9473                                 plci->State = IDLE;
9474                                 plci->channels = 0;
9475                                 plci->appl = NULL;
9476                                 plci->notifiedcall = 0;
9477                         }
9478                         listen_check(plci->adapter);
9479                         return true;
9480                 }
9481         }
9482         return false;
9483 }
9484
9485
9486 /*------------------------------------------------------------------*/
9487
9488 static byte plci_nl_busy(PLCI *plci)
9489 {
9490         /* only applicable for non-multiplexed protocols */
9491         return (plci->nl_req
9492                 || (plci->ncci_ring_list
9493                     && plci->adapter->ncci_ch[plci->ncci_ring_list]
9494                     && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9495 }
9496
9497
9498 /*------------------------------------------------------------------*/
9499 /* DTMF facilities                                                  */
9500 /*------------------------------------------------------------------*/
9501
9502
9503 static struct
9504 {
9505         byte send_mask;
9506         byte listen_mask;
9507         byte character;
9508         byte code;
9509 } dtmf_digit_map[] =
9510 {
9511         { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9512         { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9513         { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9514         { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9515         { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9516         { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9517         { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9518         { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9519         { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9520         { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9521         { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9522         { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9523         { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9524         { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9525         { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9526         { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9527         { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9528         { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9529         { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9530         { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9531
9532         { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9533         { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9534         { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9535         { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9536         { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9537         { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9538         { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9539         { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9540         { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9541         { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9542         { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9543         { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9544         { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9545         { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9546         { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9547         { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9548         { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9549         { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9550         { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9551         { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9552         { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9553         { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9554         { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9555         { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9556         { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9557         { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9558         { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9559         { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9560         { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9561         { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9562         { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9563         { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9564         { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9565         { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9566         { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9567         { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9568         { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9569         { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9570         { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9571         { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9572         { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9573         { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9574         { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9575         { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9576         { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9577         { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9578         { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9579         { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9580         { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9581         { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9582         { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9583         { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9584
9585 };
9586
9587 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9588
9589
9590 static void dtmf_enable_receiver(PLCI *plci, byte enable_mask)
9591 {
9592         word min_digit_duration, min_gap_duration;
9593
9594         dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9595                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9596                         (char *)(FILE_), __LINE__, enable_mask));
9597
9598         if (enable_mask != 0)
9599         {
9600                 min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9601                 min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9602                 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9603                 PUT_WORD(&plci->internal_req_buffer[1], min_digit_duration);
9604                 PUT_WORD(&plci->internal_req_buffer[3], min_gap_duration);
9605                 plci->NData[0].PLength = 5;
9606
9607                 PUT_WORD(&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9608                 plci->NData[0].PLength += 2;
9609                 capidtmf_recv_enable(&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9610
9611         }
9612         else
9613         {
9614                 plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9615                 plci->NData[0].PLength = 1;
9616
9617                 capidtmf_recv_disable(&(plci->capidtmf_state));
9618
9619         }
9620         plci->NData[0].P = plci->internal_req_buffer;
9621         plci->NL.X = plci->NData;
9622         plci->NL.ReqCh = 0;
9623         plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9624         plci->adapter->request(&plci->NL);
9625 }
9626
9627
9628 static void dtmf_send_digits(PLCI *plci, byte *digit_buffer, word digit_count)
9629 {
9630         word w, i;
9631
9632         dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9633                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9634                         (char *)(FILE_), __LINE__, digit_count));
9635
9636         plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9637         w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9638         PUT_WORD(&plci->internal_req_buffer[1], w);
9639         w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9640         PUT_WORD(&plci->internal_req_buffer[3], w);
9641         for (i = 0; i < digit_count; i++)
9642         {
9643                 w = 0;
9644                 while ((w < DTMF_DIGIT_MAP_ENTRIES)
9645                        && (digit_buffer[i] != dtmf_digit_map[w].character))
9646                 {
9647                         w++;
9648                 }
9649                 plci->internal_req_buffer[5 + i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9650                         dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9651         }
9652         plci->NData[0].PLength = 5 + digit_count;
9653         plci->NData[0].P = plci->internal_req_buffer;
9654         plci->NL.X = plci->NData;
9655         plci->NL.ReqCh = 0;
9656         plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9657         plci->adapter->request(&plci->NL);
9658 }
9659
9660
9661 static void dtmf_rec_clear_config(PLCI *plci)
9662 {
9663
9664         dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9665                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9666                         (char *)(FILE_), __LINE__));
9667
9668         plci->dtmf_rec_active = 0;
9669         plci->dtmf_rec_pulse_ms = 0;
9670         plci->dtmf_rec_pause_ms = 0;
9671
9672         capidtmf_init(&(plci->capidtmf_state), plci->adapter->u_law);
9673
9674 }
9675
9676
9677 static void dtmf_send_clear_config(PLCI *plci)
9678 {
9679
9680         dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9681                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9682                         (char *)(FILE_), __LINE__));
9683
9684         plci->dtmf_send_requests = 0;
9685         plci->dtmf_send_pulse_ms = 0;
9686         plci->dtmf_send_pause_ms = 0;
9687 }
9688
9689
9690 static void dtmf_prepare_switch(dword Id, PLCI *plci)
9691 {
9692
9693         dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9694                         UnMapId(Id), (char *)(FILE_), __LINE__));
9695
9696         while (plci->dtmf_send_requests != 0)
9697                 dtmf_confirmation(Id, plci);
9698 }
9699
9700
9701 static word dtmf_save_config(dword Id, PLCI *plci, byte Rc)
9702 {
9703
9704         dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9705                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9706
9707         return (GOOD);
9708 }
9709
9710
9711 static word dtmf_restore_config(dword Id, PLCI *plci, byte Rc)
9712 {
9713         word Info;
9714
9715         dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9716                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9717
9718         Info = GOOD;
9719         if (plci->B1_facilities & B1_FACILITY_DTMFR)
9720         {
9721                 switch (plci->adjust_b_state)
9722                 {
9723                 case ADJUST_B_RESTORE_DTMF_1:
9724                         plci->internal_command = plci->adjust_b_command;
9725                         if (plci_nl_busy(plci))
9726                         {
9727                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9728                                 break;
9729                         }
9730                         dtmf_enable_receiver(plci, plci->dtmf_rec_active);
9731                         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9732                         break;
9733                 case ADJUST_B_RESTORE_DTMF_2:
9734                         if ((Rc != OK) && (Rc != OK_FC))
9735                         {
9736                                 dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9737                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9738                                 Info = _WRONG_STATE;
9739                                 break;
9740                         }
9741                         break;
9742                 }
9743         }
9744         return (Info);
9745 }
9746
9747
9748 static void dtmf_command(dword Id, PLCI *plci, byte Rc)
9749 {
9750         word internal_command, Info;
9751         byte mask;
9752         byte result[4];
9753
9754         dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9755                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9756                         plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9757                         plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9758
9759         Info = GOOD;
9760         result[0] = 2;
9761         PUT_WORD(&result[1], DTMF_SUCCESS);
9762         internal_command = plci->internal_command;
9763         plci->internal_command = 0;
9764         mask = 0x01;
9765         switch (plci->dtmf_cmd)
9766         {
9767
9768         case DTMF_LISTEN_TONE_START:
9769                 mask <<= 1;
9770         case DTMF_LISTEN_MF_START:
9771                 mask <<= 1;
9772
9773         case DTMF_LISTEN_START:
9774                 switch (internal_command)
9775                 {
9776                 default:
9777                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9778                                                                   B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9779                 case DTMF_COMMAND_1:
9780                         if (adjust_b_process(Id, plci, Rc) != GOOD)
9781                         {
9782                                 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9783                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9784                                 Info = _FACILITY_NOT_SUPPORTED;
9785                                 break;
9786                         }
9787                         if (plci->internal_command)
9788                                 return;
9789                 case DTMF_COMMAND_2:
9790                         if (plci_nl_busy(plci))
9791                         {
9792                                 plci->internal_command = DTMF_COMMAND_2;
9793                                 return;
9794                         }
9795                         plci->internal_command = DTMF_COMMAND_3;
9796                         dtmf_enable_receiver(plci, (byte)(plci->dtmf_rec_active | mask));
9797                         return;
9798                 case DTMF_COMMAND_3:
9799                         if ((Rc != OK) && (Rc != OK_FC))
9800                         {
9801                                 dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9802                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9803                                 Info = _FACILITY_NOT_SUPPORTED;
9804                                 break;
9805                         }
9806
9807                         plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9808
9809                         plci->dtmf_rec_active |= mask;
9810                         break;
9811                 }
9812                 break;
9813
9814
9815         case DTMF_LISTEN_TONE_STOP:
9816                 mask <<= 1;
9817         case DTMF_LISTEN_MF_STOP:
9818                 mask <<= 1;
9819
9820         case DTMF_LISTEN_STOP:
9821                 switch (internal_command)
9822                 {
9823                 default:
9824                         plci->dtmf_rec_active &= ~mask;
9825                         if (plci->dtmf_rec_active)
9826                                 break;
9827 /*
9828   case DTMF_COMMAND_1:
9829   if (plci->dtmf_rec_active)
9830   {
9831   if (plci_nl_busy (plci))
9832   {
9833   plci->internal_command = DTMF_COMMAND_1;
9834   return;
9835   }
9836   plci->dtmf_rec_active &= ~mask;
9837   plci->internal_command = DTMF_COMMAND_2;
9838   dtmf_enable_receiver (plci, false);
9839   return;
9840   }
9841   Rc = OK;
9842   case DTMF_COMMAND_2:
9843   if ((Rc != OK) && (Rc != OK_FC))
9844   {
9845   dbug (1, dprintf("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9846   UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9847   Info = _FACILITY_NOT_SUPPORTED;
9848   break;
9849   }
9850 */
9851                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
9852                                                                   ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9853                 case DTMF_COMMAND_3:
9854                         if (adjust_b_process(Id, plci, Rc) != GOOD)
9855                         {
9856                                 dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9857                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9858                                 Info = _FACILITY_NOT_SUPPORTED;
9859                                 break;
9860                         }
9861                         if (plci->internal_command)
9862                                 return;
9863                         break;
9864                 }
9865                 break;
9866
9867
9868         case DTMF_SEND_TONE:
9869                 mask <<= 1;
9870         case DTMF_SEND_MF:
9871                 mask <<= 1;
9872
9873         case DTMF_DIGITS_SEND:
9874                 switch (internal_command)
9875                 {
9876                 default:
9877                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9878                                                                   ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9879                                            DTMF_COMMAND_1);
9880                 case DTMF_COMMAND_1:
9881                         if (adjust_b_process(Id, plci, Rc) != GOOD)
9882                         {
9883                                 dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9884                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9885                                 Info = _FACILITY_NOT_SUPPORTED;
9886                                 break;
9887                         }
9888                         if (plci->internal_command)
9889                                 return;
9890                 case DTMF_COMMAND_2:
9891                         if (plci_nl_busy(plci))
9892                         {
9893                                 plci->internal_command = DTMF_COMMAND_2;
9894                                 return;
9895                         }
9896                         plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9897                         plci->internal_command = DTMF_COMMAND_3;
9898                         dtmf_send_digits(plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9899                         return;
9900                 case DTMF_COMMAND_3:
9901                         if ((Rc != OK) && (Rc != OK_FC))
9902                         {
9903                                 dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9904                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9905                                 if (plci->dtmf_send_requests != 0)
9906                                         (plci->dtmf_send_requests)--;
9907                                 Info = _FACILITY_NOT_SUPPORTED;
9908                                 break;
9909                         }
9910                         return;
9911                 }
9912                 break;
9913         }
9914         sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9915               "wws", Info, SELECTOR_DTMF, result);
9916 }
9917
9918
9919 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
9920 {
9921         word Info;
9922         word i, j;
9923         byte mask;
9924         API_PARSE dtmf_parms[5];
9925         byte result[40];
9926
9927         dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9928                         UnMapId(Id), (char *)(FILE_), __LINE__));
9929
9930         Info = GOOD;
9931         result[0] = 2;
9932         PUT_WORD(&result[1], DTMF_SUCCESS);
9933         if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9934         {
9935                 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9936                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9937                 Info = _FACILITY_NOT_SUPPORTED;
9938         }
9939         else if (api_parse(&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9940         {
9941                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9942                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9943                 Info = _WRONG_MESSAGE_FORMAT;
9944         }
9945
9946         else if ((GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9947                  || (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9948         {
9949                 if (!((a->requested_options_table[appl->Id - 1])
9950                       & (1L << PRIVATE_DTMF_TONE)))
9951                 {
9952                         dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9953                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9954                         PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9955                 }
9956                 else
9957                 {
9958                         for (i = 0; i < 32; i++)
9959                                 result[4 + i] = 0;
9960                         if (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9961                         {
9962                                 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9963                                 {
9964                                         if (dtmf_digit_map[i].listen_mask != 0)
9965                                                 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9966                                 }
9967                         }
9968                         else
9969                         {
9970                                 for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9971                                 {
9972                                         if (dtmf_digit_map[i].send_mask != 0)
9973                                                 result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9974                                 }
9975                         }
9976                         result[0] = 3 + 32;
9977                         result[3] = 32;
9978                 }
9979         }
9980
9981         else if (plci == NULL)
9982         {
9983                 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9984                                 UnMapId(Id), (char *)(FILE_), __LINE__));
9985                 Info = _WRONG_IDENTIFIER;
9986         }
9987         else
9988         {
9989                 if (!plci->State
9990                     || !plci->NL.Id || plci->nl_remove_id)
9991                 {
9992                         dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9993                                         UnMapId(Id), (char *)(FILE_), __LINE__));
9994                         Info = _WRONG_STATE;
9995                 }
9996                 else
9997                 {
9998                         plci->command = 0;
9999                         plci->dtmf_cmd = GET_WORD(dtmf_parms[0].info);
10000                         mask = 0x01;
10001                         switch (plci->dtmf_cmd)
10002                         {
10003
10004                         case DTMF_LISTEN_TONE_START:
10005                         case DTMF_LISTEN_TONE_STOP:
10006                                 mask <<= 1;
10007                         case DTMF_LISTEN_MF_START:
10008                         case DTMF_LISTEN_MF_STOP:
10009                                 mask <<= 1;
10010                                 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10011                                       & (1L << PRIVATE_DTMF_TONE)))
10012                                 {
10013                                         dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10014                                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10015                                         PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10016                                         break;
10017                                 }
10018
10019                         case DTMF_LISTEN_START:
10020                         case DTMF_LISTEN_STOP:
10021                                 if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10022                                     && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10023                                 {
10024                                         dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
10025                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
10026                                         Info = _FACILITY_NOT_SUPPORTED;
10027                                         break;
10028                                 }
10029                                 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10030                                 {
10031                                         if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10032                                         {
10033                                                 plci->dtmf_rec_pulse_ms = 0;
10034                                                 plci->dtmf_rec_pause_ms = 0;
10035                                         }
10036                                         else
10037                                         {
10038                                                 plci->dtmf_rec_pulse_ms = GET_WORD(dtmf_parms[1].info);
10039                                                 plci->dtmf_rec_pause_ms = GET_WORD(dtmf_parms[2].info);
10040                                         }
10041                                 }
10042                                 start_internal_command(Id, plci, dtmf_command);
10043                                 return (false);
10044
10045
10046                         case DTMF_SEND_TONE:
10047                                 mask <<= 1;
10048                         case DTMF_SEND_MF:
10049                                 mask <<= 1;
10050                                 if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10051                                       & (1L << PRIVATE_DTMF_TONE)))
10052                                 {
10053                                         dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10054                                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10055                                         PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10056                                         break;
10057                                 }
10058
10059                         case DTMF_DIGITS_SEND:
10060                                 if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10061                                 {
10062                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
10063                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
10064                                         Info = _WRONG_MESSAGE_FORMAT;
10065                                         break;
10066                                 }
10067                                 if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10068                                 {
10069                                         plci->dtmf_send_pulse_ms = GET_WORD(dtmf_parms[1].info);
10070                                         plci->dtmf_send_pause_ms = GET_WORD(dtmf_parms[2].info);
10071                                 }
10072                                 i = 0;
10073                                 j = 0;
10074                                 while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10075                                 {
10076                                         j = 0;
10077                                         while ((j < DTMF_DIGIT_MAP_ENTRIES)
10078                                                && ((dtmf_parms[3].info[i + 1] != dtmf_digit_map[j].character)
10079                                                    || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10080                                         {
10081                                                 j++;
10082                                         }
10083                                         i++;
10084                                 }
10085                                 if (j == DTMF_DIGIT_MAP_ENTRIES)
10086                                 {
10087                                         dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10088                                                         UnMapId(Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10089                                         PUT_WORD(&result[1], DTMF_INCORRECT_DIGIT);
10090                                         break;
10091                                 }
10092                                 if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10093                                 {
10094                                         dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
10095                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
10096                                         Info = _WRONG_STATE;
10097                                         break;
10098                                 }
10099                                 api_save_msg(dtmf_parms, "wwws", &plci->saved_msg);
10100                                 start_internal_command(Id, plci, dtmf_command);
10101                                 return (false);
10102
10103                         default:
10104                                 dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10105                                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10106                                 PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10107                         }
10108                 }
10109         }
10110         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10111               "wws", Info, SELECTOR_DTMF, result);
10112         return (false);
10113 }
10114
10115
10116 static void dtmf_confirmation(dword Id, PLCI *plci)
10117 {
10118         word i;
10119         byte result[4];
10120
10121         dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
10122                         UnMapId(Id), (char *)(FILE_), __LINE__));
10123
10124         result[0] = 2;
10125         PUT_WORD(&result[1], DTMF_SUCCESS);
10126         if (plci->dtmf_send_requests != 0)
10127         {
10128                 sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10129                       "wws", GOOD, SELECTOR_DTMF, result);
10130                 (plci->dtmf_send_requests)--;
10131                 for (i = 0; i < plci->dtmf_send_requests; i++)
10132                         plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i + 1];
10133         }
10134 }
10135
10136
10137 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length)
10138 {
10139         word i, j, n;
10140
10141         dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10142                         UnMapId(Id), (char *)(FILE_), __LINE__));
10143
10144         n = 0;
10145         for (i = 1; i < length; i++)
10146         {
10147                 j = 0;
10148                 while ((j < DTMF_DIGIT_MAP_ENTRIES)
10149                        && ((msg[i] != dtmf_digit_map[j].code)
10150                            || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10151                 {
10152                         j++;
10153                 }
10154                 if (j < DTMF_DIGIT_MAP_ENTRIES)
10155                 {
10156
10157                         if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10158                             && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10159                             && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10160                         {
10161                                 if (n + 1 == i)
10162                                 {
10163                                         for (i = length; i > n + 1; i--)
10164                                                 msg[i] = msg[i - 1];
10165                                         length++;
10166                                         i++;
10167                                 }
10168                                 msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10169                         }
10170                         plci->tone_last_indication_code = dtmf_digit_map[j].character;
10171
10172                         msg[++n] = dtmf_digit_map[j].character;
10173                 }
10174         }
10175         if (n != 0)
10176         {
10177                 msg[0] = (byte) n;
10178                 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10179         }
10180 }
10181
10182
10183 /*------------------------------------------------------------------*/
10184 /* DTMF parameters                                                  */
10185 /*------------------------------------------------------------------*/
10186
10187 static void dtmf_parameter_write(PLCI *plci)
10188 {
10189         word i;
10190         byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10191
10192         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10193                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10194                         (char *)(FILE_), __LINE__));
10195
10196         parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10197         parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10198         for (i = 0; i < plci->dtmf_parameter_length; i++)
10199                 parameter_buffer[2 + i] = plci->dtmf_parameter_buffer[i];
10200         add_p(plci, FTY, parameter_buffer);
10201         sig_req(plci, TEL_CTRL, 0);
10202         send_req(plci);
10203 }
10204
10205
10206 static void dtmf_parameter_clear_config(PLCI *plci)
10207 {
10208
10209         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10210                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10211                         (char *)(FILE_), __LINE__));
10212
10213         plci->dtmf_parameter_length = 0;
10214 }
10215
10216
10217 static void dtmf_parameter_prepare_switch(dword Id, PLCI *plci)
10218 {
10219
10220         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10221                         UnMapId(Id), (char *)(FILE_), __LINE__));
10222
10223 }
10224
10225
10226 static word dtmf_parameter_save_config(dword Id, PLCI *plci, byte Rc)
10227 {
10228
10229         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10230                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10231
10232         return (GOOD);
10233 }
10234
10235
10236 static word dtmf_parameter_restore_config(dword Id, PLCI *plci, byte Rc)
10237 {
10238         word Info;
10239
10240         dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10241                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10242
10243         Info = GOOD;
10244         if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10245             && (plci->dtmf_parameter_length != 0))
10246         {
10247                 switch (plci->adjust_b_state)
10248                 {
10249                 case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10250                         plci->internal_command = plci->adjust_b_command;
10251                         if (plci->sig_req)
10252                         {
10253                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10254                                 break;
10255                         }
10256                         dtmf_parameter_write(plci);
10257                         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10258                         break;
10259                 case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10260                         if ((Rc != OK) && (Rc != OK_FC))
10261                         {
10262                                 dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10263                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10264                                 Info = _WRONG_STATE;
10265                                 break;
10266                         }
10267                         break;
10268                 }
10269         }
10270         return (Info);
10271 }
10272
10273
10274 /*------------------------------------------------------------------*/
10275 /* Line interconnect facilities                                     */
10276 /*------------------------------------------------------------------*/
10277
10278
10279 LI_CONFIG   *li_config_table;
10280 word li_total_channels;
10281
10282
10283 /*------------------------------------------------------------------*/
10284 /* translate a CHI information element to a channel number          */
10285 /* returns 0xff - any channel                                       */
10286 /*         0xfe - chi wrong coding                                  */
10287 /*         0xfd - D-channel                                         */
10288 /*         0x00 - no channel                                        */
10289 /*         else channel number / PRI: timeslot                      */
10290 /* if channels is provided we accept more than one channel.         */
10291 /*------------------------------------------------------------------*/
10292
10293 static byte chi_to_channel(byte *chi, dword *pchannelmap)
10294 {
10295         int p;
10296         int i;
10297         dword map;
10298         byte excl;
10299         byte ofs;
10300         byte ch;
10301
10302         if (pchannelmap) *pchannelmap = 0;
10303         if (!chi[0]) return 0xff;
10304         excl = 0;
10305
10306         if (chi[1] & 0x20) {
10307                 if (chi[0] == 1 && chi[1] == 0xac) return 0xfd; /* exclusive d-channel */
10308                 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10309                 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10310                 if ((chi[1] | 0xc8) != 0xe9) return 0xfe;
10311                 if (chi[1] & 0x08) excl = 0x40;
10312
10313                 /* int. id present */
10314                 if (chi[1] & 0x40) {
10315                         p = i + 1;
10316                         for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10317                         if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10318                 }
10319
10320                 /* coding standard, Number/Map, Channel Type */
10321                 p = i + 1;
10322                 for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10323                 if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10324                 if ((chi[p] | 0xd0) != 0xd3) return 0xfe;
10325
10326                 /* Number/Map */
10327                 if (chi[p] & 0x10) {
10328
10329                         /* map */
10330                         if ((chi[0] - p) == 4) ofs = 0;
10331                         else if ((chi[0] - p) == 3) ofs = 1;
10332                         else return 0xfe;
10333                         ch = 0;
10334                         map = 0;
10335                         for (i = 0; i < 4 && p < chi[0]; i++) {
10336                                 p++;
10337                                 ch += 8;
10338                                 map <<= 8;
10339                                 if (chi[p]) {
10340                                         for (ch = 0; !(chi[p] & (1 << ch)); ch++);
10341                                         map |= chi[p];
10342                                 }
10343                         }
10344                         ch += ofs;
10345                         map <<= ofs;
10346                 }
10347                 else {
10348
10349                         /* number */
10350                         p = i + 1;
10351                         ch = chi[p] & 0x3f;
10352                         if (pchannelmap) {
10353                                 if ((byte)(chi[0] - p) > 30) return 0xfe;
10354                                 map = 0;
10355                                 for (i = p; i <= chi[0]; i++) {
10356                                         if ((chi[i] & 0x7f) > 31) return 0xfe;
10357                                         map |= (1L << (chi[i] & 0x7f));
10358                                 }
10359                         }
10360                         else {
10361                                 if (p != chi[0]) return 0xfe;
10362                                 if (ch > 31) return 0xfe;
10363                                 map = (1L << ch);
10364                         }
10365                         if (chi[p] & 0x40) return 0xfe;
10366                 }
10367                 if (pchannelmap) *pchannelmap = map;
10368                 else if (map != ((dword)(1L << ch))) return 0xfe;
10369                 return (byte)(excl | ch);
10370         }
10371         else {  /* not PRI */
10372                 for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10373                 if (i != chi[0] || !(chi[i] & 0x80)) return 0xfe;
10374                 if (chi[1] & 0x08) excl = 0x40;
10375
10376                 switch (chi[1] | 0x98) {
10377                 case 0x98: return 0;
10378                 case 0x99:
10379                         if (pchannelmap) *pchannelmap = 2;
10380                         return excl | 1;
10381                 case 0x9a:
10382                         if (pchannelmap) *pchannelmap = 4;
10383                         return excl | 2;
10384                 case 0x9b: return 0xff;
10385                 case 0x9c: return 0xfd; /* d-ch */
10386                 default: return 0xfe;
10387                 }
10388         }
10389 }
10390
10391
10392 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id)
10393 {
10394         DIVA_CAPI_ADAPTER *a;
10395         PLCI *splci;
10396         byte old_id;
10397
10398         a = plci->adapter;
10399         old_id = plci->li_bchannel_id;
10400         if (a->li_pri)
10401         {
10402                 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10403                         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10404                 plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10405                 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10406                         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10407         }
10408         else
10409         {
10410                 if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10411                 {
10412                         if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10413                                 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10414                         plci->li_bchannel_id = bchannel_id & 0x03;
10415                         if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10416                         {
10417                                 splci = a->AdvSignalPLCI;
10418                                 if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10419                                 {
10420                                         if ((splci->li_bchannel_id != 0)
10421                                             && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10422                                         {
10423                                                 li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10424                                         }
10425                                         splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10426                                         li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10427                                         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10428                                                         (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10429                                                         (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10430                                 }
10431                         }
10432                         if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10433                                 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10434                 }
10435         }
10436         if ((old_id == 0) && (plci->li_bchannel_id != 0)
10437             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10438         {
10439                 mixer_clear_config(plci);
10440         }
10441         dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10442                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10443                         (char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10444 }
10445
10446
10447 static void mixer_set_bchannel_id(PLCI *plci, byte *chi)
10448 {
10449         DIVA_CAPI_ADAPTER *a;
10450         PLCI *splci;
10451         byte ch, old_id;
10452
10453         a = plci->adapter;
10454         old_id = plci->li_bchannel_id;
10455         ch = chi_to_channel(chi, NULL);
10456         if (!(ch & 0x80))
10457         {
10458                 if (a->li_pri)
10459                 {
10460                         if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10461                                 li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10462                         plci->li_bchannel_id = (ch & 0x1f) + 1;
10463                         if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10464                                 li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10465                 }
10466                 else
10467                 {
10468                         if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10469                         {
10470                                 if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10471                                         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10472                                 plci->li_bchannel_id = ch & 0x1f;
10473                                 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10474                                 {
10475                                         splci = a->AdvSignalPLCI;
10476                                         if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10477                                         {
10478                                                 if ((splci->li_bchannel_id != 0)
10479                                                     && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10480                                                 {
10481                                                         li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10482                                                 }
10483                                                 splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10484                                                 li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10485                                                 dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10486                                                                 (dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10487                                                                 (char *)(FILE_), __LINE__, splci->li_bchannel_id));
10488                                         }
10489                                 }
10490                                 if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10491                                         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10492                         }
10493                 }
10494         }
10495         if ((old_id == 0) && (plci->li_bchannel_id != 0)
10496             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10497         {
10498                 mixer_clear_config(plci);
10499         }
10500         dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10501                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10502                         (char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10503 }
10504
10505
10506 #define MIXER_MAX_DUMP_CHANNELS 34
10507
10508 static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER *a)
10509 {
10510         static char hex_digit_table[0x10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
10511         word n, i, j;
10512         char *p;
10513         char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10514
10515         dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10516                         (dword)(UnMapController(a->Id)), (char *)(FILE_), __LINE__));
10517
10518         for (i = 0; i < li_total_channels; i++)
10519         {
10520                 li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10521                 if (li_config_table[i].chflags != 0)
10522                         li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10523                 else
10524                 {
10525                         for (j = 0; j < li_total_channels; j++)
10526                         {
10527                                 if (((li_config_table[i].flag_table[j]) != 0)
10528                                     || ((li_config_table[j].flag_table[i]) != 0))
10529                                 {
10530                                         li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10531                                 }
10532                                 if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10533                                     || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10534                                 {
10535                                         li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10536                                 }
10537                         }
10538                 }
10539         }
10540         for (i = 0; i < li_total_channels; i++)
10541         {
10542                 for (j = 0; j < li_total_channels; j++)
10543                 {
10544                         li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10545                         if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10546                                 li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10547                 }
10548         }
10549         for (n = 0; n < li_total_channels; n++)
10550         {
10551                 if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10552                 {
10553                         for (i = 0; i < li_total_channels; i++)
10554                         {
10555                                 if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10556                                 {
10557                                         for (j = 0; j < li_total_channels; j++)
10558                                         {
10559                                                 li_config_table[i].coef_table[j] |=
10560                                                         li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10561                                         }
10562                                 }
10563                         }
10564                 }
10565         }
10566         for (i = 0; i < li_total_channels; i++)
10567         {
10568                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10569                 {
10570                         li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10571                         for (j = 0; j < li_total_channels; j++)
10572                         {
10573                                 if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10574                                         li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10575                         }
10576                         if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10577                                 li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10578                 }
10579         }
10580         for (i = 0; i < li_total_channels; i++)
10581         {
10582                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10583                 {
10584                         for (j = 0; j < li_total_channels; j++)
10585                         {
10586                                 if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10587                                         li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10588                                 if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10589                                         li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10590                                 if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10591                                         li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10592                                 if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10593                                         li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10594                         }
10595                         if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10596                         {
10597                                 for (j = 0; j < li_total_channels; j++)
10598                                 {
10599                                         if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10600                                         {
10601                                                 li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10602                                                 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10603                                                         li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10604                                         }
10605                                 }
10606                         }
10607                         if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10608                         {
10609                                 for (j = 0; j < li_total_channels; j++)
10610                                 {
10611                                         if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10612                                                 li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10613                                 }
10614                         }
10615                         if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10616                         {
10617                                 for (j = 0; j < li_total_channels; j++)
10618                                 {
10619                                         if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10620                                         {
10621                                                 for (n = 0; n < li_total_channels; n++)
10622                                                 {
10623                                                         if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10624                                                         {
10625                                                                 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10626                                                                 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10627                                                                 {
10628                                                                         li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10629                                                                         if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10630                                                                                 li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10631                                                                 }
10632                                                                 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10633                                                                         li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10634                                                         }
10635                                                 }
10636                                         }
10637                                 }
10638                         }
10639                 }
10640         }
10641         for (i = 0; i < li_total_channels; i++)
10642         {
10643                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10644                 {
10645                         if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10646                                 li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10647                         if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10648                                 li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10649                         if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10650                                 li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10651                         for (j = 0; j < li_total_channels; j++)
10652                         {
10653                                 if ((li_config_table[i].flag_table[j] &
10654                                      (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10655                                     || (li_config_table[j].flag_table[i] &
10656                                         (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10657                                 {
10658                                         li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10659                                 }
10660                                 if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10661                                         li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10662                                 if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10663                                         li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10664                         }
10665                         if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10666                         {
10667                                 li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10668                                 li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10669                         }
10670                 }
10671         }
10672         for (i = 0; i < li_total_channels; i++)
10673         {
10674                 if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10675                 {
10676                         j = 0;
10677                         while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10678                                 j++;
10679                         if (j < li_total_channels)
10680                         {
10681                                 for (j = 0; j < li_total_channels; j++)
10682                                 {
10683                                         li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10684                                         if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10685                                                 li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10686                                 }
10687                         }
10688                 }
10689         }
10690         n = li_total_channels;
10691         if (n > MIXER_MAX_DUMP_CHANNELS)
10692                 n = MIXER_MAX_DUMP_CHANNELS;
10693         p = hex_line;
10694         for (j = 0; j < n; j++)
10695         {
10696                 if ((j & 0x7) == 0)
10697                         *(p++) = ' ';
10698                 *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10699                 *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10700         }
10701         *p = '\0';
10702         dbug(1, dprintf("[%06lx] CURRENT %s",
10703                         (dword)(UnMapController(a->Id)), (char *)hex_line));
10704         p = hex_line;
10705         for (j = 0; j < n; j++)
10706         {
10707                 if ((j & 0x7) == 0)
10708                         *(p++) = ' ';
10709                 *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10710                 *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10711         }
10712         *p = '\0';
10713         dbug(1, dprintf("[%06lx] CHANNEL %s",
10714                         (dword)(UnMapController(a->Id)), (char *)hex_line));
10715         p = hex_line;
10716         for (j = 0; j < n; j++)
10717         {
10718                 if ((j & 0x7) == 0)
10719                         *(p++) = ' ';
10720                 *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10721                 *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10722         }
10723         *p = '\0';
10724         dbug(1, dprintf("[%06lx] CHFLAG  %s",
10725                         (dword)(UnMapController(a->Id)), (char *)hex_line));
10726         for (i = 0; i < n; i++)
10727         {
10728                 p = hex_line;
10729                 for (j = 0; j < n; j++)
10730                 {
10731                         if ((j & 0x7) == 0)
10732                                 *(p++) = ' ';
10733                         *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10734                         *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10735                 }
10736                 *p = '\0';
10737                 dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10738                                 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10739         }
10740         for (i = 0; i < n; i++)
10741         {
10742                 p = hex_line;
10743                 for (j = 0; j < n; j++)
10744                 {
10745                         if ((j & 0x7) == 0)
10746                                 *(p++) = ' ';
10747                         *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10748                         *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10749                 }
10750                 *p = '\0';
10751                 dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10752                                 (dword)(UnMapController(a->Id)), i, (char *)hex_line));
10753         }
10754 }
10755
10756
10757 static struct
10758 {
10759         byte mask;
10760         byte line_flags;
10761 } mixer_write_prog_pri[] =
10762 {
10763         { LI_COEF_CH_CH, 0 },
10764         { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10765         { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10766         { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10767 };
10768
10769 static struct
10770 {
10771         byte from_ch;
10772         byte to_ch;
10773         byte mask;
10774         byte xconnect_override;
10775 } mixer_write_prog_bri[] =
10776 {
10777         { 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10778         { 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10779         { 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10780         { 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10781         { 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10782         { 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10783         { 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10784         { 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10785         { 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10786         { 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10787         { 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10788         { 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10789         { 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10790         { 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10791         { 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10792         { 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10793         { 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10794         { 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10795         { 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10796         { 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10797         { 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10798         { 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10799         { 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10800         { 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10801         { 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10802         { 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10803         { 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10804         { 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10805         { 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10806         { 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10807         { 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10808         { 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10809         { 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10810         { 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10811         { 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10812         { 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10813 };
10814
10815 static byte mixer_swapped_index_bri[] =
10816 {
10817         18,  /* B      to B      */
10818         19,  /* Alt B  to B      */
10819         20,  /* PC     to B      */
10820         21,  /* Alt PC to B      */
10821         22,  /* IC     to B      */
10822         23,  /* Alt IC to B      */
10823         24,  /* B      to PC     */
10824         25,  /* Alt B  to PC     */
10825         26,  /* PC     to PC     */
10826         27,  /* Alt PC to PC     */
10827         28,  /* IC     to PC     */
10828         29,  /* Alt IC to PC     */
10829         30,  /* B      to IC     */
10830         31,  /* Alt B  to IC     */
10831         32,  /* PC     to IC     */
10832         33,  /* Alt PC to IC     */
10833         34,  /* IC     to IC     */
10834         35,  /* Alt IC to IC     */
10835         0,   /* Alt B  to Alt B  */
10836         1,   /* B      to Alt B  */
10837         2,   /* Alt PC to Alt B  */
10838         3,   /* PC     to Alt B  */
10839         4,   /* Alt IC to Alt B  */
10840         5,   /* IC     to Alt B  */
10841         6,   /* Alt B  to Alt PC */
10842         7,   /* B      to Alt PC */
10843         8,   /* Alt PC to Alt PC */
10844         9,   /* PC     to Alt PC */
10845         10,  /* Alt IC to Alt PC */
10846         11,  /* IC     to Alt PC */
10847         12,  /* Alt B  to Alt IC */
10848         13,  /* B      to Alt IC */
10849         14,  /* Alt PC to Alt IC */
10850         15,  /* PC     to Alt IC */
10851         16,  /* Alt IC to Alt IC */
10852         17   /* IC     to Alt IC */
10853 };
10854
10855 static struct
10856 {
10857         byte mask;
10858         byte from_pc;
10859         byte to_pc;
10860 } xconnect_write_prog[] =
10861 {
10862         { LI_COEF_CH_CH, false, false },
10863         { LI_COEF_CH_PC, false, true },
10864         { LI_COEF_PC_CH, true, false },
10865         { LI_COEF_PC_PC, true, true }
10866 };
10867
10868
10869 static void xconnect_query_addresses(PLCI *plci)
10870 {
10871         DIVA_CAPI_ADAPTER *a;
10872         word w, ch;
10873         byte *p;
10874
10875         dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10876                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10877                         (char *)(FILE_), __LINE__));
10878
10879         a = plci->adapter;
10880         if (a->li_pri && ((plci->li_bchannel_id == 0)
10881                           || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10882         {
10883                 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10884                                 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10885                                 (char *)(FILE_), __LINE__));
10886                 return;
10887         }
10888         p = plci->internal_req_buffer;
10889         ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10890         *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10891         w = ch;
10892         *(p++) = (byte) w;
10893         *(p++) = (byte)(w >> 8);
10894         w = ch | XCONNECT_CHANNEL_PORT_PC;
10895         *(p++) = (byte) w;
10896         *(p++) = (byte)(w >> 8);
10897         plci->NData[0].P = plci->internal_req_buffer;
10898         plci->NData[0].PLength = p - plci->internal_req_buffer;
10899         plci->NL.X = plci->NData;
10900         plci->NL.ReqCh = 0;
10901         plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10902         plci->adapter->request(&plci->NL);
10903 }
10904
10905
10906 static void xconnect_write_coefs(PLCI *plci, word internal_command)
10907 {
10908
10909         dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10910                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10911                         (char *)(FILE_), __LINE__, internal_command));
10912
10913         plci->li_write_command = internal_command;
10914         plci->li_write_channel = 0;
10915 }
10916
10917
10918 static byte xconnect_write_coefs_process(dword Id, PLCI *plci, byte Rc)
10919 {
10920         DIVA_CAPI_ADAPTER *a;
10921         word w, n, i, j, r, s, to_ch;
10922         dword d;
10923         byte *p;
10924         struct xconnect_transfer_address_s   *transfer_address;
10925         byte ch_map[MIXER_CHANNELS_BRI];
10926
10927         dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10928                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10929
10930         a = plci->adapter;
10931         if ((plci->li_bchannel_id == 0)
10932             || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10933         {
10934                 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10935                                 UnMapId(Id), (char *)(FILE_), __LINE__));
10936                 return (true);
10937         }
10938         i = a->li_base + (plci->li_bchannel_id - 1);
10939         j = plci->li_write_channel;
10940         p = plci->internal_req_buffer;
10941         if (j != 0)
10942         {
10943                 if ((Rc != OK) && (Rc != OK_FC))
10944                 {
10945                         dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10946                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10947                         return (false);
10948                 }
10949         }
10950         if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10951         {
10952                 r = 0;
10953                 s = 0;
10954                 if (j < li_total_channels)
10955                 {
10956                         if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10957                         {
10958                                 s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10959                                      (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10960                                         ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10961                                          (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10962                         }
10963                         r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10964                         while ((j < li_total_channels)
10965                                && ((r == 0)
10966                                    || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10967                                    || (!li_config_table[j].adapter->li_pri
10968                                        && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10969                                    || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10970                                         || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10971                                        && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10972                                            || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10973                                    || ((li_config_table[j].adapter->li_base != a->li_base)
10974                                        && !(r & s &
10975                                             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10976                                              (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10977                                             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10978                                              (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10979                         {
10980                                 j++;
10981                                 if (j < li_total_channels)
10982                                         r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10983                         }
10984                 }
10985                 if (j < li_total_channels)
10986                 {
10987                         plci->internal_command = plci->li_write_command;
10988                         if (plci_nl_busy(plci))
10989                                 return (true);
10990                         to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10991                         *(p++) = UDATA_REQUEST_XCONNECT_TO;
10992                         do
10993                         {
10994                                 if (li_config_table[j].adapter->li_base != a->li_base)
10995                                 {
10996                                         r &= s &
10997                                                 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10998                                                  (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10999                                                 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11000                                                  (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
11001                                 }
11002                                 n = 0;
11003                                 do
11004                                 {
11005                                         if (r & xconnect_write_prog[n].mask)
11006                                         {
11007                                                 if (xconnect_write_prog[n].from_pc)
11008                                                         transfer_address = &(li_config_table[j].send_pc);
11009                                                 else
11010                                                         transfer_address = &(li_config_table[j].send_b);
11011                                                 d = transfer_address->card_address.low;
11012                                                 *(p++) = (byte) d;
11013                                                 *(p++) = (byte)(d >> 8);
11014                                                 *(p++) = (byte)(d >> 16);
11015                                                 *(p++) = (byte)(d >> 24);
11016                                                 d = transfer_address->card_address.high;
11017                                                 *(p++) = (byte) d;
11018                                                 *(p++) = (byte)(d >> 8);
11019                                                 *(p++) = (byte)(d >> 16);
11020                                                 *(p++) = (byte)(d >> 24);
11021                                                 d = transfer_address->offset;
11022                                                 *(p++) = (byte) d;
11023                                                 *(p++) = (byte)(d >> 8);
11024                                                 *(p++) = (byte)(d >> 16);
11025                                                 *(p++) = (byte)(d >> 24);
11026                                                 w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11027                                                 *(p++) = (byte) w;
11028                                                 *(p++) = (byte)(w >> 8);
11029                                                 w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11030                                                         (li_config_table[i].adapter->u_law ?
11031                                                          (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11032                                                          (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11033                                                 *(p++) = (byte) w;
11034                                                 *(p++) = (byte) 0;
11035                                                 li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11036                                         }
11037                                         n++;
11038                                 } while ((n < ARRAY_SIZE(xconnect_write_prog))
11039                                          && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11040                                 if (n == ARRAY_SIZE(xconnect_write_prog))
11041                                 {
11042                                         do
11043                                         {
11044                                                 j++;
11045                                                 if (j < li_total_channels)
11046                                                         r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11047                                         } while ((j < li_total_channels)
11048                                                  && ((r == 0)
11049                                                      || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11050                                                      || (!li_config_table[j].adapter->li_pri
11051                                                          && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11052                                                      || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11053                                                           || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11054                                                          && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11055                                                              || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11056                                                      || ((li_config_table[j].adapter->li_base != a->li_base)
11057                                                          && !(r & s &
11058                                                               ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11059                                                                (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11060                                                               ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11061                                                                (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11062                                 }
11063                         } while ((j < li_total_channels)
11064                                  && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11065                 }
11066                 else if (j == li_total_channels)
11067                 {
11068                         plci->internal_command = plci->li_write_command;
11069                         if (plci_nl_busy(plci))
11070                                 return (true);
11071                         if (a->li_pri)
11072                         {
11073                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11074                                 w = 0;
11075                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11076                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
11077                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11078                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
11079                                 *(p++) = (byte) w;
11080                                 *(p++) = (byte)(w >> 8);
11081                         }
11082                         else
11083                         {
11084                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11085                                 w = 0;
11086                                 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11087                                     && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11088                                 {
11089                                         w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11090                                 }
11091                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11092                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
11093                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11094                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
11095                                 *(p++) = (byte) w;
11096                                 *(p++) = (byte)(w >> 8);
11097                                 for (j = 0; j < sizeof(ch_map); j += 2)
11098                                 {
11099                                         if (plci->li_bchannel_id == 2)
11100                                         {
11101                                                 ch_map[j] = (byte)(j + 1);
11102                                                 ch_map[j + 1] = (byte) j;
11103                                         }
11104                                         else
11105                                         {
11106                                                 ch_map[j] = (byte) j;
11107                                                 ch_map[j + 1] = (byte)(j + 1);
11108                                         }
11109                                 }
11110                                 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11111                                 {
11112                                         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11113                                         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11114                                         if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11115                                         {
11116                                                 *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11117                                                         mixer_write_prog_bri[n].xconnect_override :
11118                                                         ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11119                                                 if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11120                                                 {
11121                                                         w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11122                                                         li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11123                                                 }
11124                                         }
11125                                         else
11126                                         {
11127                                                 *p = 0x00;
11128                                                 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11129                                                 {
11130                                                         w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11131                                                         if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11132                                                                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11133                                                 }
11134                                         }
11135                                         p++;
11136                                 }
11137                         }
11138                         j = li_total_channels + 1;
11139                 }
11140         }
11141         else
11142         {
11143                 if (j <= li_total_channels)
11144                 {
11145                         plci->internal_command = plci->li_write_command;
11146                         if (plci_nl_busy(plci))
11147                                 return (true);
11148                         if (j < a->li_base)
11149                                 j = a->li_base;
11150                         if (a->li_pri)
11151                         {
11152                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11153                                 w = 0;
11154                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11155                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
11156                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11157                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
11158                                 *(p++) = (byte) w;
11159                                 *(p++) = (byte)(w >> 8);
11160                                 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11161                                 {
11162                                         *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11163                                         for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11164                                         {
11165                                                 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11166                                                 if (w & mixer_write_prog_pri[n].mask)
11167                                                 {
11168                                                         *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11169                                                         li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11170                                                 }
11171                                                 else
11172                                                         *(p++) = 0x00;
11173                                         }
11174                                         *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11175                                         for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11176                                         {
11177                                                 w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11178                                                 if (w & mixer_write_prog_pri[n].mask)
11179                                                 {
11180                                                         *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11181                                                         li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11182                                                 }
11183                                                 else
11184                                                         *(p++) = 0x00;
11185                                         }
11186                                 }
11187                         }
11188                         else
11189                         {
11190                                 *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11191                                 w = 0;
11192                                 if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11193                                     && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11194                                 {
11195                                         w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11196                                 }
11197                                 if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11198                                         w |= MIXER_FEATURE_ENABLE_TX_DATA;
11199                                 if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11200                                         w |= MIXER_FEATURE_ENABLE_RX_DATA;
11201                                 *(p++) = (byte) w;
11202                                 *(p++) = (byte)(w >> 8);
11203                                 for (j = 0; j < sizeof(ch_map); j += 2)
11204                                 {
11205                                         if (plci->li_bchannel_id == 2)
11206                                         {
11207                                                 ch_map[j] = (byte)(j + 1);
11208                                                 ch_map[j + 1] = (byte) j;
11209                                         }
11210                                         else
11211                                         {
11212                                                 ch_map[j] = (byte) j;
11213                                                 ch_map[j + 1] = (byte)(j + 1);
11214                                         }
11215                                 }
11216                                 for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11217                                 {
11218                                         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11219                                         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11220                                         if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11221                                         {
11222                                                 *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11223                                                 w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11224                                                 li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11225                                         }
11226                                         else
11227                                         {
11228                                                 *p = 0x00;
11229                                                 if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11230                                                 {
11231                                                         w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11232                                                         if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11233                                                                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11234                                                 }
11235                                         }
11236                                         p++;
11237                                 }
11238                         }
11239                         j = li_total_channels + 1;
11240                 }
11241         }
11242         plci->li_write_channel = j;
11243         if (p != plci->internal_req_buffer)
11244         {
11245                 plci->NData[0].P = plci->internal_req_buffer;
11246                 plci->NData[0].PLength = p - plci->internal_req_buffer;
11247                 plci->NL.X = plci->NData;
11248                 plci->NL.ReqCh = 0;
11249                 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11250                 plci->adapter->request(&plci->NL);
11251         }
11252         return (true);
11253 }
11254
11255
11256 static void mixer_notify_update(PLCI *plci, byte others)
11257 {
11258         DIVA_CAPI_ADAPTER *a;
11259         word i, w;
11260         PLCI *notify_plci;
11261         byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11262
11263         dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11264                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11265                         (char *)(FILE_), __LINE__, others));
11266
11267         a = plci->adapter;
11268         if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11269         {
11270                 if (others)
11271                         plci->li_notify_update = true;
11272                 i = 0;
11273                 do
11274                 {
11275                         notify_plci = NULL;
11276                         if (others)
11277                         {
11278                                 while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11279                                         i++;
11280                                 if (i < li_total_channels)
11281                                         notify_plci = li_config_table[i++].plci;
11282                         }
11283                         else
11284                         {
11285                                 if ((plci->li_bchannel_id != 0)
11286                                     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11287                                 {
11288                                         notify_plci = plci;
11289                                 }
11290                         }
11291                         if ((notify_plci != NULL)
11292                             && !notify_plci->li_notify_update
11293                             && (notify_plci->appl != NULL)
11294                             && (notify_plci->State)
11295                             && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11296                         {
11297                                 notify_plci->li_notify_update = true;
11298                                 ((CAPI_MSG *) msg)->header.length = 18;
11299                                 ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11300                                 ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11301                                 ((CAPI_MSG *) msg)->header.number = 0;
11302                                 ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11303                                 ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11304                                 ((CAPI_MSG *) msg)->header.ncci = 0;
11305                                 ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11306                                 ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11307                                 ((CAPI_MSG *) msg)->info.facility_req.structs[1] = LI_REQ_SILENT_UPDATE & 0xff;
11308                                 ((CAPI_MSG *) msg)->info.facility_req.structs[2] = LI_REQ_SILENT_UPDATE >> 8;
11309                                 ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11310                                 w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11311                                 if (w != _QUEUE_FULL)
11312                                 {
11313                                         if (w != 0)
11314                                         {
11315                                                 dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11316                                                                 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11317                                                                 (char *)(FILE_), __LINE__,
11318                                                                 (dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11319                                         }
11320                                         notify_plci->li_notify_update = false;
11321                                 }
11322                         }
11323                 } while (others && (notify_plci != NULL));
11324                 if (others)
11325                         plci->li_notify_update = false;
11326         }
11327 }
11328
11329
11330 static void mixer_clear_config(PLCI *plci)
11331 {
11332         DIVA_CAPI_ADAPTER *a;
11333         word i, j;
11334
11335         dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11336                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11337                         (char *)(FILE_), __LINE__));
11338
11339         plci->li_notify_update = false;
11340         plci->li_plci_b_write_pos = 0;
11341         plci->li_plci_b_read_pos = 0;
11342         plci->li_plci_b_req_pos = 0;
11343         a = plci->adapter;
11344         if ((plci->li_bchannel_id != 0)
11345             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11346         {
11347                 i = a->li_base + (plci->li_bchannel_id - 1);
11348                 li_config_table[i].curchnl = 0;
11349                 li_config_table[i].channel = 0;
11350                 li_config_table[i].chflags = 0;
11351                 for (j = 0; j < li_total_channels; j++)
11352                 {
11353                         li_config_table[j].flag_table[i] = 0;
11354                         li_config_table[i].flag_table[j] = 0;
11355                         li_config_table[i].coef_table[j] = 0;
11356                         li_config_table[j].coef_table[i] = 0;
11357                 }
11358                 if (!a->li_pri)
11359                 {
11360                         li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11361                         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11362                         {
11363                                 i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11364                                 li_config_table[i].curchnl = 0;
11365                                 li_config_table[i].channel = 0;
11366                                 li_config_table[i].chflags = 0;
11367                                 for (j = 0; j < li_total_channels; j++)
11368                                 {
11369                                         li_config_table[i].flag_table[j] = 0;
11370                                         li_config_table[j].flag_table[i] = 0;
11371                                         li_config_table[i].coef_table[j] = 0;
11372                                         li_config_table[j].coef_table[i] = 0;
11373                                 }
11374                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11375                                 {
11376                                         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11377                                         li_config_table[i].curchnl = 0;
11378                                         li_config_table[i].channel = 0;
11379                                         li_config_table[i].chflags = 0;
11380                                         for (j = 0; j < li_total_channels; j++)
11381                                         {
11382                                                 li_config_table[i].flag_table[j] = 0;
11383                                                 li_config_table[j].flag_table[i] = 0;
11384                                                 li_config_table[i].coef_table[j] = 0;
11385                                                 li_config_table[j].coef_table[i] = 0;
11386                                         }
11387                                 }
11388                         }
11389                 }
11390         }
11391 }
11392
11393
11394 static void mixer_prepare_switch(dword Id, PLCI *plci)
11395 {
11396
11397         dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11398                         UnMapId(Id), (char *)(FILE_), __LINE__));
11399
11400         do
11401         {
11402                 mixer_indication_coefs_set(Id, plci);
11403         } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11404 }
11405
11406
11407 static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11408 {
11409         DIVA_CAPI_ADAPTER *a;
11410         word i, j;
11411
11412         dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11413                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11414
11415         a = plci->adapter;
11416         if ((plci->li_bchannel_id != 0)
11417             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11418         {
11419                 i = a->li_base + (plci->li_bchannel_id - 1);
11420                 for (j = 0; j < li_total_channels; j++)
11421                 {
11422                         li_config_table[i].coef_table[j] &= 0xf;
11423                         li_config_table[j].coef_table[i] &= 0xf;
11424                 }
11425                 if (!a->li_pri)
11426                         li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11427         }
11428         return (GOOD);
11429 }
11430
11431
11432 static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11433 {
11434         DIVA_CAPI_ADAPTER *a;
11435         word Info;
11436
11437         dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11438                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11439
11440         Info = GOOD;
11441         a = plci->adapter;
11442         if ((plci->B1_facilities & B1_FACILITY_MIXER)
11443             && (plci->li_bchannel_id != 0)
11444             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11445         {
11446                 switch (plci->adjust_b_state)
11447                 {
11448                 case ADJUST_B_RESTORE_MIXER_1:
11449                         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11450                         {
11451                                 plci->internal_command = plci->adjust_b_command;
11452                                 if (plci_nl_busy(plci))
11453                                 {
11454                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11455                                         break;
11456                                 }
11457                                 xconnect_query_addresses(plci);
11458                                 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11459                                 break;
11460                         }
11461                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11462                         Rc = OK;
11463                 case ADJUST_B_RESTORE_MIXER_2:
11464                 case ADJUST_B_RESTORE_MIXER_3:
11465                 case ADJUST_B_RESTORE_MIXER_4:
11466                         if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11467                         {
11468                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11469                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11470                                 Info = _WRONG_STATE;
11471                                 break;
11472                         }
11473                         if (Rc == OK)
11474                         {
11475                                 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11476                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11477                                 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11478                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11479                         }
11480                         else if (Rc == 0)
11481                         {
11482                                 if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11483                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11484                                 else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11485                                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11486                         }
11487                         if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11488                         {
11489                                 plci->internal_command = plci->adjust_b_command;
11490                                 break;
11491                         }
11492                 case ADJUST_B_RESTORE_MIXER_5:
11493                         xconnect_write_coefs(plci, plci->adjust_b_command);
11494                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11495                         Rc = OK;
11496                 case ADJUST_B_RESTORE_MIXER_6:
11497                         if (!xconnect_write_coefs_process(Id, plci, Rc))
11498                         {
11499                                 dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11500                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11501                                 Info = _FACILITY_NOT_SUPPORTED;
11502                                 break;
11503                         }
11504                         if (plci->internal_command)
11505                                 break;
11506                         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11507                 case ADJUST_B_RESTORE_MIXER_7:
11508                         break;
11509                 }
11510         }
11511         return (Info);
11512 }
11513
11514
11515 static void mixer_command(dword Id, PLCI *plci, byte Rc)
11516 {
11517         DIVA_CAPI_ADAPTER *a;
11518         word i, internal_command;
11519
11520         dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11521                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11522                         plci->li_cmd));
11523
11524         a = plci->adapter;
11525         internal_command = plci->internal_command;
11526         plci->internal_command = 0;
11527         switch (plci->li_cmd)
11528         {
11529         case LI_REQ_CONNECT:
11530         case LI_REQ_DISCONNECT:
11531         case LI_REQ_SILENT_UPDATE:
11532                 switch (internal_command)
11533                 {
11534                 default:
11535                         if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11536                         {
11537                                 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11538                                                                           B1_FACILITY_MIXER), MIXER_COMMAND_1);
11539                         }
11540                 case MIXER_COMMAND_1:
11541                         if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11542                         {
11543                                 if (adjust_b_process(Id, plci, Rc) != GOOD)
11544                                 {
11545                                         dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11546                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
11547                                         break;
11548                                 }
11549                                 if (plci->internal_command)
11550                                         return;
11551                         }
11552                         plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11553                         if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11554                             || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11555                                 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11556                                                                                       ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11557                         {
11558                                 xconnect_write_coefs(plci, MIXER_COMMAND_2);
11559                         }
11560                         else
11561                         {
11562                                 do
11563                                 {
11564                                         mixer_indication_coefs_set(Id, plci);
11565                                 } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11566                         }
11567                 case MIXER_COMMAND_2:
11568                         if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11569                             || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11570                                 && (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11571                                                                                       ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11572                         {
11573                                 if (!xconnect_write_coefs_process(Id, plci, Rc))
11574                                 {
11575                                         dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11576                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
11577                                         if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11578                                         {
11579                                                 do
11580                                                 {
11581                                                         plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11582                                                                 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11583                                                         i = (plci->li_plci_b_write_pos == 0) ?
11584                                                                 LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11585                                                 } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11586                                                          && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11587                                         }
11588                                         break;
11589                                 }
11590                                 if (plci->internal_command)
11591                                         return;
11592                         }
11593                         if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11594                         {
11595                                 adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11596                                                                           ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11597                         }
11598                 case MIXER_COMMAND_3:
11599                         if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11600                         {
11601                                 if (adjust_b_process(Id, plci, Rc) != GOOD)
11602                                 {
11603                                         dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11604                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
11605                                         break;
11606                                 }
11607                                 if (plci->internal_command)
11608                                         return;
11609                         }
11610                         break;
11611                 }
11612                 break;
11613         }
11614         if ((plci->li_bchannel_id == 0)
11615             || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11616         {
11617                 dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11618                                 UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11619         }
11620         else
11621         {
11622                 i = a->li_base + (plci->li_bchannel_id - 1);
11623                 li_config_table[i].curchnl = plci->li_channel_bits;
11624                 if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11625                 {
11626                         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11627                         li_config_table[i].curchnl = plci->li_channel_bits;
11628                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11629                         {
11630                                 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11631                                 li_config_table[i].curchnl = plci->li_channel_bits;
11632                         }
11633                 }
11634         }
11635 }
11636
11637
11638 static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11639                               dword plci_b_id, byte connect, dword li_flags)
11640 {
11641         word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11642         PLCI *plci_b;
11643         DIVA_CAPI_ADAPTER *a_b;
11644
11645         a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11646         plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11647         ch_a = a->li_base + (plci->li_bchannel_id - 1);
11648         if (!a->li_pri && (plci->tel == ADV_VOICE)
11649             && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11650         {
11651                 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11652                 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11653                         a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11654         }
11655         else
11656         {
11657                 ch_a_v = ch_a;
11658                 ch_a_s = ch_a;
11659         }
11660         ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11661         if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11662             && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11663         {
11664                 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11665                 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11666                         a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11667         }
11668         else
11669         {
11670                 ch_b_v = ch_b;
11671                 ch_b_s = ch_b;
11672         }
11673         if (connect)
11674         {
11675                 li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11676                 li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11677                 li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11678                 li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11679         }
11680         li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11681         li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11682         li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11683         li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11684         if (ch_a_v == ch_b_v)
11685         {
11686                 li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11687                 li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11688         }
11689         else
11690         {
11691                 if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11692                 {
11693                         for (i = 0; i < li_total_channels; i++)
11694                         {
11695                                 if (i != ch_a_v)
11696                                         li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11697                         }
11698                 }
11699                 if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11700                 {
11701                         for (i = 0; i < li_total_channels; i++)
11702                         {
11703                                 if (i != ch_a_s)
11704                                         li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11705                         }
11706                 }
11707                 if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11708                 {
11709                         for (i = 0; i < li_total_channels; i++)
11710                         {
11711                                 if (i != ch_a_v)
11712                                         li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11713                         }
11714                 }
11715                 if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11716                 {
11717                         for (i = 0; i < li_total_channels; i++)
11718                         {
11719                                 if (i != ch_a_s)
11720                                         li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11721                         }
11722                 }
11723         }
11724         if (li_flags & LI_FLAG_CONFERENCE_A_B)
11725         {
11726                 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11727                 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11728                 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11729                 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11730         }
11731         if (li_flags & LI_FLAG_CONFERENCE_B_A)
11732         {
11733                 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11734                 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11735                 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11736                 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11737         }
11738         if (li_flags & LI_FLAG_MONITOR_A)
11739         {
11740                 li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11741                 li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11742         }
11743         if (li_flags & LI_FLAG_MONITOR_B)
11744         {
11745                 li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11746                 li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11747         }
11748         if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11749         {
11750                 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11751                 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11752         }
11753         if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11754         {
11755                 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11756                 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11757         }
11758         if (li_flags & LI_FLAG_MIX_A)
11759         {
11760                 li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11761                 li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11762         }
11763         if (li_flags & LI_FLAG_MIX_B)
11764         {
11765                 li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11766                 li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11767         }
11768         if (ch_a_v != ch_a_s)
11769         {
11770                 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11771                 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11772         }
11773         if (ch_b_v != ch_b_s)
11774         {
11775                 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11776                 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11777         }
11778 }
11779
11780
11781 static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11782                                dword plci_b_id, byte connect, dword li_flags)
11783 {
11784         word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11785         PLCI *plci_b;
11786         DIVA_CAPI_ADAPTER *a_b;
11787
11788         a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11789         plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11790         ch_a = a->li_base + (plci->li_bchannel_id - 1);
11791         if (!a->li_pri && (plci->tel == ADV_VOICE)
11792             && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11793         {
11794                 ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11795                 ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11796                         a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11797         }
11798         else
11799         {
11800                 ch_a_v = ch_a;
11801                 ch_a_s = ch_a;
11802         }
11803         ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11804         if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11805             && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11806         {
11807                 ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11808                 ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11809                         a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11810         }
11811         else
11812         {
11813                 ch_b_v = ch_b;
11814                 ch_b_s = ch_b;
11815         }
11816         if (connect)
11817         {
11818                 li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11819                 li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11820                 li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11821                 li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11822                 li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11823                 li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11824         }
11825         li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11826         li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11827         li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11828         li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11829         li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11830         li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11831         li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11832         li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11833         if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11834         {
11835                 li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11836                 li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11837                 li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11838                 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11839         }
11840         if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11841         {
11842                 li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11843                 li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11844                 li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11845                 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11846         }
11847         if (li_flags & LI2_FLAG_MONITOR_B)
11848         {
11849                 li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11850                 li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11851         }
11852         if (li_flags & LI2_FLAG_MIX_B)
11853         {
11854                 li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11855                 li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11856         }
11857         if (li_flags & LI2_FLAG_MONITOR_X)
11858                 li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11859         if (li_flags & LI2_FLAG_MIX_X)
11860                 li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11861         if (li_flags & LI2_FLAG_LOOP_B)
11862         {
11863                 li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11864                 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11865                 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11866                 li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11867         }
11868         if (li_flags & LI2_FLAG_LOOP_PC)
11869                 li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11870         if (li_flags & LI2_FLAG_LOOP_X)
11871                 li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11872         if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11873                 li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11874         if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11875                 li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11876         if (ch_a_v != ch_a_s)
11877         {
11878                 li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11879                 li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11880         }
11881         if (ch_b_v != ch_b_s)
11882         {
11883                 li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11884                 li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11885         }
11886 }
11887
11888
11889 static word li_check_main_plci(dword Id, PLCI *plci)
11890 {
11891         if (plci == NULL)
11892         {
11893                 dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11894                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11895                 return (_WRONG_IDENTIFIER);
11896         }
11897         if (!plci->State
11898             || !plci->NL.Id || plci->nl_remove_id
11899             || (plci->li_bchannel_id == 0))
11900         {
11901                 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11902                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11903                 return (_WRONG_STATE);
11904         }
11905         li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11906         return (GOOD);
11907 }
11908
11909
11910 static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11911                              dword plci_b_id, word plci_b_write_pos, byte *p_result)
11912 {
11913         byte ctlr_b;
11914         PLCI *plci_b;
11915
11916         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11917              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11918         {
11919                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11920                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11921                 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11922                 return (NULL);
11923         }
11924         ctlr_b = 0;
11925         if ((plci_b_id & 0x7f) != 0)
11926         {
11927                 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11928                 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11929                         ctlr_b = 0;
11930         }
11931         if ((ctlr_b == 0)
11932             || (((plci_b_id >> 8) & 0xff) == 0)
11933             || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11934         {
11935                 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11936                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11937                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11938                 return (NULL);
11939         }
11940         plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11941         if (!plci_b->State
11942             || !plci_b->NL.Id || plci_b->nl_remove_id
11943             || (plci_b->li_bchannel_id == 0))
11944         {
11945                 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11946                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11947                 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11948                 return (NULL);
11949         }
11950         li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11951         if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11952             ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11953             && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11954                 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11955         {
11956                 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11957                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11958                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
11959                 return (NULL);
11960         }
11961         if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11962                                                           (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11963         {
11964                 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11965                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11966                 PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11967                 return (NULL);
11968         }
11969         return (plci_b);
11970 }
11971
11972
11973 static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11974                               dword plci_b_id, word plci_b_write_pos, byte *p_result)
11975 {
11976         byte ctlr_b;
11977         PLCI *plci_b;
11978
11979         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11980              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11981         {
11982                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11983                                 UnMapId(Id), (char *)(FILE_), __LINE__));
11984                 PUT_WORD(p_result, _WRONG_STATE);
11985                 return (NULL);
11986         }
11987         ctlr_b = 0;
11988         if ((plci_b_id & 0x7f) != 0)
11989         {
11990                 ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11991                 if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11992                         ctlr_b = 0;
11993         }
11994         if ((ctlr_b == 0)
11995             || (((plci_b_id >> 8) & 0xff) == 0)
11996             || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11997         {
11998                 dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11999                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12000                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
12001                 return (NULL);
12002         }
12003         plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
12004         if (!plci_b->State
12005             || !plci_b->NL.Id || plci_b->nl_remove_id
12006             || (plci_b->li_bchannel_id == 0)
12007             || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12008         {
12009                 dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
12010                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12011                 PUT_WORD(p_result, _WRONG_STATE);
12012                 return (NULL);
12013         }
12014         if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12015             ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
12016             && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12017                 || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12018         {
12019                 dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
12020                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12021                 PUT_WORD(p_result, _WRONG_IDENTIFIER);
12022                 return (NULL);
12023         }
12024         if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
12025                                                           (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12026         {
12027                 dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12028                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12029                 PUT_WORD(p_result, _WRONG_STATE);
12030                 return (NULL);
12031         }
12032         return (plci_b);
12033 }
12034
12035
12036 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
12037 {
12038         word Info;
12039         word i;
12040         dword d, li_flags, plci_b_id;
12041         PLCI *plci_b;
12042         API_PARSE li_parms[3];
12043         API_PARSE li_req_parms[3];
12044         API_PARSE li_participant_struct[2];
12045         API_PARSE li_participant_parms[3];
12046         word participant_parms_pos;
12047         byte result_buffer[32];
12048         byte *result;
12049         word result_pos;
12050         word plci_b_write_pos;
12051
12052         dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
12053                         UnMapId(Id), (char *)(FILE_), __LINE__));
12054
12055         Info = GOOD;
12056         result = result_buffer;
12057         result_buffer[0] = 0;
12058         if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12059         {
12060                 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12061                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12062                 Info = _FACILITY_NOT_SUPPORTED;
12063         }
12064         else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
12065         {
12066                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12067                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12068                 Info = _WRONG_MESSAGE_FORMAT;
12069         }
12070         else
12071         {
12072                 result_buffer[0] = 3;
12073                 PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
12074                 result_buffer[3] = 0;
12075                 switch (GET_WORD(li_parms[0].info))
12076                 {
12077                 case LI_GET_SUPPORTED_SERVICES:
12078                         if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12079                         {
12080                                 result_buffer[0] = 17;
12081                                 result_buffer[3] = 14;
12082                                 PUT_WORD(&result_buffer[4], GOOD);
12083                                 d = 0;
12084                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12085                                         d |= LI_CONFERENCING_SUPPORTED;
12086                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12087                                         d |= LI_MONITORING_SUPPORTED;
12088                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12089                                         d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12090                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12091                                         d |= LI_CROSS_CONTROLLER_SUPPORTED;
12092                                 PUT_DWORD(&result_buffer[6], d);
12093                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12094                                 {
12095                                         d = 0;
12096                                         for (i = 0; i < li_total_channels; i++)
12097                                         {
12098                                                 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12099                                                     && (li_config_table[i].adapter->li_pri
12100                                                         || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12101                                                 {
12102                                                         d++;
12103                                                 }
12104                                         }
12105                                 }
12106                                 else
12107                                 {
12108                                         d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12109                                 }
12110                                 PUT_DWORD(&result_buffer[10], d / 2);
12111                                 PUT_DWORD(&result_buffer[14], d);
12112                         }
12113                         else
12114                         {
12115                                 result_buffer[0] = 25;
12116                                 result_buffer[3] = 22;
12117                                 PUT_WORD(&result_buffer[4], GOOD);
12118                                 d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12119                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12120                                         d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12121                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12122                                         d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12123                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12124                                         d |= LI2_PC_LOOPING_SUPPORTED;
12125                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12126                                         d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12127                                 PUT_DWORD(&result_buffer[6], d);
12128                                 d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12129                                 PUT_DWORD(&result_buffer[10], d / 2);
12130                                 PUT_DWORD(&result_buffer[14], d - 1);
12131                                 if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12132                                 {
12133                                         d = 0;
12134                                         for (i = 0; i < li_total_channels; i++)
12135                                         {
12136                                                 if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12137                                                     && (li_config_table[i].adapter->li_pri
12138                                                         || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12139                                                 {
12140                                                         d++;
12141                                                 }
12142                                         }
12143                                 }
12144                                 PUT_DWORD(&result_buffer[18], d / 2);
12145                                 PUT_DWORD(&result_buffer[22], d - 1);
12146                         }
12147                         break;
12148
12149                 case LI_REQ_CONNECT:
12150                         if (li_parms[1].length == 8)
12151                         {
12152                                 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12153                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12154                                 {
12155                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12156                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12157                                         Info = _WRONG_MESSAGE_FORMAT;
12158                                         break;
12159                                 }
12160                                 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12161                                 li_flags = GET_DWORD(li_req_parms[1].info);
12162                                 Info = li_check_main_plci(Id, plci);
12163                                 result_buffer[0] = 9;
12164                                 result_buffer[3] = 6;
12165                                 PUT_DWORD(&result_buffer[4], plci_b_id);
12166                                 PUT_WORD(&result_buffer[8], GOOD);
12167                                 if (Info != GOOD)
12168                                         break;
12169                                 result = plci->saved_msg.info;
12170                                 for (i = 0; i <= result_buffer[0]; i++)
12171                                         result[i] = result_buffer[i];
12172                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12173                                 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12174                                 if (plci_b == NULL)
12175                                         break;
12176                                 li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12177                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12178                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12179                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12180                         }
12181                         else
12182                         {
12183                                 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12184                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12185                                 {
12186                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12187                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12188                                         Info = _WRONG_MESSAGE_FORMAT;
12189                                         break;
12190                                 }
12191                                 li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12192                                 Info = li_check_main_plci(Id, plci);
12193                                 result_buffer[0] = 7;
12194                                 result_buffer[3] = 4;
12195                                 PUT_WORD(&result_buffer[4], Info);
12196                                 result_buffer[6] = 0;
12197                                 if (Info != GOOD)
12198                                         break;
12199                                 result = plci->saved_msg.info;
12200                                 for (i = 0; i <= result_buffer[0]; i++)
12201                                         result[i] = result_buffer[i];
12202                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12203                                 participant_parms_pos = 0;
12204                                 result_pos = 7;
12205                                 li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12206                                 while (participant_parms_pos < li_req_parms[1].length)
12207                                 {
12208                                         result[result_pos] = 6;
12209                                         result_pos += 7;
12210                                         PUT_DWORD(&result[result_pos - 6], 0);
12211                                         PUT_WORD(&result[result_pos - 2], GOOD);
12212                                         if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12213                                                       (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
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                                         if (api_parse(&li_participant_struct[0].info[1],
12221                                                       li_participant_struct[0].length, "dd", li_participant_parms))
12222                                         {
12223                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12224                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12225                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12226                                                 break;
12227                                         }
12228                                         plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12229                                         li_flags = GET_DWORD(li_participant_parms[1].info);
12230                                         PUT_DWORD(&result[result_pos - 6], plci_b_id);
12231                                         if (sizeof(result) - result_pos < 7)
12232                                         {
12233                                                 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12234                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12235                                                 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12236                                                 break;
12237                                         }
12238                                         plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12239                                         if (plci_b != NULL)
12240                                         {
12241                                                 li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12242                                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12243                                                         ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12244                                                                       LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12245                                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12246                                         }
12247                                         participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12248                                                                        (&li_req_parms[1].info[1]));
12249                                 }
12250                                 result[0] = (byte)(result_pos - 1);
12251                                 result[3] = (byte)(result_pos - 4);
12252                                 result[6] = (byte)(result_pos - 7);
12253                                 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12254                                 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12255                                     || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12256                                 {
12257                                         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12258                                         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12259                                 }
12260                                 else
12261                                         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12262                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12263                         }
12264                         mixer_calculate_coefs(a);
12265                         plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12266                         mixer_notify_update(plci, true);
12267                         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12268                               "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12269                         plci->command = 0;
12270                         plci->li_cmd = GET_WORD(li_parms[0].info);
12271                         start_internal_command(Id, plci, mixer_command);
12272                         return (false);
12273
12274                 case LI_REQ_DISCONNECT:
12275                         if (li_parms[1].length == 4)
12276                         {
12277                                 appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12278                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12279                                 {
12280                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12281                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12282                                         Info = _WRONG_MESSAGE_FORMAT;
12283                                         break;
12284                                 }
12285                                 plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12286                                 Info = li_check_main_plci(Id, plci);
12287                                 result_buffer[0] = 9;
12288                                 result_buffer[3] = 6;
12289                                 PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12290                                 PUT_WORD(&result_buffer[8], GOOD);
12291                                 if (Info != GOOD)
12292                                         break;
12293                                 result = plci->saved_msg.info;
12294                                 for (i = 0; i <= result_buffer[0]; i++)
12295                                         result[i] = result_buffer[i];
12296                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12297                                 plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12298                                 if (plci_b == NULL)
12299                                         break;
12300                                 li_update_connect(Id, a, plci, plci_b_id, false, 0);
12301                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12302                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12303                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12304                         }
12305                         else
12306                         {
12307                                 appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12308                                 if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12309                                 {
12310                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12311                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12312                                         Info = _WRONG_MESSAGE_FORMAT;
12313                                         break;
12314                                 }
12315                                 Info = li_check_main_plci(Id, plci);
12316                                 result_buffer[0] = 7;
12317                                 result_buffer[3] = 4;
12318                                 PUT_WORD(&result_buffer[4], Info);
12319                                 result_buffer[6] = 0;
12320                                 if (Info != GOOD)
12321                                         break;
12322                                 result = plci->saved_msg.info;
12323                                 for (i = 0; i <= result_buffer[0]; i++)
12324                                         result[i] = result_buffer[i];
12325                                 plci_b_write_pos = plci->li_plci_b_write_pos;
12326                                 participant_parms_pos = 0;
12327                                 result_pos = 7;
12328                                 while (participant_parms_pos < li_req_parms[0].length)
12329                                 {
12330                                         result[result_pos] = 6;
12331                                         result_pos += 7;
12332                                         PUT_DWORD(&result[result_pos - 6], 0);
12333                                         PUT_WORD(&result[result_pos - 2], GOOD);
12334                                         if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12335                                                       (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
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                                         if (api_parse(&li_participant_struct[0].info[1],
12343                                                       li_participant_struct[0].length, "d", li_participant_parms))
12344                                         {
12345                                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12346                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12347                                                 PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12348                                                 break;
12349                                         }
12350                                         plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12351                                         PUT_DWORD(&result[result_pos - 6], plci_b_id);
12352                                         if (sizeof(result) - result_pos < 7)
12353                                         {
12354                                                 dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12355                                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12356                                                 PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12357                                                 break;
12358                                         }
12359                                         plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12360                                         if (plci_b != NULL)
12361                                         {
12362                                                 li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12363                                                 plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12364                                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12365                                         }
12366                                         participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12367                                                                        (&li_req_parms[0].info[1]));
12368                                 }
12369                                 result[0] = (byte)(result_pos - 1);
12370                                 result[3] = (byte)(result_pos - 4);
12371                                 result[6] = (byte)(result_pos - 7);
12372                                 i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12373                                 if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12374                                     || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12375                                 {
12376                                         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12377                                         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12378                                 }
12379                                 else
12380                                         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12381                                 plci->li_plci_b_write_pos = plci_b_write_pos;
12382                         }
12383                         mixer_calculate_coefs(a);
12384                         plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12385                         mixer_notify_update(plci, true);
12386                         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12387                               "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12388                         plci->command = 0;
12389                         plci->li_cmd = GET_WORD(li_parms[0].info);
12390                         start_internal_command(Id, plci, mixer_command);
12391                         return (false);
12392
12393                 case LI_REQ_SILENT_UPDATE:
12394                         if (!plci || !plci->State
12395                             || !plci->NL.Id || plci->nl_remove_id
12396                             || (plci->li_bchannel_id == 0)
12397                             || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12398                         {
12399                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12400                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12401                                 return (false);
12402                         }
12403                         plci_b_write_pos = plci->li_plci_b_write_pos;
12404                         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12405                              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12406                         {
12407                                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12408                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12409                                 return (false);
12410                         }
12411                         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12412                         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12413                             || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12414                         {
12415                                 plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12416                                 plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12417                         }
12418                         else
12419                                 plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12420                         plci->li_plci_b_write_pos = plci_b_write_pos;
12421                         plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12422                         plci->command = 0;
12423                         plci->li_cmd = GET_WORD(li_parms[0].info);
12424                         start_internal_command(Id, plci, mixer_command);
12425                         return (false);
12426
12427                 default:
12428                         dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12429                                         UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12430                         Info = _FACILITY_NOT_SUPPORTED;
12431                 }
12432         }
12433         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12434               "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12435         return (false);
12436 }
12437
12438
12439 static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12440 {
12441         dword d;
12442         byte result[12];
12443
12444         dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12445                         UnMapId(Id), (char *)(FILE_), __LINE__));
12446
12447         if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12448         {
12449                 do
12450                 {
12451                         d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12452                         if (!(d & LI_PLCI_B_SKIP_FLAG))
12453                         {
12454                                 if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12455                                 {
12456                                         if (d & LI_PLCI_B_DISC_FLAG)
12457                                         {
12458                                                 result[0] = 5;
12459                                                 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12460                                                 result[3] = 2;
12461                                                 PUT_WORD(&result[4], _LI_USER_INITIATED);
12462                                         }
12463                                         else
12464                                         {
12465                                                 result[0] = 7;
12466                                                 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12467                                                 result[3] = 4;
12468                                                 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12469                                         }
12470                                 }
12471                                 else
12472                                 {
12473                                         if (d & LI_PLCI_B_DISC_FLAG)
12474                                         {
12475                                                 result[0] = 9;
12476                                                 PUT_WORD(&result[1], LI_IND_DISCONNECT);
12477                                                 result[3] = 6;
12478                                                 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12479                                                 PUT_WORD(&result[8], _LI_USER_INITIATED);
12480                                         }
12481                                         else
12482                                         {
12483                                                 result[0] = 7;
12484                                                 PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12485                                                 result[3] = 4;
12486                                                 PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12487                                         }
12488                                 }
12489                                 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12490                                       "ws", SELECTOR_LINE_INTERCONNECT, result);
12491                         }
12492                         plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12493                                 0 : plci->li_plci_b_read_pos + 1;
12494                 } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12495         }
12496 }
12497
12498
12499 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12500 {
12501         word i, j, ch;
12502         struct xconnect_transfer_address_s s,   *p;
12503         DIVA_CAPI_ADAPTER *a;
12504
12505         dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12506                         UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12507
12508         a = plci->adapter;
12509         i = 1;
12510         for (i = 1; i < length; i += 16)
12511         {
12512                 s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12513                 s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12514                 s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12515                 ch = msg[i + 12] | (msg[i + 13] << 8);
12516                 j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12517                 if (!a->li_pri && (plci->li_bchannel_id == 2))
12518                         j = 1 - j;
12519                 j += a->li_base;
12520                 if (ch & XCONNECT_CHANNEL_PORT_PC)
12521                         p = &(li_config_table[j].send_pc);
12522                 else
12523                         p = &(li_config_table[j].send_b);
12524                 p->card_address.low = s.card_address.low;
12525                 p->card_address.high = s.card_address.high;
12526                 p->offset = s.offset;
12527                 li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12528         }
12529         if (plci->internal_command_queue[0]
12530             && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12531                 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12532                 || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12533         {
12534                 (*(plci->internal_command_queue[0]))(Id, plci, 0);
12535                 if (!plci->internal_command)
12536                         next_internal_command(Id, plci);
12537         }
12538         mixer_notify_update(plci, true);
12539 }
12540
12541
12542 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12543 {
12544
12545         dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12546                         UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12547
12548 }
12549
12550
12551 static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12552 {
12553         word plci_b_write_pos;
12554
12555         plci_b_write_pos = plci->li_plci_b_write_pos;
12556         if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12557              LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12558         {
12559                 dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12560                                 (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12561                                 (char *)(FILE_), __LINE__));
12562                 return (false);
12563         }
12564         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12565         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12566         plci->li_plci_b_write_pos = plci_b_write_pos;
12567         return (true);
12568 }
12569
12570
12571 static void mixer_remove(PLCI *plci)
12572 {
12573         DIVA_CAPI_ADAPTER *a;
12574         PLCI *notify_plci;
12575         dword plci_b_id;
12576         word i, j;
12577
12578         dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12579                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12580                         (char *)(FILE_), __LINE__));
12581
12582         a = plci->adapter;
12583         plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12584         if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12585         {
12586                 if ((plci->li_bchannel_id != 0)
12587                     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12588                 {
12589                         i = a->li_base + (plci->li_bchannel_id - 1);
12590                         if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12591                         {
12592                                 for (j = 0; j < li_total_channels; j++)
12593                                 {
12594                                         if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12595                                             || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12596                                         {
12597                                                 notify_plci = li_config_table[j].plci;
12598                                                 if ((notify_plci != NULL)
12599                                                     && (notify_plci != plci)
12600                                                     && (notify_plci->appl != NULL)
12601                                                     && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12602                                                     && (notify_plci->State)
12603                                                     && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12604                                                 {
12605                                                         mixer_notify_source_removed(notify_plci, plci_b_id);
12606                                                 }
12607                                         }
12608                                 }
12609                                 mixer_clear_config(plci);
12610                                 mixer_calculate_coefs(a);
12611                                 mixer_notify_update(plci, true);
12612                         }
12613                         li_config_table[i].plci = NULL;
12614                         plci->li_bchannel_id = 0;
12615                 }
12616         }
12617 }
12618
12619
12620 /*------------------------------------------------------------------*/
12621 /* Echo canceller facilities                                        */
12622 /*------------------------------------------------------------------*/
12623
12624
12625 static void ec_write_parameters(PLCI *plci)
12626 {
12627         word w;
12628         byte parameter_buffer[6];
12629
12630         dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12631                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12632                         (char *)(FILE_), __LINE__));
12633
12634         parameter_buffer[0] = 5;
12635         parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12636         PUT_WORD(&parameter_buffer[2], plci->ec_idi_options);
12637         plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12638         w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12639         PUT_WORD(&parameter_buffer[4], w);
12640         add_p(plci, FTY, parameter_buffer);
12641         sig_req(plci, TEL_CTRL, 0);
12642         send_req(plci);
12643 }
12644
12645
12646 static void ec_clear_config(PLCI *plci)
12647 {
12648
12649         dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12650                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12651                         (char *)(FILE_), __LINE__));
12652
12653         plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12654                 LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12655         plci->ec_tail_length = 0;
12656 }
12657
12658
12659 static void ec_prepare_switch(dword Id, PLCI *plci)
12660 {
12661
12662         dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12663                         UnMapId(Id), (char *)(FILE_), __LINE__));
12664
12665 }
12666
12667
12668 static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12669 {
12670
12671         dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12672                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12673
12674         return (GOOD);
12675 }
12676
12677
12678 static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12679 {
12680         word Info;
12681
12682         dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12683                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12684
12685         Info = GOOD;
12686         if (plci->B1_facilities & B1_FACILITY_EC)
12687         {
12688                 switch (plci->adjust_b_state)
12689                 {
12690                 case ADJUST_B_RESTORE_EC_1:
12691                         plci->internal_command = plci->adjust_b_command;
12692                         if (plci->sig_req)
12693                         {
12694                                 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12695                                 break;
12696                         }
12697                         ec_write_parameters(plci);
12698                         plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12699                         break;
12700                 case ADJUST_B_RESTORE_EC_2:
12701                         if ((Rc != OK) && (Rc != OK_FC))
12702                         {
12703                                 dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12704                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12705                                 Info = _WRONG_STATE;
12706                                 break;
12707                         }
12708                         break;
12709                 }
12710         }
12711         return (Info);
12712 }
12713
12714
12715 static void ec_command(dword Id, PLCI *plci, byte Rc)
12716 {
12717         word internal_command, Info;
12718         byte result[8];
12719
12720         dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12721                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12722                         plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12723
12724         Info = GOOD;
12725         if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12726         {
12727                 result[0] = 2;
12728                 PUT_WORD(&result[1], EC_SUCCESS);
12729         }
12730         else
12731         {
12732                 result[0] = 5;
12733                 PUT_WORD(&result[1], plci->ec_cmd);
12734                 result[3] = 2;
12735                 PUT_WORD(&result[4], GOOD);
12736         }
12737         internal_command = plci->internal_command;
12738         plci->internal_command = 0;
12739         switch (plci->ec_cmd)
12740         {
12741         case EC_ENABLE_OPERATION:
12742         case EC_FREEZE_COEFFICIENTS:
12743         case EC_RESUME_COEFFICIENT_UPDATE:
12744         case EC_RESET_COEFFICIENTS:
12745                 switch (internal_command)
12746                 {
12747                 default:
12748                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12749                                                                   B1_FACILITY_EC), EC_COMMAND_1);
12750                 case EC_COMMAND_1:
12751                         if (adjust_b_process(Id, plci, Rc) != GOOD)
12752                         {
12753                                 dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12754                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12755                                 Info = _FACILITY_NOT_SUPPORTED;
12756                                 break;
12757                         }
12758                         if (plci->internal_command)
12759                                 return;
12760                 case EC_COMMAND_2:
12761                         if (plci->sig_req)
12762                         {
12763                                 plci->internal_command = EC_COMMAND_2;
12764                                 return;
12765                         }
12766                         plci->internal_command = EC_COMMAND_3;
12767                         ec_write_parameters(plci);
12768                         return;
12769                 case EC_COMMAND_3:
12770                         if ((Rc != OK) && (Rc != OK_FC))
12771                         {
12772                                 dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12773                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12774                                 Info = _FACILITY_NOT_SUPPORTED;
12775                                 break;
12776                         }
12777                         break;
12778                 }
12779                 break;
12780
12781         case EC_DISABLE_OPERATION:
12782                 switch (internal_command)
12783                 {
12784                 default:
12785                 case EC_COMMAND_1:
12786                         if (plci->B1_facilities & B1_FACILITY_EC)
12787                         {
12788                                 if (plci->sig_req)
12789                                 {
12790                                         plci->internal_command = EC_COMMAND_1;
12791                                         return;
12792                                 }
12793                                 plci->internal_command = EC_COMMAND_2;
12794                                 ec_write_parameters(plci);
12795                                 return;
12796                         }
12797                         Rc = OK;
12798                 case EC_COMMAND_2:
12799                         if ((Rc != OK) && (Rc != OK_FC))
12800                         {
12801                                 dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12802                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12803                                 Info = _FACILITY_NOT_SUPPORTED;
12804                                 break;
12805                         }
12806                         adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12807                                                                   ~B1_FACILITY_EC), EC_COMMAND_3);
12808                 case EC_COMMAND_3:
12809                         if (adjust_b_process(Id, plci, Rc) != GOOD)
12810                         {
12811                                 dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12812                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12813                                 Info = _FACILITY_NOT_SUPPORTED;
12814                                 break;
12815                         }
12816                         if (plci->internal_command)
12817                                 return;
12818                         break;
12819                 }
12820                 break;
12821         }
12822         sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12823               "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12824               PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12825 }
12826
12827
12828 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
12829 {
12830         word Info;
12831         word opt;
12832         API_PARSE ec_parms[3];
12833         byte result[16];
12834
12835         dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12836                         UnMapId(Id), (char *)(FILE_), __LINE__));
12837
12838         Info = GOOD;
12839         result[0] = 0;
12840         if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12841         {
12842                 dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12843                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12844                 Info = _FACILITY_NOT_SUPPORTED;
12845         }
12846         else
12847         {
12848                 if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12849                 {
12850                         if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12851                         {
12852                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12853                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12854                                 Info = _WRONG_MESSAGE_FORMAT;
12855                         }
12856                         else
12857                         {
12858                                 if (plci == NULL)
12859                                 {
12860                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12861                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12862                                         Info = _WRONG_IDENTIFIER;
12863                                 }
12864                                 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12865                                 {
12866                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12867                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12868                                         Info = _WRONG_STATE;
12869                                 }
12870                                 else
12871                                 {
12872                                         plci->command = 0;
12873                                         plci->ec_cmd = GET_WORD(ec_parms[0].info);
12874                                         plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12875                                         result[0] = 2;
12876                                         PUT_WORD(&result[1], EC_SUCCESS);
12877                                         if (msg[1].length >= 4)
12878                                         {
12879                                                 opt = GET_WORD(&ec_parms[0].info[2]);
12880                                                 plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12881                                                                           LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12882                                                 if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12883                                                         plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12884                                                 if (opt & EC_DETECT_DISABLE_TONE)
12885                                                         plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12886                                                 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12887                                                         plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12888                                                 if (msg[1].length >= 6)
12889                                                 {
12890                                                         plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12891                                                 }
12892                                         }
12893                                         switch (plci->ec_cmd)
12894                                         {
12895                                         case EC_ENABLE_OPERATION:
12896                                                 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12897                                                 start_internal_command(Id, plci, ec_command);
12898                                                 return (false);
12899
12900                                         case EC_DISABLE_OPERATION:
12901                                                 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12902                                                         LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12903                                                         LEC_RESET_COEFFICIENTS;
12904                                                 start_internal_command(Id, plci, ec_command);
12905                                                 return (false);
12906
12907                                         case EC_FREEZE_COEFFICIENTS:
12908                                                 plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12909                                                 start_internal_command(Id, plci, ec_command);
12910                                                 return (false);
12911
12912                                         case EC_RESUME_COEFFICIENT_UPDATE:
12913                                                 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12914                                                 start_internal_command(Id, plci, ec_command);
12915                                                 return (false);
12916
12917                                         case EC_RESET_COEFFICIENTS:
12918                                                 plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12919                                                 start_internal_command(Id, plci, ec_command);
12920                                                 return (false);
12921
12922                                         default:
12923                                                 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12924                                                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12925                                                 PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12926                                         }
12927                                 }
12928                         }
12929                 }
12930                 else
12931                 {
12932                         if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12933                         {
12934                                 dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12935                                                 UnMapId(Id), (char *)(FILE_), __LINE__));
12936                                 Info = _WRONG_MESSAGE_FORMAT;
12937                         }
12938                         else
12939                         {
12940                                 if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12941                                 {
12942                                         result[0] = 11;
12943                                         PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12944                                         result[3] = 8;
12945                                         PUT_WORD(&result[4], GOOD);
12946                                         PUT_WORD(&result[6], 0x0007);
12947                                         PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12948                                         PUT_WORD(&result[10], 0);
12949                                 }
12950                                 else if (plci == NULL)
12951                                 {
12952                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12953                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12954                                         Info = _WRONG_IDENTIFIER;
12955                                 }
12956                                 else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12957                                 {
12958                                         dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12959                                                         UnMapId(Id), (char *)(FILE_), __LINE__));
12960                                         Info = _WRONG_STATE;
12961                                 }
12962                                 else
12963                                 {
12964                                         plci->command = 0;
12965                                         plci->ec_cmd = GET_WORD(ec_parms[0].info);
12966                                         plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12967                                         result[0] = 5;
12968                                         PUT_WORD(&result[1], plci->ec_cmd);
12969                                         result[3] = 2;
12970                                         PUT_WORD(&result[4], GOOD);
12971                                         plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12972                                                                   LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12973                                         plci->ec_tail_length = 0;
12974                                         if (ec_parms[1].length >= 2)
12975                                         {
12976                                                 opt = GET_WORD(&ec_parms[1].info[1]);
12977                                                 if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12978                                                         plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12979                                                 if (opt & EC_DETECT_DISABLE_TONE)
12980                                                         plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12981                                                 if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12982                                                         plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12983                                                 if (ec_parms[1].length >= 4)
12984                                                 {
12985                                                         plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12986                                                 }
12987                                         }
12988                                         switch (plci->ec_cmd)
12989                                         {
12990                                         case EC_ENABLE_OPERATION:
12991                                                 plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12992                                                 start_internal_command(Id, plci, ec_command);
12993                                                 return (false);
12994
12995                                         case EC_DISABLE_OPERATION:
12996                                                 plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12997                                                         LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12998                                                         LEC_RESET_COEFFICIENTS;
12999                                                 start_internal_command(Id, plci, ec_command);
13000                                                 return (false);
13001
13002                                         default:
13003                                                 dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
13004                                                                 UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
13005                                                 PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13006                                         }
13007                                 }
13008                         }
13009                 }
13010         }
13011         sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13012               "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13013               PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13014         return (false);
13015 }
13016
13017
13018 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
13019 {
13020         byte result[8];
13021
13022         dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
13023                         UnMapId(Id), (char *)(FILE_), __LINE__));
13024
13025         if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13026         {
13027                 if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13028                 {
13029                         result[0] = 2;
13030                         PUT_WORD(&result[1], 0);
13031                         switch (msg[1])
13032                         {
13033                         case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13034                                 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13035                                 break;
13036                         case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13037                                 PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13038                                 break;
13039                         case LEC_DISABLE_RELEASED:
13040                                 PUT_WORD(&result[1], EC_BYPASS_RELEASED);
13041                                 break;
13042                         }
13043                 }
13044                 else
13045                 {
13046                         result[0] = 5;
13047                         PUT_WORD(&result[1], EC_BYPASS_INDICATION);
13048                         result[3] = 2;
13049                         PUT_WORD(&result[4], 0);
13050                         switch (msg[1])
13051                         {
13052                         case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13053                                 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13054                                 break;
13055                         case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13056                                 PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13057                                 break;
13058                         case LEC_DISABLE_RELEASED:
13059                                 PUT_WORD(&result[4], EC_BYPASS_RELEASED);
13060                                 break;
13061                         }
13062                 }
13063                 sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13064                       PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13065         }
13066 }
13067
13068
13069
13070 /*------------------------------------------------------------------*/
13071 /* Advanced voice                                                   */
13072 /*------------------------------------------------------------------*/
13073
13074 static void adv_voice_write_coefs(PLCI *plci, word write_command)
13075 {
13076         DIVA_CAPI_ADAPTER *a;
13077         word i;
13078         byte *p;
13079
13080         word w, n, j, k;
13081         byte ch_map[MIXER_CHANNELS_BRI];
13082
13083         byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13084
13085         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
13086                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13087                         (char *)(FILE_), __LINE__, write_command));
13088
13089         a = plci->adapter;
13090         p = coef_buffer + 1;
13091         *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13092         i = 0;
13093         while (i + sizeof(word) <= a->adv_voice_coef_length)
13094         {
13095                 PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
13096                 p += 2;
13097                 i += 2;
13098         }
13099         while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13100         {
13101                 PUT_WORD(p, 0x8000);
13102                 p += 2;
13103                 i += 2;
13104         }
13105
13106         if (!a->li_pri && (plci->li_bchannel_id == 0))
13107         {
13108                 if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13109                 {
13110                         plci->li_bchannel_id = 1;
13111                         li_config_table[a->li_base].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                 else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13117                 {
13118                         plci->li_bchannel_id = 2;
13119                         li_config_table[a->li_base + 1].plci = plci;
13120                         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13121                                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13122                                         (char *)(FILE_), __LINE__, plci->li_bchannel_id));
13123                 }
13124         }
13125         if (!a->li_pri && (plci->li_bchannel_id != 0)
13126             && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13127         {
13128                 i = a->li_base + (plci->li_bchannel_id - 1);
13129                 switch (write_command)
13130                 {
13131                 case ADV_VOICE_WRITE_ACTIVATION:
13132                         j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13133                         k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13134                         if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13135                         {
13136                                 li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13137                                 li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13138                         }
13139                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13140                         {
13141                                 li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13142                                 li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13143                                 li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13144                                 li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13145                         }
13146                         mixer_calculate_coefs(a);
13147                         li_config_table[i].curchnl = li_config_table[i].channel;
13148                         li_config_table[j].curchnl = li_config_table[j].channel;
13149                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13150                                 li_config_table[k].curchnl = li_config_table[k].channel;
13151                         break;
13152
13153                 case ADV_VOICE_WRITE_DEACTIVATION:
13154                         for (j = 0; j < li_total_channels; j++)
13155                         {
13156                                 li_config_table[i].flag_table[j] = 0;
13157                                 li_config_table[j].flag_table[i] = 0;
13158                         }
13159                         k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
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                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13166                         {
13167                                 k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13168                                 for (j = 0; j < li_total_channels; j++)
13169                                 {
13170                                         li_config_table[k].flag_table[j] = 0;
13171                                         li_config_table[j].flag_table[k] = 0;
13172                                 }
13173                         }
13174                         mixer_calculate_coefs(a);
13175                         break;
13176                 }
13177                 if (plci->B1_facilities & B1_FACILITY_MIXER)
13178                 {
13179                         w = 0;
13180                         if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13181                                 w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13182                         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13183                                 w |= MIXER_FEATURE_ENABLE_TX_DATA;
13184                         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13185                                 w |= MIXER_FEATURE_ENABLE_RX_DATA;
13186                         *(p++) = (byte) w;
13187                         *(p++) = (byte)(w >> 8);
13188                         for (j = 0; j < sizeof(ch_map); j += 2)
13189                         {
13190                                 ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13191                                 ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13192                         }
13193                         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13194                         {
13195                                 i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13196                                 j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13197                                 if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13198                                 {
13199                                         *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13200                                         w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13201                                         li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13202                                 }
13203                                 else
13204                                 {
13205                                         *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13206                                                 a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13207                                 }
13208                         }
13209                 }
13210                 else
13211                 {
13212                         for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13213                                 *(p++) = a->adv_voice_coef_buffer[i];
13214                 }
13215         }
13216         else
13217
13218         {
13219                 for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13220                         *(p++) = a->adv_voice_coef_buffer[i];
13221         }
13222         coef_buffer[0] = (p - coef_buffer) - 1;
13223         add_p(plci, FTY, coef_buffer);
13224         sig_req(plci, TEL_CTRL, 0);
13225         send_req(plci);
13226 }
13227
13228
13229 static void adv_voice_clear_config(PLCI *plci)
13230 {
13231         DIVA_CAPI_ADAPTER *a;
13232
13233         word i, j;
13234
13235
13236         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13237                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13238                         (char *)(FILE_), __LINE__));
13239
13240         a = plci->adapter;
13241         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13242         {
13243                 a->adv_voice_coef_length = 0;
13244
13245                 if (!a->li_pri && (plci->li_bchannel_id != 0)
13246                     && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13247                 {
13248                         i = a->li_base + (plci->li_bchannel_id - 1);
13249                         li_config_table[i].curchnl = 0;
13250                         li_config_table[i].channel = 0;
13251                         li_config_table[i].chflags = 0;
13252                         for (j = 0; j < li_total_channels; j++)
13253                         {
13254                                 li_config_table[i].flag_table[j] = 0;
13255                                 li_config_table[j].flag_table[i] = 0;
13256                                 li_config_table[i].coef_table[j] = 0;
13257                                 li_config_table[j].coef_table[i] = 0;
13258                         }
13259                         li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13260                         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13261                         li_config_table[i].curchnl = 0;
13262                         li_config_table[i].channel = 0;
13263                         li_config_table[i].chflags = 0;
13264                         for (j = 0; j < li_total_channels; j++)
13265                         {
13266                                 li_config_table[i].flag_table[j] = 0;
13267                                 li_config_table[j].flag_table[i] = 0;
13268                                 li_config_table[i].coef_table[j] = 0;
13269                                 li_config_table[j].coef_table[i] = 0;
13270                         }
13271                         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13272                         {
13273                                 i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13274                                 li_config_table[i].curchnl = 0;
13275                                 li_config_table[i].channel = 0;
13276                                 li_config_table[i].chflags = 0;
13277                                 for (j = 0; j < li_total_channels; j++)
13278                                 {
13279                                         li_config_table[i].flag_table[j] = 0;
13280                                         li_config_table[j].flag_table[i] = 0;
13281                                         li_config_table[i].coef_table[j] = 0;
13282                                         li_config_table[j].coef_table[i] = 0;
13283                                 }
13284                         }
13285                 }
13286
13287         }
13288 }
13289
13290
13291 static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13292 {
13293
13294         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13295                         UnMapId(Id), (char *)(FILE_), __LINE__));
13296
13297 }
13298
13299
13300 static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13301 {
13302
13303         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13304                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13305
13306         return (GOOD);
13307 }
13308
13309
13310 static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13311 {
13312         DIVA_CAPI_ADAPTER *a;
13313         word Info;
13314
13315         dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13316                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13317
13318         Info = GOOD;
13319         a = plci->adapter;
13320         if ((plci->B1_facilities & B1_FACILITY_VOICE)
13321             && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13322         {
13323                 switch (plci->adjust_b_state)
13324                 {
13325                 case ADJUST_B_RESTORE_VOICE_1:
13326                         plci->internal_command = plci->adjust_b_command;
13327                         if (plci->sig_req)
13328                         {
13329                                 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13330                                 break;
13331                         }
13332                         adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13333                         plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13334                         break;
13335                 case ADJUST_B_RESTORE_VOICE_2:
13336                         if ((Rc != OK) && (Rc != OK_FC))
13337                         {
13338                                 dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13339                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13340                                 Info = _WRONG_STATE;
13341                                 break;
13342                         }
13343                         break;
13344                 }
13345         }
13346         return (Info);
13347 }
13348
13349
13350
13351
13352 /*------------------------------------------------------------------*/
13353 /* B1 resource switching                                            */
13354 /*------------------------------------------------------------------*/
13355
13356 static byte b1_facilities_table[] =
13357 {
13358         0x00,  /* 0  No bchannel resources      */
13359         0x00,  /* 1  Codec (automatic law)      */
13360         0x00,  /* 2  Codec (A-law)              */
13361         0x00,  /* 3  Codec (y-law)              */
13362         0x00,  /* 4  HDLC for X.21              */
13363         0x00,  /* 5  HDLC                       */
13364         0x00,  /* 6  External Device 0          */
13365         0x00,  /* 7  External Device 1          */
13366         0x00,  /* 8  HDLC 56k                   */
13367         0x00,  /* 9  Transparent                */
13368         0x00,  /* 10 Loopback to network        */
13369         0x00,  /* 11 Test pattern to net        */
13370         0x00,  /* 12 Rate adaptation sync       */
13371         0x00,  /* 13 Rate adaptation async      */
13372         0x00,  /* 14 R-Interface                */
13373         0x00,  /* 15 HDLC 128k leased line      */
13374         0x00,  /* 16 FAX                        */
13375         0x00,  /* 17 Modem async                */
13376         0x00,  /* 18 Modem sync HDLC            */
13377         0x00,  /* 19 V.110 async HDLC           */
13378         0x12,  /* 20 Adv voice (Trans,mixer)    */
13379         0x00,  /* 21 Codec connected to IC      */
13380         0x0c,  /* 22 Trans,DTMF                 */
13381         0x1e,  /* 23 Trans,DTMF+mixer           */
13382         0x1f,  /* 24 Trans,DTMF+mixer+local     */
13383         0x13,  /* 25 Trans,mixer+local          */
13384         0x12,  /* 26 HDLC,mixer                 */
13385         0x12,  /* 27 HDLC 56k,mixer             */
13386         0x2c,  /* 28 Trans,LEC+DTMF             */
13387         0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13388         0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13389         0x2c,  /* 31 RTP,LEC+DTMF               */
13390         0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13391         0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13392         0x00,  /* 34 Signaling task             */
13393         0x00,  /* 35 PIAFS                      */
13394         0x0c,  /* 36 Trans,DTMF+TONE            */
13395         0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13396         0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13397 };
13398
13399
13400 static word get_b1_facilities(PLCI *plci, byte b1_resource)
13401 {
13402         word b1_facilities;
13403
13404         b1_facilities = b1_facilities_table[b1_resource];
13405         if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13406         {
13407
13408                 if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13409                       || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13410
13411                 {
13412                         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13413                                 b1_facilities |= B1_FACILITY_DTMFX;
13414                         if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13415                                 b1_facilities |= B1_FACILITY_DTMFR;
13416                 }
13417         }
13418         if ((b1_resource == 17) || (b1_resource == 18))
13419         {
13420                 if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13421                         b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13422         }
13423 /*
13424   dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13425   (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13426   (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13427 */
13428         return (b1_facilities);
13429 }
13430
13431
13432 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13433 {
13434         byte b;
13435
13436         switch (b1_resource)
13437         {
13438         case 5:
13439         case 26:
13440                 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13441                         b = 26;
13442                 else
13443                         b = 5;
13444                 break;
13445
13446         case 8:
13447         case 27:
13448                 if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13449                         b = 27;
13450                 else
13451                         b = 8;
13452                 break;
13453
13454         case 9:
13455         case 20:
13456         case 22:
13457         case 23:
13458         case 24:
13459         case 25:
13460         case 28:
13461         case 29:
13462         case 30:
13463         case 36:
13464         case 37:
13465         case 38:
13466                 if (b1_facilities & B1_FACILITY_EC)
13467                 {
13468                         if (b1_facilities & B1_FACILITY_LOCAL)
13469                                 b = 30;
13470                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13471                                 b = 29;
13472                         else
13473                                 b = 28;
13474                 }
13475
13476                 else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13477                          && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13478                              || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13479                 {
13480                         if (b1_facilities & B1_FACILITY_LOCAL)
13481                                 b = 38;
13482                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13483                                 b = 37;
13484                         else
13485                                 b = 36;
13486                 }
13487
13488                 else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13489                           && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13490                          || ((b1_facilities & B1_FACILITY_DTMFR)
13491                              && ((b1_facilities & B1_FACILITY_MIXER)
13492                                  || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13493                          || ((b1_facilities & B1_FACILITY_DTMFX)
13494                              && ((b1_facilities & B1_FACILITY_MIXER)
13495                                  || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13496                 {
13497                         if (b1_facilities & B1_FACILITY_LOCAL)
13498                                 b = 24;
13499                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13500                                 b = 23;
13501                         else
13502                                 b = 22;
13503                 }
13504                 else
13505                 {
13506                         if (b1_facilities & B1_FACILITY_LOCAL)
13507                                 b = 25;
13508                         else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13509                                 b = 20;
13510                         else
13511                                 b = 9;
13512                 }
13513                 break;
13514
13515         case 31:
13516         case 32:
13517         case 33:
13518                 if (b1_facilities & B1_FACILITY_LOCAL)
13519                         b = 33;
13520                 else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13521                         b = 32;
13522                 else
13523                         b = 31;
13524                 break;
13525
13526         default:
13527                 b = b1_resource;
13528         }
13529         dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13530                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13531                         (char *)(FILE_), __LINE__,
13532                         b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13533         return (b);
13534 }
13535
13536
13537 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13538 {
13539         word removed_facilities;
13540
13541         dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13542                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13543                         (char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13544                         new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13545
13546         new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13547         removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13548
13549         if (removed_facilities & B1_FACILITY_EC)
13550                 ec_clear_config(plci);
13551
13552
13553         if (removed_facilities & B1_FACILITY_DTMFR)
13554         {
13555                 dtmf_rec_clear_config(plci);
13556                 dtmf_parameter_clear_config(plci);
13557         }
13558         if (removed_facilities & B1_FACILITY_DTMFX)
13559                 dtmf_send_clear_config(plci);
13560
13561
13562         if (removed_facilities & B1_FACILITY_MIXER)
13563                 mixer_clear_config(plci);
13564
13565         if (removed_facilities & B1_FACILITY_VOICE)
13566                 adv_voice_clear_config(plci);
13567         plci->B1_facilities = new_b1_facilities;
13568 }
13569
13570
13571 static void adjust_b_clear(PLCI *plci)
13572 {
13573
13574         dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13575                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13576                         (char *)(FILE_), __LINE__));
13577
13578         plci->adjust_b_restore = false;
13579 }
13580
13581
13582 static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13583 {
13584         word Info;
13585         byte b1_resource;
13586         NCCI *ncci_ptr;
13587         API_PARSE bp[2];
13588
13589         dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13590                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13591
13592         Info = GOOD;
13593         switch (plci->adjust_b_state)
13594         {
13595         case ADJUST_B_START:
13596                 if ((plci->adjust_b_parms_msg == NULL)
13597                     && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13598                     && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13599                                                  ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13600                 {
13601                         b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13602                                 0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13603                         if (b1_resource == plci->B1_resource)
13604                         {
13605                                 adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13606                                 break;
13607                         }
13608                         if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13609                         {
13610                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13611                                                 UnMapId(Id), (char *)(FILE_), __LINE__,
13612                                                 plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13613                                 Info = _WRONG_STATE;
13614                                 break;
13615                         }
13616                 }
13617                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13618                 {
13619
13620                         mixer_prepare_switch(Id, plci);
13621
13622
13623                         dtmf_prepare_switch(Id, plci);
13624                         dtmf_parameter_prepare_switch(Id, plci);
13625
13626
13627                         ec_prepare_switch(Id, plci);
13628
13629                         adv_voice_prepare_switch(Id, plci);
13630                 }
13631                 plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13632                 Rc = OK;
13633         case ADJUST_B_SAVE_MIXER_1:
13634                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13635                 {
13636
13637                         Info = mixer_save_config(Id, plci, Rc);
13638                         if ((Info != GOOD) || plci->internal_command)
13639                                 break;
13640
13641                 }
13642                 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13643                 Rc = OK;
13644         case ADJUST_B_SAVE_DTMF_1:
13645                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13646                 {
13647
13648                         Info = dtmf_save_config(Id, plci, Rc);
13649                         if ((Info != GOOD) || plci->internal_command)
13650                                 break;
13651
13652                 }
13653                 plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13654         case ADJUST_B_REMOVE_L23_1:
13655                 if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13656                     && plci->NL.Id && !plci->nl_remove_id)
13657                 {
13658                         plci->internal_command = plci->adjust_b_command;
13659                         if (plci->adjust_b_ncci != 0)
13660                         {
13661                                 ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13662                                 while (ncci_ptr->data_pending)
13663                                 {
13664                                         plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13665                                         data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13666                                 }
13667                                 while (ncci_ptr->data_ack_pending)
13668                                         data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13669                         }
13670                         nl_req_ncci(plci, REMOVE,
13671                                     (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13672                         send_req(plci);
13673                         plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13674                         break;
13675                 }
13676                 plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13677                 Rc = OK;
13678         case ADJUST_B_REMOVE_L23_2:
13679                 if ((Rc != OK) && (Rc != OK_FC))
13680                 {
13681                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13682                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13683                         Info = _WRONG_STATE;
13684                         break;
13685                 }
13686                 if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13687                 {
13688                         if (plci_nl_busy(plci))
13689                         {
13690                                 plci->internal_command = plci->adjust_b_command;
13691                                 break;
13692                         }
13693                 }
13694                 plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13695                 Rc = OK;
13696         case ADJUST_B_SAVE_EC_1:
13697                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13698                 {
13699
13700                         Info = ec_save_config(Id, plci, Rc);
13701                         if ((Info != GOOD) || plci->internal_command)
13702                                 break;
13703
13704                 }
13705                 plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13706                 Rc = OK;
13707         case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13708                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13709                 {
13710
13711                         Info = dtmf_parameter_save_config(Id, plci, Rc);
13712                         if ((Info != GOOD) || plci->internal_command)
13713                                 break;
13714
13715                 }
13716                 plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13717                 Rc = OK;
13718         case ADJUST_B_SAVE_VOICE_1:
13719                 if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13720                 {
13721                         Info = adv_voice_save_config(Id, plci, Rc);
13722                         if ((Info != GOOD) || plci->internal_command)
13723                                 break;
13724                 }
13725                 plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13726         case ADJUST_B_SWITCH_L1_1:
13727                 if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13728                 {
13729                         if (plci->sig_req)
13730                         {
13731                                 plci->internal_command = plci->adjust_b_command;
13732                                 break;
13733                         }
13734                         if (plci->adjust_b_parms_msg != NULL)
13735                                 api_load_msg(plci->adjust_b_parms_msg, bp);
13736                         else
13737                                 api_load_msg(&plci->B_protocol, bp);
13738                         Info = add_b1(plci, bp,
13739                                       (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13740                                       plci->adjust_b_facilities);
13741                         if (Info != GOOD)
13742                         {
13743                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13744                                                 UnMapId(Id), (char *)(FILE_), __LINE__,
13745                                                 plci->B1_resource, plci->adjust_b_facilities));
13746                                 break;
13747                         }
13748                         plci->internal_command = plci->adjust_b_command;
13749                         sig_req(plci, RESOURCES, 0);
13750                         send_req(plci);
13751                         plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13752                         break;
13753                 }
13754                 plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13755                 Rc = OK;
13756         case ADJUST_B_SWITCH_L1_2:
13757                 if ((Rc != OK) && (Rc != OK_FC))
13758                 {
13759                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13760                                         UnMapId(Id), (char *)(FILE_), __LINE__,
13761                                         Rc, plci->B1_resource, plci->adjust_b_facilities));
13762                         Info = _WRONG_STATE;
13763                         break;
13764                 }
13765                 plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13766                 Rc = OK;
13767         case ADJUST_B_RESTORE_VOICE_1:
13768         case ADJUST_B_RESTORE_VOICE_2:
13769                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13770                 {
13771                         Info = adv_voice_restore_config(Id, plci, Rc);
13772                         if ((Info != GOOD) || plci->internal_command)
13773                                 break;
13774                 }
13775                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13776                 Rc = OK;
13777         case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13778         case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13779                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13780                 {
13781
13782                         Info = dtmf_parameter_restore_config(Id, plci, Rc);
13783                         if ((Info != GOOD) || plci->internal_command)
13784                                 break;
13785
13786                 }
13787                 plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13788                 Rc = OK;
13789         case ADJUST_B_RESTORE_EC_1:
13790         case ADJUST_B_RESTORE_EC_2:
13791                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13792                 {
13793
13794                         Info = ec_restore_config(Id, plci, Rc);
13795                         if ((Info != GOOD) || plci->internal_command)
13796                                 break;
13797
13798                 }
13799                 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13800         case ADJUST_B_ASSIGN_L23_1:
13801                 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13802                 {
13803                         if (plci_nl_busy(plci))
13804                         {
13805                                 plci->internal_command = plci->adjust_b_command;
13806                                 break;
13807                         }
13808                         if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13809                                 plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13810                         if (plci->adjust_b_parms_msg != NULL)
13811                                 api_load_msg(plci->adjust_b_parms_msg, bp);
13812                         else
13813                                 api_load_msg(&plci->B_protocol, bp);
13814                         Info = add_b23(plci, bp);
13815                         if (Info != GOOD)
13816                         {
13817                                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13818                                                 UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13819                                 break;
13820                         }
13821                         plci->internal_command = plci->adjust_b_command;
13822                         nl_req_ncci(plci, ASSIGN, 0);
13823                         send_req(plci);
13824                         plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13825                         break;
13826                 }
13827                 plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13828                 Rc = ASSIGN_OK;
13829         case ADJUST_B_ASSIGN_L23_2:
13830                 if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13831                 {
13832                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13833                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13834                         Info = _WRONG_STATE;
13835                         break;
13836                 }
13837                 if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13838                 {
13839                         if (Rc != ASSIGN_OK)
13840                         {
13841                                 plci->internal_command = plci->adjust_b_command;
13842                                 break;
13843                         }
13844                 }
13845                 if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13846                 {
13847                         plci->adjust_b_restore = true;
13848                         break;
13849                 }
13850                 plci->adjust_b_state = ADJUST_B_CONNECT_1;
13851         case ADJUST_B_CONNECT_1:
13852                 if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13853                 {
13854                         plci->internal_command = plci->adjust_b_command;
13855                         if (plci_nl_busy(plci))
13856                                 break;
13857                         nl_req_ncci(plci, N_CONNECT, 0);
13858                         send_req(plci);
13859                         plci->adjust_b_state = ADJUST_B_CONNECT_2;
13860                         break;
13861                 }
13862                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13863                 Rc = OK;
13864         case ADJUST_B_CONNECT_2:
13865         case ADJUST_B_CONNECT_3:
13866         case ADJUST_B_CONNECT_4:
13867                 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13868                 {
13869                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13870                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13871                         Info = _WRONG_STATE;
13872                         break;
13873                 }
13874                 if (Rc == OK)
13875                 {
13876                         if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13877                         {
13878                                 get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13879                                 Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13880                         }
13881                         if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13882                                 plci->adjust_b_state = ADJUST_B_CONNECT_3;
13883                         else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13884                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13885                 }
13886                 else if (Rc == 0)
13887                 {
13888                         if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13889                                 plci->adjust_b_state = ADJUST_B_CONNECT_4;
13890                         else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13891                                 plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13892                 }
13893                 if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13894                 {
13895                         plci->internal_command = plci->adjust_b_command;
13896                         break;
13897                 }
13898                 Rc = OK;
13899         case ADJUST_B_RESTORE_DTMF_1:
13900         case ADJUST_B_RESTORE_DTMF_2:
13901                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13902                 {
13903
13904                         Info = dtmf_restore_config(Id, plci, Rc);
13905                         if ((Info != GOOD) || plci->internal_command)
13906                                 break;
13907
13908                 }
13909                 plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13910                 Rc = OK;
13911         case ADJUST_B_RESTORE_MIXER_1:
13912         case ADJUST_B_RESTORE_MIXER_2:
13913         case ADJUST_B_RESTORE_MIXER_3:
13914         case ADJUST_B_RESTORE_MIXER_4:
13915         case ADJUST_B_RESTORE_MIXER_5:
13916         case ADJUST_B_RESTORE_MIXER_6:
13917         case ADJUST_B_RESTORE_MIXER_7:
13918                 if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13919                 {
13920
13921                         Info = mixer_restore_config(Id, plci, Rc);
13922                         if ((Info != GOOD) || plci->internal_command)
13923                                 break;
13924
13925                 }
13926                 plci->adjust_b_state = ADJUST_B_END;
13927         case ADJUST_B_END:
13928                 break;
13929         }
13930         return (Info);
13931 }
13932
13933
13934 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13935 {
13936
13937         dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13938                         UnMapId(Id), (char *)(FILE_), __LINE__,
13939                         plci->B1_resource, b1_facilities));
13940
13941         plci->adjust_b_parms_msg = bp_msg;
13942         plci->adjust_b_facilities = b1_facilities;
13943         plci->adjust_b_command = internal_command;
13944         plci->adjust_b_ncci = (word)(Id >> 16);
13945         if ((bp_msg == NULL) && (plci->B1_resource == 0))
13946                 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13947         else
13948                 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13949         plci->adjust_b_state = ADJUST_B_START;
13950         dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13951                         UnMapId(Id), (char *)(FILE_), __LINE__,
13952                         plci->B1_resource, b1_facilities));
13953 }
13954
13955
13956 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13957 {
13958         word internal_command;
13959
13960         dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13961                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13962
13963         internal_command = plci->internal_command;
13964         plci->internal_command = 0;
13965         switch (internal_command)
13966         {
13967         default:
13968                 plci->command = 0;
13969                 if (plci->req_in != 0)
13970                 {
13971                         plci->internal_command = ADJUST_B_RESTORE_1;
13972                         break;
13973                 }
13974                 Rc = OK;
13975         case ADJUST_B_RESTORE_1:
13976                 if ((Rc != OK) && (Rc != OK_FC))
13977                 {
13978                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13979                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13980                 }
13981                 plci->adjust_b_parms_msg = NULL;
13982                 plci->adjust_b_facilities = plci->B1_facilities;
13983                 plci->adjust_b_command = ADJUST_B_RESTORE_2;
13984                 plci->adjust_b_ncci = (word)(Id >> 16);
13985                 plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13986                 plci->adjust_b_state = ADJUST_B_START;
13987                 dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13988                                 UnMapId(Id), (char *)(FILE_), __LINE__));
13989         case ADJUST_B_RESTORE_2:
13990                 if (adjust_b_process(Id, plci, Rc) != GOOD)
13991                 {
13992                         dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13993                                         UnMapId(Id), (char *)(FILE_), __LINE__));
13994                 }
13995                 if (plci->internal_command)
13996                         break;
13997                 break;
13998         }
13999 }
14000
14001
14002 static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
14003 {
14004         word Info;
14005         word internal_command;
14006
14007         dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
14008                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14009
14010         Info = GOOD;
14011         internal_command = plci->internal_command;
14012         plci->internal_command = 0;
14013         switch (internal_command)
14014         {
14015         default:
14016                 plci->command = 0;
14017                 plci->adjust_b_parms_msg = NULL;
14018                 plci->adjust_b_facilities = plci->B1_facilities;
14019                 plci->adjust_b_command = RESET_B3_COMMAND_1;
14020                 plci->adjust_b_ncci = (word)(Id >> 16);
14021                 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14022                 plci->adjust_b_state = ADJUST_B_START;
14023                 dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
14024                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14025         case RESET_B3_COMMAND_1:
14026                 Info = adjust_b_process(Id, plci, Rc);
14027                 if (Info != GOOD)
14028                 {
14029                         dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
14030                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14031                         break;
14032                 }
14033                 if (plci->internal_command)
14034                         return;
14035                 break;
14036         }
14037 /*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14038         sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
14039 }
14040
14041
14042 static void select_b_command(dword Id, PLCI *plci, byte Rc)
14043 {
14044         word Info;
14045         word internal_command;
14046         byte esc_chi[3];
14047
14048         dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
14049                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14050
14051         Info = GOOD;
14052         internal_command = plci->internal_command;
14053         plci->internal_command = 0;
14054         switch (internal_command)
14055         {
14056         default:
14057                 plci->command = 0;
14058                 plci->adjust_b_parms_msg = &plci->saved_msg;
14059                 if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14060                         plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14061                 else
14062                         plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14063                 plci->adjust_b_command = SELECT_B_COMMAND_1;
14064                 plci->adjust_b_ncci = (word)(Id >> 16);
14065                 if (plci->saved_msg.parms[0].length == 0)
14066                 {
14067                         plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14068                                 ADJUST_B_MODE_NO_RESOURCE;
14069                 }
14070                 else
14071                 {
14072                         plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14073                                 ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14074                 }
14075                 plci->adjust_b_state = ADJUST_B_START;
14076                 dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
14077                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14078         case SELECT_B_COMMAND_1:
14079                 Info = adjust_b_process(Id, plci, Rc);
14080                 if (Info != GOOD)
14081                 {
14082                         dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
14083                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14084                         break;
14085                 }
14086                 if (plci->internal_command)
14087                         return;
14088                 if (plci->tel == ADV_VOICE)
14089                 {
14090                         esc_chi[0] = 0x02;
14091                         esc_chi[1] = 0x18;
14092                         esc_chi[2] = plci->b_channel;
14093                         SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14094                 }
14095                 break;
14096         }
14097         sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14098 }
14099
14100
14101 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
14102 {
14103         word internal_command;
14104
14105         dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14106                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14107
14108         internal_command = plci->internal_command;
14109         plci->internal_command = 0;
14110         switch (internal_command)
14111         {
14112         default:
14113                 plci->command = 0;
14114         case FAX_CONNECT_ACK_COMMAND_1:
14115                 if (plci_nl_busy(plci))
14116                 {
14117                         plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14118                         return;
14119                 }
14120                 plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14121                 plci->NData[0].P = plci->fax_connect_info_buffer;
14122                 plci->NData[0].PLength = plci->fax_connect_info_length;
14123                 plci->NL.X = plci->NData;
14124                 plci->NL.ReqCh = 0;
14125                 plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14126                 plci->adapter->request(&plci->NL);
14127                 return;
14128         case FAX_CONNECT_ACK_COMMAND_2:
14129                 if ((Rc != OK) && (Rc != OK_FC))
14130                 {
14131                         dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14132                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14133                         break;
14134                 }
14135         }
14136         if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14137             && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14138         {
14139                 if (plci->B3_prot == 4)
14140                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14141                 else
14142                         sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
14143                 plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14144         }
14145 }
14146
14147
14148 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14149 {
14150         word internal_command;
14151
14152         dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14153                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14154
14155         internal_command = plci->internal_command;
14156         plci->internal_command = 0;
14157         switch (internal_command)
14158         {
14159         default:
14160                 plci->command = 0;
14161         case FAX_EDATA_ACK_COMMAND_1:
14162                 if (plci_nl_busy(plci))
14163                 {
14164                         plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14165                         return;
14166                 }
14167                 plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14168                 plci->NData[0].P = plci->fax_connect_info_buffer;
14169                 plci->NData[0].PLength = plci->fax_edata_ack_length;
14170                 plci->NL.X = plci->NData;
14171                 plci->NL.ReqCh = 0;
14172                 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14173                 plci->adapter->request(&plci->NL);
14174                 return;
14175         case FAX_EDATA_ACK_COMMAND_2:
14176                 if ((Rc != OK) && (Rc != OK_FC))
14177                 {
14178                         dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14179                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14180                         break;
14181                 }
14182         }
14183 }
14184
14185
14186 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14187 {
14188         word Info;
14189         word internal_command;
14190
14191         dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14192                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14193
14194         Info = GOOD;
14195         internal_command = plci->internal_command;
14196         plci->internal_command = 0;
14197         switch (internal_command)
14198         {
14199         default:
14200                 plci->command = 0;
14201         case FAX_CONNECT_INFO_COMMAND_1:
14202                 if (plci_nl_busy(plci))
14203                 {
14204                         plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14205                         return;
14206                 }
14207                 plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14208                 plci->NData[0].P = plci->fax_connect_info_buffer;
14209                 plci->NData[0].PLength = plci->fax_connect_info_length;
14210                 plci->NL.X = plci->NData;
14211                 plci->NL.ReqCh = 0;
14212                 plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14213                 plci->adapter->request(&plci->NL);
14214                 return;
14215         case FAX_CONNECT_INFO_COMMAND_2:
14216                 if ((Rc != OK) && (Rc != OK_FC))
14217                 {
14218                         dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14219                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14220                         Info = _WRONG_STATE;
14221                         break;
14222                 }
14223                 if (plci_nl_busy(plci))
14224                 {
14225                         plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14226                         return;
14227                 }
14228                 plci->command = _CONNECT_B3_R;
14229                 nl_req_ncci(plci, N_CONNECT, 0);
14230                 send_req(plci);
14231                 return;
14232         }
14233         sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14234 }
14235
14236
14237 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14238 {
14239         word Info;
14240         word internal_command;
14241
14242         dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14243                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14244
14245         Info = GOOD;
14246         internal_command = plci->internal_command;
14247         plci->internal_command = 0;
14248         switch (internal_command)
14249         {
14250         default:
14251                 plci->command = 0;
14252                 plci->adjust_b_parms_msg = NULL;
14253                 plci->adjust_b_facilities = plci->B1_facilities;
14254                 plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14255                 plci->adjust_b_ncci = (word)(Id >> 16);
14256                 plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14257                 plci->adjust_b_state = ADJUST_B_START;
14258                 dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14259                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14260         case FAX_ADJUST_B23_COMMAND_1:
14261                 Info = adjust_b_process(Id, plci, Rc);
14262                 if (Info != GOOD)
14263                 {
14264                         dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14265                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14266                         break;
14267                 }
14268                 if (plci->internal_command)
14269                         return;
14270         case FAX_ADJUST_B23_COMMAND_2:
14271                 if (plci_nl_busy(plci))
14272                 {
14273                         plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14274                         return;
14275                 }
14276                 plci->command = _CONNECT_B3_R;
14277                 nl_req_ncci(plci, N_CONNECT, 0);
14278                 send_req(plci);
14279                 return;
14280         }
14281         sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14282 }
14283
14284
14285 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14286 {
14287         word internal_command;
14288
14289         dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14290                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14291
14292         internal_command = plci->internal_command;
14293         plci->internal_command = 0;
14294         switch (internal_command)
14295         {
14296         default:
14297                 plci->command = 0;
14298                 plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14299                 return;
14300         case FAX_DISCONNECT_COMMAND_1:
14301         case FAX_DISCONNECT_COMMAND_2:
14302         case FAX_DISCONNECT_COMMAND_3:
14303                 if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14304                 {
14305                         dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14306                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14307                         break;
14308                 }
14309                 if (Rc == OK)
14310                 {
14311                         if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14312                             || (internal_command == FAX_DISCONNECT_COMMAND_2))
14313                         {
14314                                 plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14315                         }
14316                 }
14317                 else if (Rc == 0)
14318                 {
14319                         if (internal_command == FAX_DISCONNECT_COMMAND_1)
14320                                 plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14321                 }
14322                 return;
14323         }
14324 }
14325
14326
14327
14328 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14329 {
14330         word Info;
14331         word internal_command;
14332
14333         dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14334                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14335
14336         Info = GOOD;
14337         internal_command = plci->internal_command;
14338         plci->internal_command = 0;
14339         switch (internal_command)
14340         {
14341         default:
14342                 plci->command = 0;
14343         case RTP_CONNECT_B3_REQ_COMMAND_1:
14344                 if (plci_nl_busy(plci))
14345                 {
14346                         plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14347                         return;
14348                 }
14349                 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14350                 nl_req_ncci(plci, N_CONNECT, 0);
14351                 send_req(plci);
14352                 return;
14353         case RTP_CONNECT_B3_REQ_COMMAND_2:
14354                 if ((Rc != OK) && (Rc != OK_FC))
14355                 {
14356                         dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14357                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14358                         Info = _WRONG_STATE;
14359                         break;
14360                 }
14361                 if (plci_nl_busy(plci))
14362                 {
14363                         plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14364                         return;
14365                 }
14366                 plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14367                 plci->NData[0].PLength = plci->internal_req_buffer[0];
14368                 plci->NData[0].P = plci->internal_req_buffer + 1;
14369                 plci->NL.X = plci->NData;
14370                 plci->NL.ReqCh = 0;
14371                 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14372                 plci->adapter->request(&plci->NL);
14373                 break;
14374         case RTP_CONNECT_B3_REQ_COMMAND_3:
14375                 return;
14376         }
14377         sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14378 }
14379
14380
14381 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14382 {
14383         word internal_command;
14384
14385         dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14386                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14387
14388         internal_command = plci->internal_command;
14389         plci->internal_command = 0;
14390         switch (internal_command)
14391         {
14392         default:
14393                 plci->command = 0;
14394         case RTP_CONNECT_B3_RES_COMMAND_1:
14395                 if (plci_nl_busy(plci))
14396                 {
14397                         plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14398                         return;
14399                 }
14400                 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14401                 nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14402                 send_req(plci);
14403                 return;
14404         case RTP_CONNECT_B3_RES_COMMAND_2:
14405                 if ((Rc != OK) && (Rc != OK_FC))
14406                 {
14407                         dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14408                                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14409                         break;
14410                 }
14411                 if (plci_nl_busy(plci))
14412                 {
14413                         plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14414                         return;
14415                 }
14416                 sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14417                 plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14418                 plci->NData[0].PLength = plci->internal_req_buffer[0];
14419                 plci->NData[0].P = plci->internal_req_buffer + 1;
14420                 plci->NL.X = plci->NData;
14421                 plci->NL.ReqCh = 0;
14422                 plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14423                 plci->adapter->request(&plci->NL);
14424                 return;
14425         case RTP_CONNECT_B3_RES_COMMAND_3:
14426                 return;
14427         }
14428 }
14429
14430
14431
14432 static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14433 {
14434         byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14435         word Info;
14436         word internal_command;
14437
14438         dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14439                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14440
14441         Info = GOOD;
14442         internal_command = plci->internal_command;
14443         plci->internal_command = 0;
14444         switch (internal_command)
14445         {
14446         default:
14447                 if (!plci->NL.Id)
14448                         break;
14449                 plci->command = 0;
14450                 plci->adjust_b_parms_msg = NULL;
14451                 plci->adjust_b_facilities = plci->B1_facilities;
14452                 plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14453                 plci->adjust_b_ncci = (word)(Id >> 16);
14454                 plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14455                 plci->adjust_b_state = ADJUST_B_START;
14456                 dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14457                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14458         case HOLD_SAVE_COMMAND_1:
14459                 Info = adjust_b_process(Id, plci, Rc);
14460                 if (Info != GOOD)
14461                 {
14462                         dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14463                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14464                         break;
14465                 }
14466                 if (plci->internal_command)
14467                         return;
14468         }
14469         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14470 }
14471
14472
14473 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14474 {
14475         byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14476         word Info;
14477         word internal_command;
14478
14479         dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14480                         UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14481
14482         Info = GOOD;
14483         internal_command = plci->internal_command;
14484         plci->internal_command = 0;
14485         switch (internal_command)
14486         {
14487         default:
14488                 plci->command = 0;
14489                 plci->adjust_b_parms_msg = NULL;
14490                 plci->adjust_b_facilities = plci->B1_facilities;
14491                 plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14492                 plci->adjust_b_ncci = (word)(Id >> 16);
14493                 plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14494                 plci->adjust_b_state = ADJUST_B_START;
14495                 dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14496                                 UnMapId(Id), (char *)(FILE_), __LINE__));
14497         case RETRIEVE_RESTORE_COMMAND_1:
14498                 Info = adjust_b_process(Id, plci, Rc);
14499                 if (Info != GOOD)
14500                 {
14501                         dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14502                                         UnMapId(Id), (char *)(FILE_), __LINE__));
14503                         break;
14504                 }
14505                 if (plci->internal_command)
14506                         return;
14507         }
14508         sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14509 }
14510
14511
14512 static void init_b1_config(PLCI *plci)
14513 {
14514
14515         dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14516                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14517                         (char *)(FILE_), __LINE__));
14518
14519         plci->B1_resource = 0;
14520         plci->B1_facilities = 0;
14521
14522         plci->li_bchannel_id = 0;
14523         mixer_clear_config(plci);
14524
14525
14526         ec_clear_config(plci);
14527
14528
14529         dtmf_rec_clear_config(plci);
14530         dtmf_send_clear_config(plci);
14531         dtmf_parameter_clear_config(plci);
14532
14533         adv_voice_clear_config(plci);
14534         adjust_b_clear(plci);
14535 }
14536
14537
14538 static void clear_b1_config(PLCI *plci)
14539 {
14540
14541         dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14542                         (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14543                         (char *)(FILE_), __LINE__));
14544
14545         adv_voice_clear_config(plci);
14546         adjust_b_clear(plci);
14547
14548         ec_clear_config(plci);
14549
14550
14551         dtmf_rec_clear_config(plci);
14552         dtmf_send_clear_config(plci);
14553         dtmf_parameter_clear_config(plci);
14554
14555
14556         if ((plci->li_bchannel_id != 0)
14557             && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14558         {
14559                 mixer_clear_config(plci);
14560                 li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14561                 plci->li_bchannel_id = 0;
14562         }
14563
14564         plci->B1_resource = 0;
14565         plci->B1_facilities = 0;
14566 }
14567
14568
14569 /* -----------------------------------------------------------------
14570    XON protocol local helpers
14571    ----------------------------------------------------------------- */
14572 static void channel_flow_control_remove(PLCI *plci) {
14573         DIVA_CAPI_ADAPTER *a = plci->adapter;
14574         word i;
14575         for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14576                 if (a->ch_flow_plci[i] == plci->Id) {
14577                         a->ch_flow_plci[i] = 0;
14578                         a->ch_flow_control[i] = 0;
14579                 }
14580         }
14581 }
14582
14583 static void channel_x_on(PLCI *plci, byte ch) {
14584         DIVA_CAPI_ADAPTER *a = plci->adapter;
14585         if (a->ch_flow_control[ch] & N_XON_SENT) {
14586                 a->ch_flow_control[ch] &= ~N_XON_SENT;
14587         }
14588 }
14589
14590 static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14591         DIVA_CAPI_ADAPTER *a = plci->adapter;
14592         if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14593                 a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14594                 a->ch_flow_plci[ch] = plci->Id;
14595                 a->ch_flow_control_pending++;
14596         }
14597 }
14598
14599 static void channel_request_xon(PLCI *plci, byte ch) {
14600         DIVA_CAPI_ADAPTER *a = plci->adapter;
14601
14602         if (a->ch_flow_control[ch] & N_CH_XOFF) {
14603                 a->ch_flow_control[ch] |= N_XON_REQ;
14604                 a->ch_flow_control[ch] &= ~N_CH_XOFF;
14605                 a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14606         }
14607 }
14608
14609 static void channel_xmit_extended_xon(PLCI *plci) {
14610         DIVA_CAPI_ADAPTER *a;
14611         int max_ch = ARRAY_SIZE(a->ch_flow_control);
14612         int i, one_requested = 0;
14613
14614         if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14615                 return;
14616         }
14617
14618         for (i = 0; i < max_ch; i++) {
14619                 if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14620                     (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14621                     (plci->Id == a->ch_flow_plci[i])) {
14622                         channel_request_xon(plci, (byte)i);
14623                         one_requested = 1;
14624                 }
14625         }
14626
14627         if (one_requested) {
14628                 channel_xmit_xon(plci);
14629         }
14630 }
14631
14632 /*
14633   Try to xmit next X_ON
14634 */
14635 static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14636         int max_ch = ARRAY_SIZE(a->ch_flow_control);
14637         int i;
14638
14639         if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14640                 return (0);
14641         }
14642
14643         if (a->last_flow_control_ch >= max_ch) {
14644                 a->last_flow_control_ch = 1;
14645         }
14646         for (i = a->last_flow_control_ch; i < max_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         for (i = 1; i < a->last_flow_control_ch; i++) {
14655                 if ((a->ch_flow_control[i] & N_XON_REQ) &&
14656                     (plci->Id == a->ch_flow_plci[i])) {
14657                         a->last_flow_control_ch = i + 1;
14658                         return (i);
14659                 }
14660         }
14661
14662         return (0);
14663 }
14664
14665 static void channel_xmit_xon(PLCI *plci) {
14666         DIVA_CAPI_ADAPTER *a = plci->adapter;
14667         byte ch;
14668
14669         if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14670                 return;
14671         }
14672         if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14673                 return;
14674         }
14675         a->ch_flow_control[ch] &= ~N_XON_REQ;
14676         a->ch_flow_control[ch] |= N_XON_SENT;
14677
14678         plci->NL.Req = plci->nl_req = (byte)N_XON;
14679         plci->NL.ReqCh         = ch;
14680         plci->NL.X             = plci->NData;
14681         plci->NL.XNum          = 1;
14682         plci->NData[0].P       = &plci->RBuffer[0];
14683         plci->NData[0].PLength = 0;
14684
14685         plci->adapter->request(&plci->NL);
14686 }
14687
14688 static int channel_can_xon(PLCI *plci, byte ch) {
14689         APPL *APPLptr;
14690         DIVA_CAPI_ADAPTER *a;
14691         word NCCIcode;
14692         dword count;
14693         word Num;
14694         word i;
14695
14696         APPLptr = plci->appl;
14697         a = plci->adapter;
14698
14699         if (!APPLptr)
14700                 return (0);
14701
14702         NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14703
14704         /* count all buffers within the Application pool    */
14705         /* belonging to the same NCCI. XON if a first is    */
14706         /* used.                                            */
14707         count = 0;
14708         Num = 0xffff;
14709         for (i = 0; i < APPLptr->MaxBuffer; i++) {
14710                 if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14711                 if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14712         }
14713         if ((count > 2) || (Num == 0xffff)) {
14714                 return (0);
14715         }
14716         return (1);
14717 }
14718
14719
14720 /*------------------------------------------------------------------*/
14721
14722 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14723 {
14724         return 1;
14725 }
14726
14727
14728
14729 /**********************************************************************************/
14730 /* function groups the listening applications according to the CIP mask and the   */
14731 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14732 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14733 /* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14734 /* function must be enabled by setting "a->group_optimization_enabled" from the   */
14735 /* OS specific part (per adapter).                                                */
14736 /**********************************************************************************/
14737 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14738 {
14739         word i, j, k, busy, group_found;
14740         dword info_mask_group[MAX_CIP_TYPES];
14741         dword cip_mask_group[MAX_CIP_TYPES];
14742         word appl_number_group_type[MAX_APPL];
14743         PLCI *auxplci;
14744
14745         set_group_ind_mask(plci); /* all APPLs within this inc. call are allowed to dial in */
14746
14747         if (!a->group_optimization_enabled)
14748         {
14749                 dbug(1, dprintf("No group optimization"));
14750                 return;
14751         }
14752
14753         dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14754
14755         for (i = 0; i < MAX_CIP_TYPES; i++)
14756         {
14757                 info_mask_group[i] = 0;
14758                 cip_mask_group[i] = 0;
14759         }
14760         for (i = 0; i < MAX_APPL; i++)
14761         {
14762                 appl_number_group_type[i] = 0;
14763         }
14764         for (i = 0; i < max_appl; i++) /* check if any multi instance capable application is present */
14765         {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14766                 if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14767                 {
14768                         dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14769                         return; /* allow good application unfiltered access */
14770                 }
14771         }
14772         for (i = 0; i < max_appl; i++) /* Build CIP Groups */
14773         {
14774                 if (application[i].Id && a->CIP_Mask[i])
14775                 {
14776                         for (k = 0, busy = false; k < a->max_plci; k++)
14777                         {
14778                                 if (a->plci[k].Id)
14779                                 {
14780                                         auxplci = &a->plci[k];
14781                                         if (auxplci->appl == &application[i]) /* application has a busy PLCI */
14782                                         {
14783                                                 busy = true;
14784                                                 dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14785                                         }
14786                                         else if (test_c_ind_mask_bit(auxplci, i)) /* application has an incoming call pending */
14787                                         {
14788                                                 busy = true;
14789                                                 dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14790                                         }
14791                                 }
14792                         }
14793
14794                         for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++)     /* build groups with free applications only */
14795                         {
14796                                 if (j == MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14797                                 {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14798                                         appl_number_group_type[i] = MAX_CIP_TYPES;
14799                                         group_found = true;
14800                                         dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14801                                 }
14802                                 else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14803                                 {                                      /* is group already present ?                  */
14804                                         appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14805                                         group_found = true;
14806                                         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]));
14807                                 }
14808                                 else if (!info_mask_group[j])
14809                                 {                                      /* establish a new group                       */
14810                                         appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14811                                         info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14812                                         cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14813                                         group_found = true;
14814                                         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]));
14815                                 }
14816                         }
14817                 }
14818         }
14819
14820         for (i = 0; i < max_appl; i++) /* Build group_optimization_mask_table */
14821         {
14822                 if (appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14823                 {
14824                         if (appl_number_group_type[i] == MAX_CIP_TYPES)
14825                         {
14826                                 dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14827                         }
14828                         else
14829                         {
14830                                 dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14831                                 for (j = i + 1; j < max_appl; j++)   /* search other group members and mark them as busy        */
14832                                 {
14833                                         if (appl_number_group_type[i] == appl_number_group_type[j])
14834                                         {
14835                                                 dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14836                                                 clear_group_ind_mask_bit(plci, j);           /* disable call on other group members */
14837                                                 appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14838                                         }
14839                                 }
14840                         }
14841                 }
14842                 else                                                 /* application should not get a call */
14843                 {
14844                         clear_group_ind_mask_bit(plci, i);
14845                 }
14846         }
14847
14848 }
14849
14850
14851
14852 /* OS notifies the driver about a application Capi_Register */
14853 word CapiRegister(word id)
14854 {
14855         word i, j, appls_found;
14856
14857         PLCI *plci;
14858         DIVA_CAPI_ADAPTER *a;
14859
14860         for (i = 0, appls_found = 0; i < max_appl; i++)
14861         {
14862                 if (application[i].Id && (application[i].Id != id))
14863                 {
14864                         appls_found++;                       /* an application has been found */
14865                 }
14866         }
14867
14868         if (appls_found) return true;
14869         for (i = 0; i < max_adapter; i++)                   /* scan all adapters...    */
14870         {
14871                 a = &adapter[i];
14872                 if (a->request)
14873                 {
14874                         if (a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14875                         {
14876                                 if (!appls_found)           /* first application does a capi register   */
14877                                 {
14878                                         if ((j = get_plci(a)))                    /* activate L1 of all adapters */
14879                                         {
14880                                                 plci = &a->plci[j - 1];
14881                                                 plci->command = 0;
14882                                                 add_p(plci, OAD, "\x01\xfd");
14883                                                 add_p(plci, CAI, "\x01\x80");
14884                                                 add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14885                                                 add_p(plci, SHIFT | 6, NULL);
14886                                                 add_p(plci, SIN, "\x02\x00\x00");
14887                                                 plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14888                                                 sig_req(plci, ASSIGN, DSIG_ID);
14889                                                 add_p(plci, FTY, "\x02\xff\x07"); /* l1 start */
14890                                                 sig_req(plci, SIG_CTRL, 0);
14891                                                 send_req(plci);
14892                                         }
14893                                 }
14894                         }
14895                 }
14896         }
14897         return false;
14898 }
14899
14900 /*------------------------------------------------------------------*/
14901
14902 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14903
14904 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14905 {
14906         word i;
14907         /* Format of vswitch_t:
14908            0 byte length
14909            1 byte VSWITCHIE
14910            2 byte VSWITCH_REQ/VSWITCH_IND
14911            3 byte reserved
14912            4 word VSwitchcommand
14913            6 word returnerror
14914            8... Params
14915         */
14916         if (!plci ||
14917             !plci->appl ||
14918             !plci->State ||
14919             plci->Sig.Ind == NCR_FACILITY
14920                 )
14921                 return;
14922
14923         for (i = 0; i < MAX_MULTI_IE; i++)
14924         {
14925                 if (!parms[i][0]) continue;
14926                 if (parms[i][0] < 7)
14927                 {
14928                         parms[i][0] = 0; /* kill it */
14929                         continue;
14930                 }
14931                 dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14932                 switch (parms[i][4])
14933                 {
14934                 case VSJOIN:
14935                         if (!plci->relatedPTYPLCI ||
14936                             (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14937                         { /* Error */
14938                                 break;
14939                         }
14940                         /* remember all necessary informations */
14941                         if (parms[i][0] != 11 || parms[i][8] != 3) /* Length Test */
14942                         {
14943                                 break;
14944                         }
14945                         if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14946                         {   /* first indication after ECT-Request on Consultation Call */
14947                                 plci->vswitchstate = parms[i][9];
14948                                 parms[i][9] = 2; /* State */
14949                                 /* now ask first Call to join */
14950                         }
14951                         else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14952                         { /* Answer of VSWITCH_REQ from first Call */
14953                                 plci->vswitchstate = parms[i][9];
14954                                 /* tell consultation call to join
14955                                    and the protocol capabilities of the first call */
14956                         }
14957                         else
14958                         { /* Error */
14959                                 break;
14960                         }
14961                         plci->vsprot = parms[i][10]; /* protocol */
14962                         plci->vsprotdialect = parms[i][11]; /* protocoldialect */
14963                         /* send join request to related PLCI */
14964                         parms[i][1] = VSWITCHIE;
14965                         parms[i][2] = VSWITCH_REQ;
14966
14967                         plci->relatedPTYPLCI->command = 0;
14968                         plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14969                         add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14970                         sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14971                         send_req(plci->relatedPTYPLCI);
14972                         break;
14973                 case VSTRANSPORT:
14974                 default:
14975                         if (plci->relatedPTYPLCI &&
14976                             plci->vswitchstate == 3 &&
14977                             plci->relatedPTYPLCI->vswitchstate == 3)
14978                         {
14979                                 add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14980                                 sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14981                                 send_req(plci->relatedPTYPLCI);
14982                         }
14983                         break;
14984                 }
14985                 parms[i][0] = 0; /* kill it */
14986         }
14987 }
14988
14989
14990 /*------------------------------------------------------------------*/
14991
14992 static int diva_get_dma_descriptor(PLCI *plci, dword   *dma_magic) {
14993         ENTITY e;
14994         IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14995
14996         if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14997                 return (-1);
14998         }
14999
15000         pReq->xdi_dma_descriptor_operation.Req = 0;
15001         pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15002
15003         pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
15004         pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
15005         pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15006         pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15007
15008         e.user[0] = plci->adapter->Id - 1;
15009         plci->adapter->request((ENTITY *)pReq);
15010
15011         if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15012             (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15013             pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15014                 *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15015                 dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
15016                                 plci->adapter->Id,
15017                                 pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15018                                 *dma_magic));
15019                 return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15020         } else {
15021                 dbug(1, dprintf("dma_alloc failed"));
15022                 return (-1);
15023         }
15024 }
15025
15026 static void diva_free_dma_descriptor(PLCI *plci, int nr) {
15027         ENTITY e;
15028         IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
15029
15030         if (nr < 0) {
15031                 return;
15032         }
15033
15034         pReq->xdi_dma_descriptor_operation.Req = 0;
15035         pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15036
15037         pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15038         pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
15039         pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15040         pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15041
15042         e.user[0] = plci->adapter->Id - 1;
15043         plci->adapter->request((ENTITY *)pReq);
15044
15045         if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15046                 dbug(1, dprintf("dma_free(%d)", nr));
15047         } else {
15048                 dbug(1, dprintf("dma_free failed (%d)", nr));
15049         }
15050 }
15051
15052 /*------------------------------------------------------------------*/