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