1 /*
2  *
3  Copyright (c) Eicon Networks, 2002.
4  *
5  This source file is supplied for the use with
6  Eicon Networks range of DIVA Server Adapters.
7  *
8  Eicon File Revision :    2.1
9  *
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2, or (at your option)
13  any later version.
14  *
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
17  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18  See the GNU General Public License for more details.
19  *
20  You should have received a copy of the GNU General Public License
21  along with this program; if not, write to the Free Software
22  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25 
26 #include <linux/bitmap.h>
27 
28 #include "platform.h"
29 #include "di_defs.h"
30 #include "pc.h"
31 #include "capi20.h"
32 #include "divacapi.h"
33 #include "mdm_msg.h"
34 #include "divasync.h"
35 
36 #define FILE_ "MESSAGE.C"
37 #define dprintf
38 
39 /*------------------------------------------------------------------*/
40 /* This is options supported for all adapters that are server by    */
41 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
42 /* and it is not necessary to save it separate for every adapter    */
43 /* Macrose defined here have only local meaning                     */
44 /*------------------------------------------------------------------*/
45 static dword diva_xdi_extended_features = 0;
46 
47 #define DIVA_CAPI_USE_CMA                 0x00000001
48 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR  0x00000002
49 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL  0x00000004
50 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA     0x00000008
51 
52 /*
53   CAPI can request to process all return codes self only if:
54   protocol code supports this && xdi supports this
55 */
56 #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__)   (((__a__)->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL) && ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) && (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
57 
58 /*------------------------------------------------------------------*/
59 /* local function prototypes                                        */
60 /*------------------------------------------------------------------*/
61 
62 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci);
63 void AutomaticLaw(DIVA_CAPI_ADAPTER *);
64 word CapiRelease(word);
65 word CapiRegister(word);
66 word api_put(APPL *, CAPI_MSG *);
67 static word api_parse(byte *, word, byte *, API_PARSE *);
68 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out);
69 static void api_load_msg(API_SAVE *in, API_PARSE *out);
70 
71 word api_remove_start(void);
72 void api_remove_complete(void);
73 
74 static void plci_remove(PLCI *);
75 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a);
76 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *);
77 
78 void callback(ENTITY *);
79 
80 static void control_rc(PLCI *, byte, byte, byte, byte, byte);
81 static void data_rc(PLCI *, byte);
82 static void data_ack(PLCI *, byte);
83 static void sig_ind(PLCI *);
84 static void SendInfo(PLCI *, dword, byte **, byte);
85 static void SendSetupInfo(APPL *, PLCI *, dword, byte **, byte);
86 static void SendSSExtInd(APPL *, PLCI *plci, dword Id, byte **parms);
87 
88 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
89 
90 static void nl_ind(PLCI *);
91 
92 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
93 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
94 static byte connect_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
95 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
96 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
97 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
98 static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
99 static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
100 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
101 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
102 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
103 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
104 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
105 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
106 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
107 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
108 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
109 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
110 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
111 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
112 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
113 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
114 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
115 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
116 
117 static word get_plci(DIVA_CAPI_ADAPTER *);
118 static void add_p(PLCI *, byte, byte *);
119 static void add_s(PLCI *plci, byte code, API_PARSE *p);
120 static void add_ss(PLCI *plci, byte code, API_PARSE *p);
121 static void add_ie(PLCI *plci, byte code, byte *p, word p_length);
122 static void add_d(PLCI *, word, byte *);
123 static void add_ai(PLCI *, API_PARSE *);
124 static word add_b1(PLCI *, API_PARSE *, word, word);
125 static word add_b23(PLCI *, API_PARSE *);
126 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms);
127 static void sig_req(PLCI *, byte, byte);
128 static void nl_req_ncci(PLCI *, byte, byte);
129 static void send_req(PLCI *);
130 static void send_data(PLCI *);
131 static word plci_remove_check(PLCI *);
132 static void listen_check(DIVA_CAPI_ADAPTER *);
133 static byte AddInfo(byte **, byte **, byte *, byte *);
134 static byte getChannel(API_PARSE *);
135 static void IndParse(PLCI *, const word *, byte **, byte);
136 static byte ie_compare(byte *, byte *);
137 static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *);
138 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *, word);
139 
140 /*
141   XON protocol helpers
142 */
143 static void channel_flow_control_remove(PLCI *plci);
144 static void channel_x_off(PLCI *plci, byte ch, byte flag);
145 static void channel_x_on(PLCI *plci, byte ch);
146 static void channel_request_xon(PLCI *plci, byte ch);
147 static void channel_xmit_xon(PLCI *plci);
148 static int channel_can_xon(PLCI *plci, byte ch);
149 static void channel_xmit_extended_xon(PLCI *plci);
150 
151 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type, dword info_mask, byte setupParse);
152 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte);
153 static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *);
154 static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER *);
155 static void VoiceChannelOff(PLCI *plci);
156 static void adv_voice_write_coefs(PLCI *plci, word write_command);
157 static void adv_voice_clear_config(PLCI *plci);
158 
159 static word get_b1_facilities(PLCI *plci, byte b1_resource);
160 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities);
161 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities);
162 static word adjust_b_process(dword Id, PLCI *plci, byte Rc);
163 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command);
164 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc);
165 static void reset_b3_command(dword Id, PLCI *plci, byte Rc);
166 static void select_b_command(dword Id, PLCI *plci, byte Rc);
167 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc);
168 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc);
169 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc);
170 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc);
171 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc);
172 static void hold_save_command(dword Id, PLCI *plci, byte Rc);
173 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc);
174 static void init_b1_config(PLCI *plci);
175 static void clear_b1_config(PLCI *plci);
176 
177 static void dtmf_command(dword Id, PLCI *plci, byte Rc);
178 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
179 static void dtmf_confirmation(dword Id, PLCI *plci);
180 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length);
181 static void dtmf_parameter_write(PLCI *plci);
182 
183 
184 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id);
185 static void mixer_set_bchannel_id(PLCI *plci, byte *chi);
186 static void mixer_clear_config(PLCI *plci);
187 static void mixer_notify_update(PLCI *plci, byte others);
188 static void mixer_command(dword Id, PLCI *plci, byte Rc);
189 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
190 static void mixer_indication_coefs_set(dword Id, PLCI *plci);
191 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length);
192 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length);
193 static void mixer_remove(PLCI *plci);
194 
195 
196 static void ec_command(dword Id, PLCI *plci, byte Rc);
197 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
198 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length);
199 
200 
201 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc);
202 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc);
203 
204 
205 static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic);
206 static void diva_free_dma_descriptor(PLCI *plci, int nr);
207 
208 /*------------------------------------------------------------------*/
209 /* external function prototypes                                     */
210 /*------------------------------------------------------------------*/
211 
212 extern byte MapController(byte);
213 extern byte UnMapController(byte);
214 #define MapId(Id)(((Id) & 0xffffff00L) | MapController((byte)(Id)))
215 #define UnMapId(Id)(((Id) & 0xffffff00L) | UnMapController((byte)(Id)))
216 
217 void sendf(APPL *, word, dword, word, byte *, ...);
218 void *TransmitBufferSet(APPL *appl, dword ref);
219 void *TransmitBufferGet(APPL *appl, void *p);
220 void TransmitBufferFree(APPL *appl, void *p);
221 void *ReceiveBufferGet(APPL *appl, int Num);
222 
223 int fax_head_line_time(char *buffer);
224 
225 
226 /*------------------------------------------------------------------*/
227 /* Global data definitions                                          */
228 /*------------------------------------------------------------------*/
229 extern byte max_adapter;
230 extern byte max_appl;
231 extern DIVA_CAPI_ADAPTER *adapter;
232 extern APPL *application;
233 
234 
235 
236 
237 
238 
239 
240 static byte remove_started = false;
241 static PLCI dummy_plci;
242 
243 
244 static struct _ftable {
245 	word command;
246 	byte *format;
247 	byte (*function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
248 } ftable[] = {
249 	{_DATA_B3_R,                          "dwww",         data_b3_req},
250 	{_DATA_B3_I | RESPONSE,               "w",            data_b3_res},
251 	{_INFO_R,                             "ss",           info_req},
252 	{_INFO_I | RESPONSE,                  "",             info_res},
253 	{_CONNECT_R,                          "wsssssssss",   connect_req},
254 	{_CONNECT_I | RESPONSE,               "wsssss",       connect_res},
255 	{_CONNECT_ACTIVE_I | RESPONSE,        "",             connect_a_res},
256 	{_DISCONNECT_R,                       "s",            disconnect_req},
257 	{_DISCONNECT_I | RESPONSE,            "",             disconnect_res},
258 	{_LISTEN_R,                           "dddss",        listen_req},
259 	{_ALERT_R,                            "s",            alert_req},
260 	{_FACILITY_R,                         "ws",           facility_req},
261 	{_FACILITY_I | RESPONSE,              "ws",           facility_res},
262 	{_CONNECT_B3_R,                       "s",            connect_b3_req},
263 	{_CONNECT_B3_I | RESPONSE,            "ws",           connect_b3_res},
264 	{_CONNECT_B3_ACTIVE_I | RESPONSE,     "",             connect_b3_a_res},
265 	{_DISCONNECT_B3_R,                    "s",            disconnect_b3_req},
266 	{_DISCONNECT_B3_I | RESPONSE,         "",             disconnect_b3_res},
267 	{_RESET_B3_R,                         "s",            reset_b3_req},
268 	{_RESET_B3_I | RESPONSE,              "",             reset_b3_res},
269 	{_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "ws",           connect_b3_t90_a_res},
270 	{_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "",             connect_b3_t90_a_res},
271 	{_SELECT_B_REQ,                       "s",            select_b_req},
272 	{_MANUFACTURER_R,                     "dws",          manufacturer_req},
273 	{_MANUFACTURER_I | RESPONSE,          "dws",          manufacturer_res},
274 	{_MANUFACTURER_I | RESPONSE,          "",             manufacturer_res}
275 };
276 
277 static byte *cip_bc[29][2] = {
278 	{ "",                     ""                     }, /* 0 */
279 	{ "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 1 */
280 	{ "\x02\x88\x90",         "\x02\x88\x90"         }, /* 2 */
281 	{ "\x02\x89\x90",         "\x02\x89\x90"         }, /* 3 */
282 	{ "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 4 */
283 	{ "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 5 */
284 	{ "\x02\x98\x90",         "\x02\x98\x90"         }, /* 6 */
285 	{ "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
286 	{ "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
287 	{ "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 9 */
288 	{ "",                     ""                     }, /* 10 */
289 	{ "",                     ""                     }, /* 11 */
290 	{ "",                     ""                     }, /* 12 */
291 	{ "",                     ""                     }, /* 13 */
292 	{ "",                     ""                     }, /* 14 */
293 	{ "",                     ""                     }, /* 15 */
294 
295 	{ "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 16 */
296 	{ "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 17 */
297 	{ "\x02\x88\x90",         "\x02\x88\x90"         }, /* 18 */
298 	{ "\x02\x88\x90",         "\x02\x88\x90"         }, /* 19 */
299 	{ "\x02\x88\x90",         "\x02\x88\x90"         }, /* 20 */
300 	{ "\x02\x88\x90",         "\x02\x88\x90"         }, /* 21 */
301 	{ "\x02\x88\x90",         "\x02\x88\x90"         }, /* 22 */
302 	{ "\x02\x88\x90",         "\x02\x88\x90"         }, /* 23 */
303 	{ "\x02\x88\x90",         "\x02\x88\x90"         }, /* 24 */
304 	{ "\x02\x88\x90",         "\x02\x88\x90"         }, /* 25 */
305 	{ "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 26 */
306 	{ "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 27 */
307 	{ "\x02\x88\x90",         "\x02\x88\x90"         }  /* 28 */
308 };
309 
310 static byte *cip_hlc[29] = {
311 	"",                           /* 0 */
312 	"",                           /* 1 */
313 	"",                           /* 2 */
314 	"",                           /* 3 */
315 	"",                           /* 4 */
316 	"",                           /* 5 */
317 	"",                           /* 6 */
318 	"",                           /* 7 */
319 	"",                           /* 8 */
320 	"",                           /* 9 */
321 	"",                           /* 10 */
322 	"",                           /* 11 */
323 	"",                           /* 12 */
324 	"",                           /* 13 */
325 	"",                           /* 14 */
326 	"",                           /* 15 */
327 
328 	"\x02\x91\x81",               /* 16 */
329 	"\x02\x91\x84",               /* 17 */
330 	"\x02\x91\xa1",               /* 18 */
331 	"\x02\x91\xa4",               /* 19 */
332 	"\x02\x91\xa8",               /* 20 */
333 	"\x02\x91\xb1",               /* 21 */
334 	"\x02\x91\xb2",               /* 22 */
335 	"\x02\x91\xb5",               /* 23 */
336 	"\x02\x91\xb8",               /* 24 */
337 	"\x02\x91\xc1",               /* 25 */
338 	"\x02\x91\x81",               /* 26 */
339 	"\x03\x91\xe0\x01",           /* 27 */
340 	"\x03\x91\xe0\x02"            /* 28 */
341 };
342 
343 /*------------------------------------------------------------------*/
344 
345 #define V120_HEADER_LENGTH 1
346 #define V120_HEADER_EXTEND_BIT  0x80
347 #define V120_HEADER_BREAK_BIT   0x40
348 #define V120_HEADER_C1_BIT      0x04
349 #define V120_HEADER_C2_BIT      0x08
350 #define V120_HEADER_FLUSH_COND  (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
351 
352 static byte v120_default_header[] =
353 {
354 
355 	0x83                          /*  Ext, BR , res, res, C2 , C1 , B  , F   */
356 
357 };
358 
359 static byte v120_break_header[] =
360 {
361 
362 	0xc3 | V120_HEADER_BREAK_BIT  /*  Ext, BR , res, res, C2 , C1 , B  , F   */
363 
364 };
365 
366 
367 /*------------------------------------------------------------------*/
368 /* API_PUT function                                                 */
369 /*------------------------------------------------------------------*/
370 
api_put(APPL * appl,CAPI_MSG * msg)371 word api_put(APPL *appl, CAPI_MSG *msg)
372 {
373 	word i, j, k, l, n;
374 	word ret;
375 	byte c;
376 	byte controller;
377 	DIVA_CAPI_ADAPTER *a;
378 	PLCI *plci;
379 	NCCI *ncci_ptr;
380 	word ncci;
381 	CAPI_MSG *m;
382 	API_PARSE msg_parms[MAX_MSG_PARMS + 1];
383 
384 	if (msg->header.length < sizeof(msg->header) ||
385 	    msg->header.length > MAX_MSG_SIZE) {
386 		dbug(1, dprintf("bad len"));
387 		return _BAD_MSG;
388 	}
389 
390 	controller = (byte)((msg->header.controller & 0x7f) - 1);
391 
392 	/* controller starts with 0 up to (max_adapter - 1) */
393 	if (controller >= max_adapter)
394 	{
395 		dbug(1, dprintf("invalid ctrl"));
396 		return _BAD_MSG;
397 	}
398 
399 	a = &adapter[controller];
400 	plci = NULL;
401 	if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
402 	{
403 		dbug(1, dprintf("plci=%x", msg->header.plci));
404 		plci = &a->plci[msg->header.plci - 1];
405 		ncci = GET_WORD(&msg->header.ncci);
406 		if (plci->Id
407 		    && (plci->appl
408 			|| (plci->State == INC_CON_PENDING)
409 			|| (plci->State == INC_CON_ALERT)
410 			|| (msg->header.command == (_DISCONNECT_I | RESPONSE)))
411 		    && ((ncci == 0)
412 			|| (msg->header.command == (_DISCONNECT_B3_I | RESPONSE))
413 			|| ((ncci < MAX_NCCI + 1) && (a->ncci_plci[ncci] == plci->Id))))
414 		{
415 			i = plci->msg_in_read_pos;
416 			j = plci->msg_in_write_pos;
417 			if (j >= i)
418 			{
419 				if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
420 					i += MSG_IN_QUEUE_SIZE - j;
421 				else
422 					j = 0;
423 			}
424 			else
425 			{
426 
427 				n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
428 
429 				if (i > MSG_IN_QUEUE_SIZE - n)
430 					i = MSG_IN_QUEUE_SIZE - n + 1;
431 				i -= j;
432 			}
433 
434 			if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
435 
436 			{
437 				dbug(0, dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
438 						msg->header.length, plci->msg_in_write_pos,
439 						plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
440 
441 				return _QUEUE_FULL;
442 			}
443 			c = false;
444 			if ((((byte *) msg) < ((byte *)(plci->msg_in_queue)))
445 			    || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
446 			{
447 				if (plci->msg_in_write_pos != plci->msg_in_read_pos)
448 					c = true;
449 			}
450 			if (msg->header.command == _DATA_B3_R)
451 			{
452 				if (msg->header.length < 20)
453 				{
454 					dbug(1, dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
455 					return _BAD_MSG;
456 				}
457 				ncci_ptr = &(a->ncci[ncci]);
458 				n = ncci_ptr->data_pending;
459 				l = ncci_ptr->data_ack_pending;
460 				k = plci->msg_in_read_pos;
461 				while (k != plci->msg_in_write_pos)
462 				{
463 					if (k == plci->msg_in_wrap_pos)
464 						k = 0;
465 					if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
466 					    && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
467 					{
468 						n++;
469 						if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
470 							l++;
471 					}
472 
473 					k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
474 					      MSG_IN_OVERHEAD + 3) & 0xfffc;
475 
476 				}
477 				if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
478 				{
479 					dbug(0, dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
480 							ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
481 
482 					return _QUEUE_FULL;
483 				}
484 				if (plci->req_in || plci->internal_command)
485 				{
486 					if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
487 					    && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
488 					{
489 						dbug(0, dprintf("Q-FULL3(requeue)"));
490 
491 						return _QUEUE_FULL;
492 					}
493 					c = true;
494 				}
495 			}
496 			else
497 			{
498 				if (plci->req_in || plci->internal_command)
499 					c = true;
500 				else
501 				{
502 					plci->command = msg->header.command;
503 					plci->number = msg->header.number;
504 				}
505 			}
506 			if (c)
507 			{
508 				dbug(1, dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
509 						msg->header.command, plci->req_in, plci->internal_command,
510 						msg->header.length, plci->msg_in_write_pos,
511 						plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
512 				if (j == 0)
513 					plci->msg_in_wrap_pos = plci->msg_in_write_pos;
514 				m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
515 				for (i = 0; i < msg->header.length; i++)
516 					((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i];
517 				if (m->header.command == _DATA_B3_R)
518 				{
519 
520 					m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet(appl, m->info.data_b3_req.Data));
521 
522 				}
523 
524 				j = (j + 3) & 0xfffc;
525 
526 				*((APPL **)(&((byte *)(plci->msg_in_queue))[j])) = appl;
527 				plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
528 				return 0;
529 			}
530 		}
531 		else
532 		{
533 			plci = NULL;
534 		}
535 	}
536 	dbug(1, dprintf("com=%x", msg->header.command));
537 
538 	for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
539 	for (i = 0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
540 
541 		if (ftable[i].command == msg->header.command) {
542 			/* break loop if the message is correct, otherwise continue scan  */
543 			/* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */
544 			if (!api_parse(msg->info.b, (word)(msg->header.length - 12), ftable[i].format, msg_parms)) {
545 				ret = 0;
546 				break;
547 			}
548 			for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
549 		}
550 	}
551 	if (ret) {
552 		dbug(1, dprintf("BAD_MSG"));
553 		if (plci) plci->command = 0;
554 		return ret;
555 	}
556 
557 
558 	c = ftable[i].function(GET_DWORD(&msg->header.controller),
559 			       msg->header.number,
560 			       a,
561 			       plci,
562 			       appl,
563 			       msg_parms);
564 
565 	channel_xmit_extended_xon(plci);
566 
567 	if (c == 1) send_req(plci);
568 	if (c == 2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
569 	if (plci && !plci->req_in) plci->command = 0;
570 	return 0;
571 }
572 
573 
574 /*------------------------------------------------------------------*/
575 /* api_parse function, check the format of api messages             */
576 /*------------------------------------------------------------------*/
577 
api_parse(byte * msg,word length,byte * format,API_PARSE * parms)578 static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
579 {
580 	word i;
581 	word p;
582 
583 	for (i = 0, p = 0; format[i]; i++) {
584 		if (parms)
585 		{
586 			parms[i].info = &msg[p];
587 		}
588 		switch (format[i]) {
589 		case 'b':
590 			p += 1;
591 			break;
592 		case 'w':
593 			p += 2;
594 			break;
595 		case 'd':
596 			p += 4;
597 			break;
598 		case 's':
599 			if (msg[p] == 0xff) {
600 				parms[i].info += 2;
601 				parms[i].length = msg[p + 1] + (msg[p + 2] << 8);
602 				p += (parms[i].length + 3);
603 			}
604 			else {
605 				parms[i].length = msg[p];
606 				p += (parms[i].length + 1);
607 			}
608 			break;
609 		}
610 
611 		if (p > length) return true;
612 	}
613 	if (parms) parms[i].info = NULL;
614 	return false;
615 }
616 
api_save_msg(API_PARSE * in,byte * format,API_SAVE * out)617 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
618 {
619 	word i, j, n = 0;
620 	byte *p;
621 
622 	p = out->info;
623 	for (i = 0; format[i] != '\0'; i++)
624 	{
625 		out->parms[i].info = p;
626 		out->parms[i].length = in[i].length;
627 		switch (format[i])
628 		{
629 		case 'b':
630 			n = 1;
631 			break;
632 		case 'w':
633 			n = 2;
634 			break;
635 		case 'd':
636 			n = 4;
637 			break;
638 		case 's':
639 			n = in[i].length + 1;
640 			break;
641 		}
642 		for (j = 0; j < n; j++)
643 			*(p++) = in[i].info[j];
644 	}
645 	out->parms[i].info = NULL;
646 	out->parms[i].length = 0;
647 }
648 
api_load_msg(API_SAVE * in,API_PARSE * out)649 static void api_load_msg(API_SAVE *in, API_PARSE *out)
650 {
651 	word i;
652 
653 	i = 0;
654 	do
655 	{
656 		out[i].info = in->parms[i].info;
657 		out[i].length = in->parms[i].length;
658 	} while (in->parms[i++].info);
659 }
660 
661 
662 /*------------------------------------------------------------------*/
663 /* CAPI remove function                                             */
664 /*------------------------------------------------------------------*/
665 
api_remove_start(void)666 word api_remove_start(void)
667 {
668 	word i;
669 	word j;
670 
671 	if (!remove_started) {
672 		remove_started = true;
673 		for (i = 0; i < max_adapter; i++) {
674 			if (adapter[i].request) {
675 				for (j = 0; j < adapter[i].max_plci; j++) {
676 					if (adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
677 				}
678 			}
679 		}
680 		return 1;
681 	}
682 	else {
683 		for (i = 0; i < max_adapter; i++) {
684 			if (adapter[i].request) {
685 				for (j = 0; j < adapter[i].max_plci; j++) {
686 					if (adapter[i].plci[j].Sig.Id) return 1;
687 				}
688 			}
689 		}
690 	}
691 	api_remove_complete();
692 	return 0;
693 }
694 
695 
696 /*------------------------------------------------------------------*/
697 /* internal command queue                                           */
698 /*------------------------------------------------------------------*/
699 
init_internal_command_queue(PLCI * plci)700 static void init_internal_command_queue(PLCI *plci)
701 {
702 	word i;
703 
704 	dbug(1, dprintf("%s,%d: init_internal_command_queue",
705 			(char *)(FILE_), __LINE__));
706 
707 	plci->internal_command = 0;
708 	for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
709 		plci->internal_command_queue[i] = NULL;
710 }
711 
712 
start_internal_command(dword Id,PLCI * plci,t_std_internal_command command_function)713 static void start_internal_command(dword Id, PLCI *plci, t_std_internal_command command_function)
714 {
715 	word i;
716 
717 	dbug(1, dprintf("[%06lx] %s,%d: start_internal_command",
718 			UnMapId(Id), (char *)(FILE_), __LINE__));
719 
720 	if (plci->internal_command == 0)
721 	{
722 		plci->internal_command_queue[0] = command_function;
723 		(*command_function)(Id, plci, OK);
724 	}
725 	else
726 	{
727 		i = 1;
728 		while (plci->internal_command_queue[i] != NULL)
729 			i++;
730 		plci->internal_command_queue[i] = command_function;
731 	}
732 }
733 
734 
next_internal_command(dword Id,PLCI * plci)735 static void next_internal_command(dword Id, PLCI *plci)
736 {
737 	word i;
738 
739 	dbug(1, dprintf("[%06lx] %s,%d: next_internal_command",
740 			UnMapId(Id), (char *)(FILE_), __LINE__));
741 
742 	plci->internal_command = 0;
743 	plci->internal_command_queue[0] = NULL;
744 	while (plci->internal_command_queue[1] != NULL)
745 	{
746 		for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
747 			plci->internal_command_queue[i] = plci->internal_command_queue[i + 1];
748 		plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
749 		(*(plci->internal_command_queue[0]))(Id, plci, OK);
750 		if (plci->internal_command != 0)
751 			return;
752 		plci->internal_command_queue[0] = NULL;
753 	}
754 }
755 
756 
757 /*------------------------------------------------------------------*/
758 /* NCCI allocate/remove function                                    */
759 /*------------------------------------------------------------------*/
760 
761 static dword ncci_mapping_bug = 0;
762 
get_ncci(PLCI * plci,byte ch,word force_ncci)763 static word get_ncci(PLCI *plci, byte ch, word force_ncci)
764 {
765 	DIVA_CAPI_ADAPTER *a;
766 	word ncci, i, j, k;
767 
768 	a = plci->adapter;
769 	if (!ch || a->ch_ncci[ch])
770 	{
771 		ncci_mapping_bug++;
772 		dbug(1, dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
773 				ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
774 		ncci = ch;
775 	}
776 	else
777 	{
778 		if (force_ncci)
779 			ncci = force_ncci;
780 		else
781 		{
782 			if ((ch < MAX_NCCI + 1) && !a->ncci_ch[ch])
783 				ncci = ch;
784 			else
785 			{
786 				ncci = 1;
787 				while ((ncci < MAX_NCCI + 1) && a->ncci_ch[ncci])
788 					ncci++;
789 				if (ncci == MAX_NCCI + 1)
790 				{
791 					ncci_mapping_bug++;
792 					i = 1;
793 					do
794 					{
795 						j = 1;
796 						while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i))
797 							j++;
798 						k = j;
799 						if (j < MAX_NCCI + 1)
800 						{
801 							do
802 							{
803 								j++;
804 							} while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i));
805 						}
806 					} while ((i < MAX_NL_CHANNEL + 1) && (j < MAX_NCCI + 1));
807 					if (i < MAX_NL_CHANNEL + 1)
808 					{
809 						dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
810 								ncci_mapping_bug, ch, force_ncci, i, k, j));
811 					}
812 					else
813 					{
814 						dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x",
815 								ncci_mapping_bug, ch, force_ncci));
816 					}
817 					ncci = ch;
818 				}
819 			}
820 			a->ncci_plci[ncci] = plci->Id;
821 			a->ncci_state[ncci] = IDLE;
822 			if (!plci->ncci_ring_list)
823 				plci->ncci_ring_list = ncci;
824 			else
825 				a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
826 			a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
827 		}
828 		a->ncci_ch[ncci] = ch;
829 		a->ch_ncci[ch] = (byte) ncci;
830 		dbug(1, dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
831 				ncci_mapping_bug, ch, force_ncci, ch, ncci));
832 	}
833 	return (ncci);
834 }
835 
836 
ncci_free_receive_buffers(PLCI * plci,word ncci)837 static void ncci_free_receive_buffers(PLCI *plci, word ncci)
838 {
839 	DIVA_CAPI_ADAPTER *a;
840 	APPL *appl;
841 	word i, ncci_code;
842 	dword Id;
843 
844 	a = plci->adapter;
845 	Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
846 	if (ncci)
847 	{
848 		if (a->ncci_plci[ncci] == plci->Id)
849 		{
850 			if (!plci->appl)
851 			{
852 				ncci_mapping_bug++;
853 				dbug(1, dprintf("NCCI mapping appl expected %ld %08lx",
854 						ncci_mapping_bug, Id));
855 			}
856 			else
857 			{
858 				appl = plci->appl;
859 				ncci_code = ncci | (((word) a->Id) << 8);
860 				for (i = 0; i < appl->MaxBuffer; i++)
861 				{
862 					if ((appl->DataNCCI[i] == ncci_code)
863 					    && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
864 					{
865 						appl->DataNCCI[i] = 0;
866 					}
867 				}
868 			}
869 		}
870 	}
871 	else
872 	{
873 		for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
874 		{
875 			if (a->ncci_plci[ncci] == plci->Id)
876 			{
877 				if (!plci->appl)
878 				{
879 					ncci_mapping_bug++;
880 					dbug(1, dprintf("NCCI mapping no appl %ld %08lx",
881 							ncci_mapping_bug, Id));
882 				}
883 				else
884 				{
885 					appl = plci->appl;
886 					ncci_code = ncci | (((word) a->Id) << 8);
887 					for (i = 0; i < appl->MaxBuffer; i++)
888 					{
889 						if ((appl->DataNCCI[i] == ncci_code)
890 						    && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
891 						{
892 							appl->DataNCCI[i] = 0;
893 						}
894 					}
895 				}
896 			}
897 		}
898 	}
899 }
900 
901 
cleanup_ncci_data(PLCI * plci,word ncci)902 static void cleanup_ncci_data(PLCI *plci, word ncci)
903 {
904 	NCCI *ncci_ptr;
905 
906 	if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
907 	{
908 		ncci_ptr = &(plci->adapter->ncci[ncci]);
909 		if (plci->appl)
910 		{
911 			while (ncci_ptr->data_pending != 0)
912 			{
913 				if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
914 					TransmitBufferFree(plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
915 				(ncci_ptr->data_out)++;
916 				if (ncci_ptr->data_out == MAX_DATA_B3)
917 					ncci_ptr->data_out = 0;
918 				(ncci_ptr->data_pending)--;
919 			}
920 		}
921 		ncci_ptr->data_out = 0;
922 		ncci_ptr->data_pending = 0;
923 		ncci_ptr->data_ack_out = 0;
924 		ncci_ptr->data_ack_pending = 0;
925 	}
926 }
927 
928 
ncci_remove(PLCI * plci,word ncci,byte preserve_ncci)929 static void ncci_remove(PLCI *plci, word ncci, byte preserve_ncci)
930 {
931 	DIVA_CAPI_ADAPTER *a;
932 	dword Id;
933 	word i;
934 
935 	a = plci->adapter;
936 	Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
937 	if (!preserve_ncci)
938 		ncci_free_receive_buffers(plci, ncci);
939 	if (ncci)
940 	{
941 		if (a->ncci_plci[ncci] != plci->Id)
942 		{
943 			ncci_mapping_bug++;
944 			dbug(1, dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
945 					ncci_mapping_bug, Id, preserve_ncci));
946 		}
947 		else
948 		{
949 			cleanup_ncci_data(plci, ncci);
950 			dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
951 					ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
952 			a->ch_ncci[a->ncci_ch[ncci]] = 0;
953 			if (!preserve_ncci)
954 			{
955 				a->ncci_ch[ncci] = 0;
956 				a->ncci_plci[ncci] = 0;
957 				a->ncci_state[ncci] = IDLE;
958 				i = plci->ncci_ring_list;
959 				while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
960 					i = a->ncci_next[i];
961 				if ((i != 0) && (a->ncci_next[i] == ncci))
962 				{
963 					if (i == ncci)
964 						plci->ncci_ring_list = 0;
965 					else if (plci->ncci_ring_list == ncci)
966 						plci->ncci_ring_list = i;
967 					a->ncci_next[i] = a->ncci_next[ncci];
968 				}
969 				a->ncci_next[ncci] = 0;
970 			}
971 		}
972 	}
973 	else
974 	{
975 		for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
976 		{
977 			if (a->ncci_plci[ncci] == plci->Id)
978 			{
979 				cleanup_ncci_data(plci, ncci);
980 				dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
981 						ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
982 				a->ch_ncci[a->ncci_ch[ncci]] = 0;
983 				if (!preserve_ncci)
984 				{
985 					a->ncci_ch[ncci] = 0;
986 					a->ncci_plci[ncci] = 0;
987 					a->ncci_state[ncci] = IDLE;
988 					a->ncci_next[ncci] = 0;
989 				}
990 			}
991 		}
992 		if (!preserve_ncci)
993 			plci->ncci_ring_list = 0;
994 	}
995 }
996 
997 
998 /*------------------------------------------------------------------*/
999 /* PLCI remove function                                             */
1000 /*------------------------------------------------------------------*/
1001 
plci_free_msg_in_queue(PLCI * plci)1002 static void plci_free_msg_in_queue(PLCI *plci)
1003 {
1004 	word i;
1005 
1006 	if (plci->appl)
1007 	{
1008 		i = plci->msg_in_read_pos;
1009 		while (i != plci->msg_in_write_pos)
1010 		{
1011 			if (i == plci->msg_in_wrap_pos)
1012 				i = 0;
1013 			if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1014 			{
1015 
1016 				TransmitBufferFree(plci->appl,
1017 						   (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1018 
1019 			}
1020 
1021 			i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1022 			      MSG_IN_OVERHEAD + 3) & 0xfffc;
1023 
1024 		}
1025 	}
1026 	plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1027 	plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1028 	plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1029 }
1030 
1031 
plci_remove(PLCI * plci)1032 static void plci_remove(PLCI *plci)
1033 {
1034 
1035 	if (!plci) {
1036 		dbug(1, dprintf("plci_remove(no plci)"));
1037 		return;
1038 	}
1039 	init_internal_command_queue(plci);
1040 	dbug(1, dprintf("plci_remove(%x,tel=%x)", plci->Id, plci->tel));
1041 	if (plci_remove_check(plci))
1042 	{
1043 		return;
1044 	}
1045 	if (plci->Sig.Id == 0xff)
1046 	{
1047 		dbug(1, dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1048 		if (plci->NL.Id && !plci->nl_remove_id)
1049 		{
1050 			nl_req_ncci(plci, REMOVE, 0);
1051 			send_req(plci);
1052 		}
1053 	}
1054 	else
1055 	{
1056 		if (!plci->sig_remove_id
1057 		    && (plci->Sig.Id
1058 			|| (plci->req_in != plci->req_out)
1059 			|| (plci->nl_req || plci->sig_req)))
1060 		{
1061 			sig_req(plci, HANGUP, 0);
1062 			send_req(plci);
1063 		}
1064 	}
1065 	ncci_remove(plci, 0, false);
1066 	plci_free_msg_in_queue(plci);
1067 
1068 	plci->channels = 0;
1069 	plci->appl = NULL;
1070 	if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1071 		plci->State = OUTG_DIS_PENDING;
1072 }
1073 
1074 /*------------------------------------------------------------------*/
1075 /* translation function for each message                            */
1076 /*------------------------------------------------------------------*/
1077 
connect_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)1078 static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1079 			PLCI *plci, APPL *appl, API_PARSE *parms)
1080 {
1081 	word ch;
1082 	word i;
1083 	word Info;
1084 	byte LinkLayer;
1085 	API_PARSE *ai;
1086 	API_PARSE *bp;
1087 	API_PARSE ai_parms[5];
1088 	word channel = 0;
1089 	dword ch_mask;
1090 	byte m;
1091 	static byte esc_chi[35] = {0x02, 0x18, 0x01};
1092 	static byte lli[2] = {0x01, 0x00};
1093 	byte noCh = 0;
1094 	word dir = 0;
1095 	byte *p_chi = "";
1096 
1097 	for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1098 
1099 	dbug(1, dprintf("connect_req(%d)", parms->length));
1100 	Info = _WRONG_IDENTIFIER;
1101 	if (a)
1102 	{
1103 		if (a->adapter_disabled)
1104 		{
1105 			dbug(1, dprintf("adapter disabled"));
1106 			Id = ((word)1 << 8) | a->Id;
1107 			sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
1108 			sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1109 			return false;
1110 		}
1111 		Info = _OUT_OF_PLCI;
1112 		if ((i = get_plci(a)))
1113 		{
1114 			Info = 0;
1115 			plci = &a->plci[i - 1];
1116 			plci->appl = appl;
1117 			plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1118 			/* check 'external controller' bit for codec support */
1119 			if (Id & EXT_CONTROLLER)
1120 			{
1121 				if (AdvCodecSupport(a, plci, appl, 0))
1122 				{
1123 					plci->Id = 0;
1124 					sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1125 					return 2;
1126 				}
1127 			}
1128 			ai = &parms[9];
1129 			bp = &parms[5];
1130 			ch = 0;
1131 			if (bp->length)LinkLayer = bp->info[3];
1132 			else LinkLayer = 0;
1133 			if (ai->length)
1134 			{
1135 				ch = 0xffff;
1136 				if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1137 				{
1138 					ch = 0;
1139 					if (ai_parms[0].length)
1140 					{
1141 						ch = GET_WORD(ai_parms[0].info + 1);
1142 						if (ch > 4) ch = 0; /* safety -> ignore ChannelID */
1143 						if (ch == 4) /* explizit CHI in message */
1144 						{
1145 							/* check length of B-CH struct */
1146 							if ((ai_parms[0].info)[3] >= 1)
1147 							{
1148 								if ((ai_parms[0].info)[4] == CHI)
1149 								{
1150 									p_chi = &((ai_parms[0].info)[5]);
1151 								}
1152 								else
1153 								{
1154 									p_chi = &((ai_parms[0].info)[3]);
1155 								}
1156 								if (p_chi[0] > 35) /* check length of channel ID */
1157 								{
1158 									Info = _WRONG_MESSAGE_FORMAT;
1159 								}
1160 							}
1161 							else Info = _WRONG_MESSAGE_FORMAT;
1162 						}
1163 
1164 						if (ch == 3 && ai_parms[0].length >= 7 && ai_parms[0].length <= 36)
1165 						{
1166 							dir = GET_WORD(ai_parms[0].info + 3);
1167 							ch_mask = 0;
1168 							m = 0x3f;
1169 							for (i = 0; i + 5 <= ai_parms[0].length; i++)
1170 							{
1171 								if (ai_parms[0].info[i + 5] != 0)
1172 								{
1173 									if ((ai_parms[0].info[i + 5] | m) != 0xff)
1174 										Info = _WRONG_MESSAGE_FORMAT;
1175 									else
1176 									{
1177 										if (ch_mask == 0)
1178 											channel = i;
1179 										ch_mask |= 1L << i;
1180 									}
1181 								}
1182 								m = 0;
1183 							}
1184 							if (ch_mask == 0)
1185 								Info = _WRONG_MESSAGE_FORMAT;
1186 							if (!Info)
1187 							{
1188 								if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1189 								{
1190 									esc_chi[0] = (byte)(ai_parms[0].length - 2);
1191 									for (i = 0; i + 5 <= ai_parms[0].length; i++)
1192 										esc_chi[i + 3] = ai_parms[0].info[i + 5];
1193 								}
1194 								else
1195 									esc_chi[0] = 2;
1196 								esc_chi[2] = (byte)channel;
1197 								plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1198 								add_p(plci, LLI, lli);
1199 								add_p(plci, ESC, esc_chi);
1200 								plci->State = LOCAL_CONNECT;
1201 								if (!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
1202 							}
1203 						}
1204 					}
1205 				}
1206 				else  Info = _WRONG_MESSAGE_FORMAT;
1207 			}
1208 
1209 			dbug(1, dprintf("ch=%x,dir=%x,p_ch=%d", ch, dir, channel));
1210 			plci->command = _CONNECT_R;
1211 			plci->number = Number;
1212 			/* x.31 or D-ch free SAPI in LinkLayer? */
1213 			if (ch == 1 && LinkLayer != 3 && LinkLayer != 12) noCh = true;
1214 			if ((ch == 0 || ch == 2 || noCh || ch == 3 || ch == 4) && !Info)
1215 			{
1216 				/* B-channel used for B3 connections (ch==0), or no B channel    */
1217 				/* is used (ch==2) or perm. connection (3) is used  do a CALL    */
1218 				if (noCh) Info = add_b1(plci, &parms[5], 2, 0);    /* no resource    */
1219 				else     Info = add_b1(plci, &parms[5], ch, 0);
1220 				add_s(plci, OAD, &parms[2]);
1221 				add_s(plci, OSA, &parms[4]);
1222 				add_s(plci, BC, &parms[6]);
1223 				add_s(plci, LLC, &parms[7]);
1224 				add_s(plci, HLC, &parms[8]);
1225 				if (a->Info_Mask[appl->Id - 1] & 0x200)
1226 				{
1227 					/* early B3 connect (CIP mask bit 9) no release after a disc */
1228 					add_p(plci, LLI, "\x01\x01");
1229 				}
1230 				if (GET_WORD(parms[0].info) < 29) {
1231 					add_p(plci, BC, cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1232 					add_p(plci, HLC, cip_hlc[GET_WORD(parms[0].info)]);
1233 				}
1234 				add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1235 				sig_req(plci, ASSIGN, DSIG_ID);
1236 			}
1237 			else if (ch == 1) {
1238 
1239 				/* D-Channel used for B3 connections */
1240 				plci->Sig.Id = 0xff;
1241 				Info = 0;
1242 			}
1243 
1244 			if (!Info && ch != 2 && !noCh) {
1245 				Info = add_b23(plci, &parms[5]);
1246 				if (!Info) {
1247 					if (!(plci->tel && !plci->adv_nl))nl_req_ncci(plci, ASSIGN, 0);
1248 				}
1249 			}
1250 
1251 			if (!Info)
1252 			{
1253 				if (ch == 0 || ch == 2 || ch == 3 || noCh || ch == 4)
1254 				{
1255 					if (plci->spoofed_msg == SPOOFING_REQUIRED)
1256 					{
1257 						api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1258 						plci->spoofed_msg = CALL_REQ;
1259 						plci->internal_command = BLOCK_PLCI;
1260 						plci->command = 0;
1261 						dbug(1, dprintf("Spoof"));
1262 						send_req(plci);
1263 						return false;
1264 					}
1265 					if (ch == 4)add_p(plci, CHI, p_chi);
1266 					add_s(plci, CPN, &parms[1]);
1267 					add_s(plci, DSA, &parms[3]);
1268 					if (noCh) add_p(plci, ESC, "\x02\x18\xfd");  /* D-channel, no B-L3 */
1269 					add_ai(plci, &parms[9]);
1270 					if (!dir)sig_req(plci, CALL_REQ, 0);
1271 					else
1272 					{
1273 						plci->command = PERM_LIST_REQ;
1274 						plci->appl = appl;
1275 						sig_req(plci, LISTEN_REQ, 0);
1276 						send_req(plci);
1277 						return false;
1278 					}
1279 				}
1280 				send_req(plci);
1281 				return false;
1282 			}
1283 			plci->Id = 0;
1284 		}
1285 	}
1286 	sendf(appl,
1287 	      _CONNECT_R | CONFIRM,
1288 	      Id,
1289 	      Number,
1290 	      "w", Info);
1291 	return 2;
1292 }
1293 
connect_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)1294 static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1295 			PLCI *plci, APPL *appl, API_PARSE *parms)
1296 {
1297 	word i, Info;
1298 	word Reject;
1299 	static byte cau_t[] = {0, 0, 0x90, 0x91, 0xac, 0x9d, 0x86, 0xd8, 0x9b};
1300 	static byte esc_t[] = {0x03, 0x08, 0x00, 0x00};
1301 	API_PARSE *ai;
1302 	API_PARSE ai_parms[5];
1303 	word ch = 0;
1304 
1305 	if (!plci) {
1306 		dbug(1, dprintf("connect_res(no plci)"));
1307 		return 0;  /* no plci, no send */
1308 	}
1309 
1310 	dbug(1, dprintf("connect_res(State=0x%x)", plci->State));
1311 	for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1312 	ai = &parms[5];
1313 	dbug(1, dprintf("ai->length=%d", ai->length));
1314 
1315 	if (ai->length)
1316 	{
1317 		if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1318 		{
1319 			dbug(1, dprintf("ai_parms[0].length=%d/0x%x", ai_parms[0].length, GET_WORD(ai_parms[0].info + 1)));
1320 			ch = 0;
1321 			if (ai_parms[0].length)
1322 			{
1323 				ch = GET_WORD(ai_parms[0].info + 1);
1324 				dbug(1, dprintf("BCH-I=0x%x", ch));
1325 			}
1326 		}
1327 	}
1328 
1329 	if (plci->State == INC_CON_CONNECTED_ALERT)
1330 	{
1331 		dbug(1, dprintf("Connected Alert Call_Res"));
1332 		if (a->Info_Mask[appl->Id - 1] & 0x200)
1333 		{
1334 			/* early B3 connect (CIP mask bit 9) no release after a disc */
1335 			add_p(plci, LLI, "\x01\x01");
1336 		}
1337 		add_s(plci, CONN_NR, &parms[2]);
1338 		add_s(plci, LLC, &parms[4]);
1339 		add_ai(plci, &parms[5]);
1340 		plci->State = INC_CON_ACCEPT;
1341 		sig_req(plci, CALL_RES, 0);
1342 		return 1;
1343 	}
1344 	else if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT) {
1345 		__clear_bit(appl->Id - 1, plci->c_ind_mask_table);
1346 		dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
1347 		Reject = GET_WORD(parms[0].info);
1348 		dbug(1, dprintf("Reject=0x%x", Reject));
1349 		if (Reject)
1350 		{
1351 			if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
1352 			{
1353 				if ((Reject & 0xff00) == 0x3400)
1354 				{
1355 					esc_t[2] = ((byte)(Reject & 0x00ff)) | 0x80;
1356 					add_p(plci, ESC, esc_t);
1357 					add_ai(plci, &parms[5]);
1358 					sig_req(plci, REJECT, 0);
1359 				}
1360 				else if (Reject == 1 || Reject >= 9)
1361 				{
1362 					add_ai(plci, &parms[5]);
1363 					sig_req(plci, HANGUP, 0);
1364 				}
1365 				else
1366 				{
1367 					esc_t[2] = cau_t[(Reject&0x000f)];
1368 					add_p(plci, ESC, esc_t);
1369 					add_ai(plci, &parms[5]);
1370 					sig_req(plci, REJECT, 0);
1371 				}
1372 				plci->appl = appl;
1373 			}
1374 			else
1375 			{
1376 				sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1377 			}
1378 		}
1379 		else {
1380 			plci->appl = appl;
1381 			if (Id & EXT_CONTROLLER) {
1382 				if (AdvCodecSupport(a, plci, appl, 0)) {
1383 					dbug(1, dprintf("connect_res(error from AdvCodecSupport)"));
1384 					sig_req(plci, HANGUP, 0);
1385 					return 1;
1386 				}
1387 				if (plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1388 				{
1389 					Info = add_b23(plci, &parms[1]);
1390 					if (Info)
1391 					{
1392 						dbug(1, dprintf("connect_res(error from add_b23)"));
1393 						sig_req(plci, HANGUP, 0);
1394 						return 1;
1395 					}
1396 					if (plci->adv_nl)
1397 					{
1398 						nl_req_ncci(plci, ASSIGN, 0);
1399 					}
1400 				}
1401 			}
1402 			else
1403 			{
1404 				plci->tel = 0;
1405 				if (ch != 2)
1406 				{
1407 					Info = add_b23(plci, &parms[1]);
1408 					if (Info)
1409 					{
1410 						dbug(1, dprintf("connect_res(error from add_b23 2)"));
1411 						sig_req(plci, HANGUP, 0);
1412 						return 1;
1413 					}
1414 				}
1415 				nl_req_ncci(plci, ASSIGN, 0);
1416 			}
1417 
1418 			if (plci->spoofed_msg == SPOOFING_REQUIRED)
1419 			{
1420 				api_save_msg(parms, "wsssss", &plci->saved_msg);
1421 				plci->spoofed_msg = CALL_RES;
1422 				plci->internal_command = BLOCK_PLCI;
1423 				plci->command = 0;
1424 				dbug(1, dprintf("Spoof"));
1425 			}
1426 			else
1427 			{
1428 				add_b1(plci, &parms[1], ch, plci->B1_facilities);
1429 				if (a->Info_Mask[appl->Id - 1] & 0x200)
1430 				{
1431 					/* early B3 connect (CIP mask bit 9) no release after a disc */
1432 					add_p(plci, LLI, "\x01\x01");
1433 				}
1434 				add_s(plci, CONN_NR, &parms[2]);
1435 				add_s(plci, LLC, &parms[4]);
1436 				add_ai(plci, &parms[5]);
1437 				plci->State = INC_CON_ACCEPT;
1438 				sig_req(plci, CALL_RES, 0);
1439 			}
1440 
1441 			for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
1442 				sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1443 		}
1444 	}
1445 	return 1;
1446 }
1447 
connect_a_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)1448 static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1449 			  PLCI *plci, APPL *appl, API_PARSE *msg)
1450 {
1451 	dbug(1, dprintf("connect_a_res"));
1452 	return false;
1453 }
1454 
disconnect_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)1455 static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1456 			   PLCI *plci, APPL *appl, API_PARSE *msg)
1457 {
1458 	word Info;
1459 	word i;
1460 
1461 	dbug(1, dprintf("disconnect_req"));
1462 
1463 	Info = _WRONG_IDENTIFIER;
1464 
1465 	if (plci)
1466 	{
1467 		if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
1468 		{
1469 			__clear_bit(appl->Id - 1, plci->c_ind_mask_table);
1470 			plci->appl = appl;
1471 			for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
1472 				sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1473 			plci->State = OUTG_DIS_PENDING;
1474 		}
1475 		if (plci->Sig.Id && plci->appl)
1476 		{
1477 			Info = 0;
1478 			if (plci->Sig.Id != 0xff)
1479 			{
1480 				if (plci->State != INC_DIS_PENDING)
1481 				{
1482 					add_ai(plci, &msg[0]);
1483 					sig_req(plci, HANGUP, 0);
1484 					plci->State = OUTG_DIS_PENDING;
1485 					return 1;
1486 				}
1487 			}
1488 			else
1489 			{
1490 				if (plci->NL.Id && !plci->nl_remove_id)
1491 				{
1492 					mixer_remove(plci);
1493 					nl_req_ncci(plci, REMOVE, 0);
1494 					sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
1495 					sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1496 					plci->State = INC_DIS_PENDING;
1497 				}
1498 				return 1;
1499 			}
1500 		}
1501 	}
1502 
1503 	if (!appl)  return false;
1504 	sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", Info);
1505 	return false;
1506 }
1507 
disconnect_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)1508 static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1509 			   PLCI *plci, APPL *appl, API_PARSE *msg)
1510 {
1511 	dbug(1, dprintf("disconnect_res"));
1512 	if (plci)
1513 	{
1514 		/* clear ind mask bit, just in case of collsion of          */
1515 		/* DISCONNECT_IND and CONNECT_RES                           */
1516 		__clear_bit(appl->Id - 1, plci->c_ind_mask_table);
1517 		ncci_free_receive_buffers(plci, 0);
1518 		if (plci_remove_check(plci))
1519 		{
1520 			return 0;
1521 		}
1522 		if (plci->State == INC_DIS_PENDING
1523 		    || plci->State == SUSPENDING) {
1524 			if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL)) {
1525 				if (plci->State != SUSPENDING) plci->State = IDLE;
1526 				dbug(1, dprintf("chs=%d", plci->channels));
1527 				if (!plci->channels) {
1528 					plci_remove(plci);
1529 				}
1530 			}
1531 		}
1532 	}
1533 	return 0;
1534 }
1535 
listen_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)1536 static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1537 		       PLCI *plci, APPL *appl, API_PARSE *parms)
1538 {
1539 	word Info;
1540 	byte i;
1541 
1542 	dbug(1, dprintf("listen_req(Appl=0x%x)", appl->Id));
1543 
1544 	Info = _WRONG_IDENTIFIER;
1545 	if (a) {
1546 		Info = 0;
1547 		a->Info_Mask[appl->Id - 1] = GET_DWORD(parms[0].info);
1548 		a->CIP_Mask[appl->Id - 1] = GET_DWORD(parms[1].info);
1549 		dbug(1, dprintf("CIP_MASK=0x%lx", GET_DWORD(parms[1].info)));
1550 		if (a->Info_Mask[appl->Id - 1] & 0x200) { /* early B3 connect provides */
1551 			a->Info_Mask[appl->Id - 1] |=  0x10;   /* call progression infos    */
1552 		}
1553 
1554 		/* check if external controller listen and switch listen on or off*/
1555 		if (Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)) {
1556 			if (a->profile.Global_Options & ON_BOARD_CODEC) {
1557 				dummy_plci.State = IDLE;
1558 				a->codec_listen[appl->Id - 1] = &dummy_plci;
1559 				a->TelOAD[0] = (byte)(parms[3].length);
1560 				for (i = 1; parms[3].length >= i && i < 22; i++) {
1561 					a->TelOAD[i] = parms[3].info[i];
1562 				}
1563 				a->TelOAD[i] = 0;
1564 				a->TelOSA[0] = (byte)(parms[4].length);
1565 				for (i = 1; parms[4].length >= i && i < 22; i++) {
1566 					a->TelOSA[i] = parms[4].info[i];
1567 				}
1568 				a->TelOSA[i] = 0;
1569 			}
1570 			else Info = 0x2002; /* wrong controller, codec not supported */
1571 		}
1572 		else{               /* clear listen */
1573 			a->codec_listen[appl->Id - 1] = (PLCI *)0;
1574 		}
1575 	}
1576 	sendf(appl,
1577 	      _LISTEN_R | CONFIRM,
1578 	      Id,
1579 	      Number,
1580 	      "w", Info);
1581 
1582 	if (a) listen_check(a);
1583 	return false;
1584 }
1585 
info_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)1586 static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1587 		     PLCI *plci, APPL *appl, API_PARSE *msg)
1588 {
1589 	word i;
1590 	API_PARSE *ai;
1591 	PLCI *rc_plci = NULL;
1592 	API_PARSE ai_parms[5];
1593 	word Info = 0;
1594 
1595 	dbug(1, dprintf("info_req"));
1596 	for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1597 
1598 	ai = &msg[1];
1599 
1600 	if (ai->length)
1601 	{
1602 		if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1603 		{
1604 			dbug(1, dprintf("AddInfo wrong"));
1605 			Info = _WRONG_MESSAGE_FORMAT;
1606 		}
1607 	}
1608 	if (!a) Info = _WRONG_STATE;
1609 
1610 	if (!Info && plci)
1611 	{                /* no fac, with CPN, or KEY */
1612 		rc_plci = plci;
1613 		if (!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length))
1614 		{
1615 			/* overlap sending option */
1616 			dbug(1, dprintf("OvlSnd"));
1617 			add_s(plci, CPN, &msg[0]);
1618 			add_s(plci, KEY, &ai_parms[1]);
1619 			sig_req(plci, INFO_REQ, 0);
1620 			send_req(plci);
1621 			return false;
1622 		}
1623 
1624 		if (plci->State && ai_parms[2].length)
1625 		{
1626 			/* User_Info option */
1627 			dbug(1, dprintf("UUI"));
1628 			add_s(plci, UUI, &ai_parms[2]);
1629 			sig_req(plci, USER_DATA, 0);
1630 		}
1631 		else if (plci->State && ai_parms[3].length)
1632 		{
1633 			/* Facility option */
1634 			dbug(1, dprintf("FAC"));
1635 			add_s(plci, CPN, &msg[0]);
1636 			add_ai(plci, &msg[1]);
1637 			sig_req(plci, FACILITY_REQ, 0);
1638 		}
1639 		else
1640 		{
1641 			Info = _WRONG_STATE;
1642 		}
1643 	}
1644 	else if ((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1645 	{
1646 		/* NCR_Facility option -> send UUI and Keypad too */
1647 		dbug(1, dprintf("NCR_FAC"));
1648 		if ((i = get_plci(a)))
1649 		{
1650 			rc_plci = &a->plci[i - 1];
1651 			appl->NullCREnable = true;
1652 			rc_plci->internal_command = C_NCR_FAC_REQ;
1653 			rc_plci->appl = appl;
1654 			add_p(rc_plci, CAI, "\x01\x80");
1655 			add_p(rc_plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1656 			sig_req(rc_plci, ASSIGN, DSIG_ID);
1657 			send_req(rc_plci);
1658 		}
1659 		else
1660 		{
1661 			Info = _OUT_OF_PLCI;
1662 		}
1663 
1664 		if (!Info)
1665 		{
1666 			add_s(rc_plci, CPN, &msg[0]);
1667 			add_ai(rc_plci, &msg[1]);
1668 			sig_req(rc_plci, NCR_FACILITY, 0);
1669 			send_req(rc_plci);
1670 			return false;
1671 			/* for application controlled supplementary services    */
1672 		}
1673 	}
1674 
1675 	if (!rc_plci)
1676 	{
1677 		Info = _WRONG_MESSAGE_FORMAT;
1678 	}
1679 
1680 	if (!Info)
1681 	{
1682 		send_req(rc_plci);
1683 	}
1684 	else
1685 	{  /* appl is not assigned to a PLCI or error condition */
1686 		dbug(1, dprintf("localInfoCon"));
1687 		sendf(appl,
1688 		      _INFO_R | CONFIRM,
1689 		      Id,
1690 		      Number,
1691 		      "w", Info);
1692 	}
1693 	return false;
1694 }
1695 
info_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)1696 static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1697 		     PLCI *plci, APPL *appl, API_PARSE *msg)
1698 {
1699 	dbug(1, dprintf("info_res"));
1700 	return false;
1701 }
1702 
alert_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)1703 static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1704 		      PLCI *plci, APPL *appl, API_PARSE *msg)
1705 {
1706 	word Info;
1707 	byte ret;
1708 
1709 	dbug(1, dprintf("alert_req"));
1710 
1711 	Info = _WRONG_IDENTIFIER;
1712 	ret = false;
1713 	if (plci) {
1714 		Info = _ALERT_IGNORED;
1715 		if (plci->State != INC_CON_ALERT) {
1716 			Info = _WRONG_STATE;
1717 			if (plci->State == INC_CON_PENDING) {
1718 				Info = 0;
1719 				plci->State = INC_CON_ALERT;
1720 				add_ai(plci, &msg[0]);
1721 				sig_req(plci, CALL_ALERT, 0);
1722 				ret = 1;
1723 			}
1724 		}
1725 	}
1726 	sendf(appl,
1727 	      _ALERT_R | CONFIRM,
1728 	      Id,
1729 	      Number,
1730 	      "w", Info);
1731 	return ret;
1732 }
1733 
facility_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)1734 static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1735 			 PLCI *plci, APPL *appl, API_PARSE *msg)
1736 {
1737 	word Info = 0;
1738 	word i    = 0;
1739 
1740 	word selector;
1741 	word SSreq;
1742 	long relatedPLCIvalue;
1743 	DIVA_CAPI_ADAPTER *relatedadapter;
1744 	byte *SSparms  = "";
1745 	byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1746 	byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1747 	API_PARSE *parms;
1748 	API_PARSE ss_parms[11];
1749 	PLCI *rplci;
1750 	byte cai[15];
1751 	dword d;
1752 	API_PARSE dummy;
1753 
1754 	dbug(1, dprintf("facility_req"));
1755 	for (i = 0; i < 9; i++) ss_parms[i].length = 0;
1756 
1757 	parms = &msg[1];
1758 
1759 	if (!a)
1760 	{
1761 		dbug(1, dprintf("wrong Ctrl"));
1762 		Info = _WRONG_IDENTIFIER;
1763 	}
1764 
1765 	selector = GET_WORD(msg[0].info);
1766 
1767 	if (!Info)
1768 	{
1769 		switch (selector)
1770 		{
1771 		case SELECTOR_HANDSET:
1772 			Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1773 			break;
1774 
1775 		case SELECTOR_SU_SERV:
1776 			if (!msg[1].length)
1777 			{
1778 				Info = _WRONG_MESSAGE_FORMAT;
1779 				break;
1780 			}
1781 			SSreq = GET_WORD(&(msg[1].info[1]));
1782 			PUT_WORD(&RCparms[1], SSreq);
1783 			SSparms = RCparms;
1784 			switch (SSreq)
1785 			{
1786 			case S_GET_SUPPORTED_SERVICES:
1787 				if ((i = get_plci(a)))
1788 				{
1789 					rplci = &a->plci[i - 1];
1790 					rplci->appl = appl;
1791 					add_p(rplci, CAI, "\x01\x80");
1792 					add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1793 					sig_req(rplci, ASSIGN, DSIG_ID);
1794 					send_req(rplci);
1795 				}
1796 				else
1797 				{
1798 					PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1799 					SSparms = (byte *)SSstruct;
1800 					break;
1801 				}
1802 				rplci->internal_command = GETSERV_REQ_PEND;
1803 				rplci->number = Number;
1804 				rplci->appl = appl;
1805 				sig_req(rplci, S_SUPPORTED, 0);
1806 				send_req(rplci);
1807 				return false;
1808 				break;
1809 
1810 			case S_LISTEN:
1811 				if (parms->length == 7)
1812 				{
1813 					if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1814 					{
1815 						dbug(1, dprintf("format wrong"));
1816 						Info = _WRONG_MESSAGE_FORMAT;
1817 						break;
1818 					}
1819 				}
1820 				else
1821 				{
1822 					Info = _WRONG_MESSAGE_FORMAT;
1823 					break;
1824 				}
1825 				a->Notification_Mask[appl->Id - 1] = GET_DWORD(ss_parms[2].info);
1826 				if (a->Notification_Mask[appl->Id - 1] & SMASK_MWI) /* MWI active? */
1827 				{
1828 					if ((i = get_plci(a)))
1829 					{
1830 						rplci = &a->plci[i - 1];
1831 						rplci->appl = appl;
1832 						add_p(rplci, CAI, "\x01\x80");
1833 						add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1834 						sig_req(rplci, ASSIGN, DSIG_ID);
1835 						send_req(rplci);
1836 					}
1837 					else
1838 					{
1839 						break;
1840 					}
1841 					rplci->internal_command = GET_MWI_STATE;
1842 					rplci->number = Number;
1843 					sig_req(rplci, MWI_POLL, 0);
1844 					send_req(rplci);
1845 				}
1846 				break;
1847 
1848 			case S_HOLD:
1849 				api_parse(&parms->info[1], (word)parms->length, "ws", ss_parms);
1850 				if (plci && plci->State && plci->SuppState == IDLE)
1851 				{
1852 					plci->SuppState = HOLD_REQUEST;
1853 					plci->command = C_HOLD_REQ;
1854 					add_s(plci, CAI, &ss_parms[1]);
1855 					sig_req(plci, CALL_HOLD, 0);
1856 					send_req(plci);
1857 					return false;
1858 				}
1859 				else Info = 0x3010;                    /* wrong state           */
1860 				break;
1861 			case S_RETRIEVE:
1862 				if (plci && plci->State && plci->SuppState == CALL_HELD)
1863 				{
1864 					if (Id & EXT_CONTROLLER)
1865 					{
1866 						if (AdvCodecSupport(a, plci, appl, 0))
1867 						{
1868 							Info = 0x3010;                    /* wrong state           */
1869 							break;
1870 						}
1871 					}
1872 					else plci->tel = 0;
1873 
1874 					plci->SuppState = RETRIEVE_REQUEST;
1875 					plci->command = C_RETRIEVE_REQ;
1876 					if (plci->spoofed_msg == SPOOFING_REQUIRED)
1877 					{
1878 						plci->spoofed_msg = CALL_RETRIEVE;
1879 						plci->internal_command = BLOCK_PLCI;
1880 						plci->command = 0;
1881 						dbug(1, dprintf("Spoof"));
1882 						return false;
1883 					}
1884 					else
1885 					{
1886 						sig_req(plci, CALL_RETRIEVE, 0);
1887 						send_req(plci);
1888 						return false;
1889 					}
1890 				}
1891 				else Info = 0x3010;                    /* wrong state           */
1892 				break;
1893 			case S_SUSPEND:
1894 				if (parms->length)
1895 				{
1896 					if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
1897 					{
1898 						dbug(1, dprintf("format wrong"));
1899 						Info = _WRONG_MESSAGE_FORMAT;
1900 						break;
1901 					}
1902 				}
1903 				if (plci && plci->State)
1904 				{
1905 					add_s(plci, CAI, &ss_parms[2]);
1906 					plci->command = SUSPEND_REQ;
1907 					sig_req(plci, SUSPEND, 0);
1908 					plci->State = SUSPENDING;
1909 					send_req(plci);
1910 				}
1911 				else Info = 0x3010;                    /* wrong state           */
1912 				break;
1913 
1914 			case S_RESUME:
1915 				if (!(i = get_plci(a)))
1916 				{
1917 					Info = _OUT_OF_PLCI;
1918 					break;
1919 				}
1920 				rplci = &a->plci[i - 1];
1921 				rplci->appl = appl;
1922 				rplci->number = Number;
1923 				rplci->tel = 0;
1924 				rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1925 				/* check 'external controller' bit for codec support */
1926 				if (Id & EXT_CONTROLLER)
1927 				{
1928 					if (AdvCodecSupport(a, rplci, appl, 0))
1929 					{
1930 						rplci->Id = 0;
1931 						Info = 0x300A;
1932 						break;
1933 					}
1934 				}
1935 				if (parms->length)
1936 				{
1937 					if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
1938 					{
1939 						dbug(1, dprintf("format wrong"));
1940 						rplci->Id = 0;
1941 						Info = _WRONG_MESSAGE_FORMAT;
1942 						break;
1943 					}
1944 				}
1945 				dummy.length = 0;
1946 				dummy.info = "\x00";
1947 				add_b1(rplci, &dummy, 0, 0);
1948 				if (a->Info_Mask[appl->Id - 1] & 0x200)
1949 				{
1950 					/* early B3 connect (CIP mask bit 9) no release after a disc */
1951 					add_p(rplci, LLI, "\x01\x01");
1952 				}
1953 				add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1954 				sig_req(rplci, ASSIGN, DSIG_ID);
1955 				send_req(rplci);
1956 				add_s(rplci, CAI, &ss_parms[2]);
1957 				rplci->command = RESUME_REQ;
1958 				sig_req(rplci, RESUME, 0);
1959 				rplci->State = RESUMING;
1960 				send_req(rplci);
1961 				break;
1962 
1963 			case S_CONF_BEGIN: /* Request */
1964 			case S_CONF_DROP:
1965 			case S_CONF_ISOLATE:
1966 			case S_CONF_REATTACH:
1967 				if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1968 				{
1969 					dbug(1, dprintf("format wrong"));
1970 					Info = _WRONG_MESSAGE_FORMAT;
1971 					break;
1972 				}
1973 				if (plci && plci->State && ((plci->SuppState == IDLE) || (plci->SuppState == CALL_HELD)))
1974 				{
1975 					d = GET_DWORD(ss_parms[2].info);
1976 					if (d >= 0x80)
1977 					{
1978 						dbug(1, dprintf("format wrong"));
1979 						Info = _WRONG_MESSAGE_FORMAT;
1980 						break;
1981 					}
1982 					plci->ptyState = (byte)SSreq;
1983 					plci->command = 0;
1984 					cai[0] = 2;
1985 					switch (SSreq)
1986 					{
1987 					case S_CONF_BEGIN:
1988 						cai[1] = CONF_BEGIN;
1989 						plci->internal_command = CONF_BEGIN_REQ_PEND;
1990 						break;
1991 					case S_CONF_DROP:
1992 						cai[1] = CONF_DROP;
1993 						plci->internal_command = CONF_DROP_REQ_PEND;
1994 						break;
1995 					case S_CONF_ISOLATE:
1996 						cai[1] = CONF_ISOLATE;
1997 						plci->internal_command = CONF_ISOLATE_REQ_PEND;
1998 						break;
1999 					case S_CONF_REATTACH:
2000 						cai[1] = CONF_REATTACH;
2001 						plci->internal_command = CONF_REATTACH_REQ_PEND;
2002 						break;
2003 					}
2004 					cai[2] = (byte)d; /* Conference Size resp. PartyId */
2005 					add_p(plci, CAI, cai);
2006 					sig_req(plci, S_SERVICE, 0);
2007 					send_req(plci);
2008 					return false;
2009 				}
2010 				else Info = 0x3010;                    /* wrong state           */
2011 				break;
2012 
2013 			case S_ECT:
2014 			case S_3PTY_BEGIN:
2015 			case S_3PTY_END:
2016 			case S_CONF_ADD:
2017 				if (parms->length == 7)
2018 				{
2019 					if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2020 					{
2021 						dbug(1, dprintf("format wrong"));
2022 						Info = _WRONG_MESSAGE_FORMAT;
2023 						break;
2024 					}
2025 				}
2026 				else if (parms->length == 8) /* workaround for the T-View-S */
2027 				{
2028 					if (api_parse(&parms->info[1], (word)parms->length, "wbdb", ss_parms))
2029 					{
2030 						dbug(1, dprintf("format wrong"));
2031 						Info = _WRONG_MESSAGE_FORMAT;
2032 						break;
2033 					}
2034 				}
2035 				else
2036 				{
2037 					Info = _WRONG_MESSAGE_FORMAT;
2038 					break;
2039 				}
2040 				if (!msg[1].length)
2041 				{
2042 					Info = _WRONG_MESSAGE_FORMAT;
2043 					break;
2044 				}
2045 				if (!plci)
2046 				{
2047 					Info = _WRONG_IDENTIFIER;
2048 					break;
2049 				}
2050 				relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2051 				relatedPLCIvalue &= 0x0000FFFF;
2052 				dbug(1, dprintf("PTY/ECT/addCONF,relPLCI=%lx", relatedPLCIvalue));
2053 				/* controller starts with 0 up to (max_adapter - 1) */
2054 				if (((relatedPLCIvalue & 0x7f) == 0)
2055 				    || (MapController((byte)(relatedPLCIvalue & 0x7f)) == 0)
2056 				    || (MapController((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2057 				{
2058 					if (SSreq == S_3PTY_END)
2059 					{
2060 						dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2061 						rplci = plci;
2062 					}
2063 					else
2064 					{
2065 						Info = 0x3010;                    /* wrong state           */
2066 						break;
2067 					}
2068 				}
2069 				else
2070 				{
2071 					relatedadapter = &adapter[MapController((byte)(relatedPLCIvalue & 0x7f)) - 1];
2072 					relatedPLCIvalue >>= 8;
2073 					/* find PLCI PTR*/
2074 					for (i = 0, rplci = NULL; i < relatedadapter->max_plci; i++)
2075 					{
2076 						if (relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2077 						{
2078 							rplci = &relatedadapter->plci[i];
2079 						}
2080 					}
2081 					if (!rplci || !relatedPLCIvalue)
2082 					{
2083 						if (SSreq == S_3PTY_END)
2084 						{
2085 							dbug(1, dprintf("use 2nd PLCI=PLCI"));
2086 							rplci = plci;
2087 						}
2088 						else
2089 						{
2090 							Info = 0x3010;                    /* wrong state           */
2091 							break;
2092 						}
2093 					}
2094 				}
2095 /*
2096   dbug(1, dprintf("rplci:%x", rplci));
2097   dbug(1, dprintf("plci:%x", plci));
2098   dbug(1, dprintf("rplci->ptyState:%x", rplci->ptyState));
2099   dbug(1, dprintf("plci->ptyState:%x", plci->ptyState));
2100   dbug(1, dprintf("SSreq:%x", SSreq));
2101   dbug(1, dprintf("rplci->internal_command:%x", rplci->internal_command));
2102   dbug(1, dprintf("rplci->appl:%x", rplci->appl));
2103   dbug(1, dprintf("rplci->Id:%x", rplci->Id));
2104 */
2105 				/* send PTY/ECT req, cannot check all states because of US stuff */
2106 				if (!rplci->internal_command && rplci->appl)
2107 				{
2108 					plci->command = 0;
2109 					rplci->relatedPTYPLCI = plci;
2110 					plci->relatedPTYPLCI = rplci;
2111 					rplci->ptyState = (byte)SSreq;
2112 					if (SSreq == S_ECT)
2113 					{
2114 						rplci->internal_command = ECT_REQ_PEND;
2115 						cai[1] = ECT_EXECUTE;
2116 
2117 						rplci->vswitchstate = 0;
2118 						rplci->vsprot = 0;
2119 						rplci->vsprotdialect = 0;
2120 						plci->vswitchstate = 0;
2121 						plci->vsprot = 0;
2122 						plci->vsprotdialect = 0;
2123 
2124 					}
2125 					else if (SSreq == S_CONF_ADD)
2126 					{
2127 						rplci->internal_command = CONF_ADD_REQ_PEND;
2128 						cai[1] = CONF_ADD;
2129 					}
2130 					else
2131 					{
2132 						rplci->internal_command = PTY_REQ_PEND;
2133 						cai[1] = (byte)(SSreq - 3);
2134 					}
2135 					rplci->number = Number;
2136 					if (plci != rplci) /* explicit invocation */
2137 					{
2138 						cai[0] = 2;
2139 						cai[2] = plci->Sig.Id;
2140 						dbug(1, dprintf("explicit invocation"));
2141 					}
2142 					else
2143 					{
2144 						dbug(1, dprintf("implicit invocation"));
2145 						cai[0] = 1;
2146 					}
2147 					add_p(rplci, CAI, cai);
2148 					sig_req(rplci, S_SERVICE, 0);
2149 					send_req(rplci);
2150 					return false;
2151 				}
2152 				else
2153 				{
2154 					dbug(0, dprintf("Wrong line"));
2155 					Info = 0x3010;                    /* wrong state           */
2156 					break;
2157 				}
2158 				break;
2159 
2160 			case S_CALL_DEFLECTION:
2161 				if (api_parse(&parms->info[1], (word)parms->length, "wbwss", ss_parms))
2162 				{
2163 					dbug(1, dprintf("format wrong"));
2164 					Info = _WRONG_MESSAGE_FORMAT;
2165 					break;
2166 				}
2167 				if (!plci)
2168 				{
2169 					Info = _WRONG_IDENTIFIER;
2170 					break;
2171 				}
2172 				/* reuse unused screening indicator */
2173 				ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2174 				plci->command = 0;
2175 				plci->internal_command = CD_REQ_PEND;
2176 				appl->CDEnable = true;
2177 				cai[0] = 1;
2178 				cai[1] = CALL_DEFLECTION;
2179 				add_p(plci, CAI, cai);
2180 				add_p(plci, CPN, ss_parms[3].info);
2181 				sig_req(plci, S_SERVICE, 0);
2182 				send_req(plci);
2183 				return false;
2184 				break;
2185 
2186 			case S_CALL_FORWARDING_START:
2187 				if (api_parse(&parms->info[1], (word)parms->length, "wbdwwsss", ss_parms))
2188 				{
2189 					dbug(1, dprintf("format wrong"));
2190 					Info = _WRONG_MESSAGE_FORMAT;
2191 					break;
2192 				}
2193 
2194 				if ((i = get_plci(a)))
2195 				{
2196 					rplci = &a->plci[i - 1];
2197 					rplci->appl = appl;
2198 					add_p(rplci, CAI, "\x01\x80");
2199 					add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2200 					sig_req(rplci, ASSIGN, DSIG_ID);
2201 					send_req(rplci);
2202 				}
2203 				else
2204 				{
2205 					Info = _OUT_OF_PLCI;
2206 					break;
2207 				}
2208 
2209 				/* reuse unused screening indicator */
2210 				rplci->internal_command = CF_START_PEND;
2211 				rplci->appl = appl;
2212 				rplci->number = Number;
2213 				appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2214 				cai[0] = 2;
2215 				cai[1] = 0x70 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2216 				cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2217 				add_p(rplci, CAI, cai);
2218 				add_p(rplci, OAD, ss_parms[5].info);
2219 				add_p(rplci, CPN, ss_parms[6].info);
2220 				sig_req(rplci, S_SERVICE, 0);
2221 				send_req(rplci);
2222 				return false;
2223 				break;
2224 
2225 			case S_INTERROGATE_DIVERSION:
2226 			case S_INTERROGATE_NUMBERS:
2227 			case S_CALL_FORWARDING_STOP:
2228 			case S_CCBS_REQUEST:
2229 			case S_CCBS_DEACTIVATE:
2230 			case S_CCBS_INTERROGATE:
2231 				switch (SSreq)
2232 				{
2233 				case S_INTERROGATE_NUMBERS:
2234 					if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2235 					{
2236 						dbug(0, dprintf("format wrong"));
2237 						Info = _WRONG_MESSAGE_FORMAT;
2238 					}
2239 					break;
2240 				case S_CCBS_REQUEST:
2241 				case S_CCBS_DEACTIVATE:
2242 					if (api_parse(&parms->info[1], (word)parms->length, "wbdw", ss_parms))
2243 					{
2244 						dbug(0, dprintf("format wrong"));
2245 						Info = _WRONG_MESSAGE_FORMAT;
2246 					}
2247 					break;
2248 				case S_CCBS_INTERROGATE:
2249 					if (api_parse(&parms->info[1], (word)parms->length, "wbdws", ss_parms))
2250 					{
2251 						dbug(0, dprintf("format wrong"));
2252 						Info = _WRONG_MESSAGE_FORMAT;
2253 					}
2254 					break;
2255 				default:
2256 					if (api_parse(&parms->info[1], (word)parms->length, "wbdwws", ss_parms))
2257 					{
2258 						dbug(0, dprintf("format wrong"));
2259 						Info = _WRONG_MESSAGE_FORMAT;
2260 						break;
2261 					}
2262 					break;
2263 				}
2264 
2265 				if (Info) break;
2266 				if ((i = get_plci(a)))
2267 				{
2268 					rplci = &a->plci[i - 1];
2269 					switch (SSreq)
2270 					{
2271 					case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2272 						cai[1] = 0x60 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2273 						rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2274 						break;
2275 					case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2276 						cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2277 						rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2278 						break;
2279 					case S_CALL_FORWARDING_STOP:
2280 						rplci->internal_command = CF_STOP_PEND;
2281 						cai[1] = 0x80 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2282 						break;
2283 					case S_CCBS_REQUEST:
2284 						cai[1] = CCBS_REQUEST;
2285 						rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2286 						break;
2287 					case S_CCBS_DEACTIVATE:
2288 						cai[1] = CCBS_DEACTIVATE;
2289 						rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2290 						break;
2291 					case S_CCBS_INTERROGATE:
2292 						cai[1] = CCBS_INTERROGATE;
2293 						rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2294 						break;
2295 					default:
2296 						cai[1] = 0;
2297 						break;
2298 					}
2299 					rplci->appl = appl;
2300 					rplci->number = Number;
2301 					add_p(rplci, CAI, "\x01\x80");
2302 					add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2303 					sig_req(rplci, ASSIGN, DSIG_ID);
2304 					send_req(rplci);
2305 				}
2306 				else
2307 				{
2308 					Info = _OUT_OF_PLCI;
2309 					break;
2310 				}
2311 
2312 				appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2313 				switch (SSreq)
2314 				{
2315 				case S_INTERROGATE_NUMBERS:
2316 					cai[0] = 1;
2317 					add_p(rplci, CAI, cai);
2318 					break;
2319 				case S_CCBS_REQUEST:
2320 				case S_CCBS_DEACTIVATE:
2321 					cai[0] = 3;
2322 					PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2323 					add_p(rplci, CAI, cai);
2324 					break;
2325 				case S_CCBS_INTERROGATE:
2326 					cai[0] = 3;
2327 					PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2328 					add_p(rplci, CAI, cai);
2329 					add_p(rplci, OAD, ss_parms[4].info);
2330 					break;
2331 				default:
2332 					cai[0] = 2;
2333 					cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2334 					add_p(rplci, CAI, cai);
2335 					add_p(rplci, OAD, ss_parms[5].info);
2336 					break;
2337 				}
2338 
2339 				sig_req(rplci, S_SERVICE, 0);
2340 				send_req(rplci);
2341 				return false;
2342 				break;
2343 
2344 			case S_MWI_ACTIVATE:
2345 				if (api_parse(&parms->info[1], (word)parms->length, "wbwdwwwssss", ss_parms))
2346 				{
2347 					dbug(1, dprintf("format wrong"));
2348 					Info = _WRONG_MESSAGE_FORMAT;
2349 					break;
2350 				}
2351 				if (!plci)
2352 				{
2353 					if ((i = get_plci(a)))
2354 					{
2355 						rplci = &a->plci[i - 1];
2356 						rplci->appl = appl;
2357 						rplci->cr_enquiry = true;
2358 						add_p(rplci, CAI, "\x01\x80");
2359 						add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2360 						sig_req(rplci, ASSIGN, DSIG_ID);
2361 						send_req(rplci);
2362 					}
2363 					else
2364 					{
2365 						Info = _OUT_OF_PLCI;
2366 						break;
2367 					}
2368 				}
2369 				else
2370 				{
2371 					rplci = plci;
2372 					rplci->cr_enquiry = false;
2373 				}
2374 
2375 				rplci->command = 0;
2376 				rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2377 				rplci->appl = appl;
2378 				rplci->number = Number;
2379 
2380 				cai[0] = 13;
2381 				cai[1] = ACTIVATION_MWI; /* Function */
2382 				PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2383 				PUT_DWORD(&cai[4], GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2384 				PUT_WORD(&cai[8], GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2385 				PUT_WORD(&cai[10], GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2386 				PUT_WORD(&cai[12], GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2387 				add_p(rplci, CAI, cai);
2388 				add_p(rplci, CPN, ss_parms[7].info); /* Receiving User Number */
2389 				add_p(rplci, OAD, ss_parms[8].info); /* Controlling User Number */
2390 				add_p(rplci, OSA, ss_parms[9].info); /* Controlling User Provided Number */
2391 				add_p(rplci, UID, ss_parms[10].info); /* Time */
2392 				sig_req(rplci, S_SERVICE, 0);
2393 				send_req(rplci);
2394 				return false;
2395 
2396 			case S_MWI_DEACTIVATE:
2397 				if (api_parse(&parms->info[1], (word)parms->length, "wbwwss", ss_parms))
2398 				{
2399 					dbug(1, dprintf("format wrong"));
2400 					Info = _WRONG_MESSAGE_FORMAT;
2401 					break;
2402 				}
2403 				if (!plci)
2404 				{
2405 					if ((i = get_plci(a)))
2406 					{
2407 						rplci = &a->plci[i - 1];
2408 						rplci->appl = appl;
2409 						rplci->cr_enquiry = true;
2410 						add_p(rplci, CAI, "\x01\x80");
2411 						add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2412 						sig_req(rplci, ASSIGN, DSIG_ID);
2413 						send_req(rplci);
2414 					}
2415 					else
2416 					{
2417 						Info = _OUT_OF_PLCI;
2418 						break;
2419 					}
2420 				}
2421 				else
2422 				{
2423 					rplci = plci;
2424 					rplci->cr_enquiry = false;
2425 				}
2426 
2427 				rplci->command = 0;
2428 				rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2429 				rplci->appl = appl;
2430 				rplci->number = Number;
2431 
2432 				cai[0] = 5;
2433 				cai[1] = DEACTIVATION_MWI; /* Function */
2434 				PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2435 				PUT_WORD(&cai[4], GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2436 				add_p(rplci, CAI, cai);
2437 				add_p(rplci, CPN, ss_parms[4].info); /* Receiving User Number */
2438 				add_p(rplci, OAD, ss_parms[5].info); /* Controlling User Number */
2439 				sig_req(rplci, S_SERVICE, 0);
2440 				send_req(rplci);
2441 				return false;
2442 
2443 			default:
2444 				Info = 0x300E;  /* not supported */
2445 				break;
2446 			}
2447 			break; /* case SELECTOR_SU_SERV: end */
2448 
2449 
2450 		case SELECTOR_DTMF:
2451 			return (dtmf_request(Id, Number, a, plci, appl, msg));
2452 
2453 
2454 
2455 		case SELECTOR_LINE_INTERCONNECT:
2456 			return (mixer_request(Id, Number, a, plci, appl, msg));
2457 
2458 
2459 
2460 		case PRIV_SELECTOR_ECHO_CANCELLER:
2461 			appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2462 			return (ec_request(Id, Number, a, plci, appl, msg));
2463 
2464 		case SELECTOR_ECHO_CANCELLER:
2465 			appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2466 			return (ec_request(Id, Number, a, plci, appl, msg));
2467 
2468 
2469 		case SELECTOR_V42BIS:
2470 		default:
2471 			Info = _FACILITY_NOT_SUPPORTED;
2472 			break;
2473 		} /* end of switch (selector) */
2474 	}
2475 
2476 	dbug(1, dprintf("SendFacRc"));
2477 	sendf(appl,
2478 	      _FACILITY_R | CONFIRM,
2479 	      Id,
2480 	      Number,
2481 	      "wws", Info, selector, SSparms);
2482 	return false;
2483 }
2484 
facility_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)2485 static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2486 			 PLCI *plci, APPL *appl, API_PARSE *msg)
2487 {
2488 	dbug(1, dprintf("facility_res"));
2489 	return false;
2490 }
2491 
connect_b3_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)2492 static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2493 			   PLCI *plci, APPL *appl, API_PARSE *parms)
2494 {
2495 	word Info = 0;
2496 	byte req;
2497 	byte len;
2498 	word w;
2499 	word fax_control_bits, fax_feature_bits, fax_info_change;
2500 	API_PARSE *ncpi;
2501 	byte pvc[2];
2502 
2503 	API_PARSE fax_parms[9];
2504 	word i;
2505 
2506 
2507 	dbug(1, dprintf("connect_b3_req"));
2508 	if (plci)
2509 	{
2510 		if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2511 		    || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2512 		{
2513 			Info = _WRONG_STATE;
2514 		}
2515 		else
2516 		{
2517 			/* local reply if assign unsuccessful
2518 			   or B3 protocol allows only one layer 3 connection
2519 			   and already connected
2520 			   or B2 protocol not any LAPD
2521 			   and connect_b3_req contradicts originate/answer direction */
2522 			if (!plci->NL.Id
2523 			    || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2524 				&& ((plci->channels != 0)
2525 				    || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2526 					&& ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2527 			{
2528 				dbug(1, dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2529 						plci->channels, plci->NL.Id, plci->call_dir, plci->SuppState));
2530 				Info = _WRONG_STATE;
2531 				sendf(appl,
2532 				      _CONNECT_B3_R | CONFIRM,
2533 				      Id,
2534 				      Number,
2535 				      "w", Info);
2536 				return false;
2537 			}
2538 			plci->requested_options_conn = 0;
2539 
2540 			req = N_CONNECT;
2541 			ncpi = &parms[0];
2542 			if (plci->B3_prot == 2 || plci->B3_prot == 3)
2543 			{
2544 				if (ncpi->length > 2)
2545 				{
2546 					/* check for PVC */
2547 					if (ncpi->info[2] || ncpi->info[3])
2548 					{
2549 						pvc[0] = ncpi->info[3];
2550 						pvc[1] = ncpi->info[2];
2551 						add_d(plci, 2, pvc);
2552 						req = N_RESET;
2553 					}
2554 					else
2555 					{
2556 						if (ncpi->info[1] & 1) req = N_CONNECT | N_D_BIT;
2557 						add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2558 					}
2559 				}
2560 			}
2561 			else if (plci->B3_prot == 5)
2562 			{
2563 				if (plci->NL.Id && !plci->nl_remove_id)
2564 				{
2565 					fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2566 					fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2567 					if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2568 					    || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2569 					{
2570 						len = offsetof(T30_INFO, universal_6);
2571 						fax_info_change = false;
2572 						if (ncpi->length >= 4)
2573 						{
2574 							w = GET_WORD(&ncpi->info[3]);
2575 							if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2576 							{
2577 								((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2578 									(byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2579 									       ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2580 								fax_info_change = true;
2581 							}
2582 							fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2583 							if (w & 0x0002)  /* Fax-polling request */
2584 								fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2585 							if ((w & 0x0004) /* Request to send / poll another document */
2586 							    && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2587 							{
2588 								fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2589 							}
2590 							if (ncpi->length >= 6)
2591 							{
2592 								w = GET_WORD(&ncpi->info[5]);
2593 								if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2594 								{
2595 									((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2596 									fax_info_change = true;
2597 								}
2598 
2599 								if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2600 								    && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2601 								{
2602 									plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2603 								}
2604 								if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2605 								    && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2606 								{
2607 									plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2608 								}
2609 								fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2610 										      T30_CONTROL_BIT_ACCEPT_PASSWORD);
2611 								if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2612 								    & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2613 								{
2614 									if (api_parse(&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2615 										Info = _WRONG_MESSAGE_FORMAT;
2616 									else
2617 									{
2618 										if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2619 										    & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2620 										{
2621 											fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2622 											if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2623 												fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2624 										}
2625 										w = fax_parms[4].length;
2626 										if (w > 20)
2627 											w = 20;
2628 										((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2629 										for (i = 0; i < w; i++)
2630 											((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1 + i];
2631 										((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2632 										len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2633 										w = fax_parms[5].length;
2634 										if (w > 20)
2635 											w = 20;
2636 										plci->fax_connect_info_buffer[len++] = (byte) w;
2637 										for (i = 0; i < w; i++)
2638 											plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1 + i];
2639 										w = fax_parms[6].length;
2640 										if (w > 20)
2641 											w = 20;
2642 										plci->fax_connect_info_buffer[len++] = (byte) w;
2643 										for (i = 0; i < w; i++)
2644 											plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1 + i];
2645 										if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2646 										    & (1L << PRIVATE_FAX_NONSTANDARD))
2647 										{
2648 											if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2649 											{
2650 												dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2651 												plci->fax_connect_info_buffer[len++] = 0;
2652 											}
2653 											else
2654 											{
2655 												if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2656 													plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2657 												plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2658 												for (i = 0; i < fax_parms[7].length; i++)
2659 													plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2660 											}
2661 										}
2662 									}
2663 								}
2664 								else
2665 								{
2666 									len = offsetof(T30_INFO, universal_6);
2667 								}
2668 								fax_info_change = true;
2669 
2670 							}
2671 							if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2672 							{
2673 								PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2674 								fax_info_change = true;
2675 							}
2676 						}
2677 						if (Info == GOOD)
2678 						{
2679 							plci->fax_connect_info_length = len;
2680 							if (fax_info_change)
2681 							{
2682 								if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2683 								{
2684 									start_internal_command(Id, plci, fax_connect_info_command);
2685 									return false;
2686 								}
2687 								else
2688 								{
2689 									start_internal_command(Id, plci, fax_adjust_b23_command);
2690 									return false;
2691 								}
2692 							}
2693 						}
2694 					}
2695 					else  Info = _WRONG_STATE;
2696 				}
2697 				else  Info = _WRONG_STATE;
2698 			}
2699 
2700 			else if (plci->B3_prot == B3_RTP)
2701 			{
2702 				plci->internal_req_buffer[0] = ncpi->length + 1;
2703 				plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2704 				for (w = 0; w < ncpi->length; w++)
2705 					plci->internal_req_buffer[2 + w] = ncpi->info[1 + w];
2706 				start_internal_command(Id, plci, rtp_connect_b3_req_command);
2707 				return false;
2708 			}
2709 
2710 			if (!Info)
2711 			{
2712 				nl_req_ncci(plci, req, 0);
2713 				return 1;
2714 			}
2715 		}
2716 	}
2717 	else Info = _WRONG_IDENTIFIER;
2718 
2719 	sendf(appl,
2720 	      _CONNECT_B3_R | CONFIRM,
2721 	      Id,
2722 	      Number,
2723 	      "w", Info);
2724 	return false;
2725 }
2726 
connect_b3_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)2727 static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2728 			   PLCI *plci, APPL *appl, API_PARSE *parms)
2729 {
2730 	word ncci;
2731 	API_PARSE *ncpi;
2732 	byte req;
2733 
2734 	word w;
2735 
2736 
2737 	API_PARSE fax_parms[9];
2738 	word i;
2739 	byte len;
2740 
2741 
2742 	dbug(1, dprintf("connect_b3_res"));
2743 
2744 	ncci = (word)(Id >> 16);
2745 	if (plci && ncci) {
2746 		if (a->ncci_state[ncci] == INC_CON_PENDING) {
2747 			if (GET_WORD(&parms[0].info[0]) != 0)
2748 			{
2749 				a->ncci_state[ncci] = OUTG_REJ_PENDING;
2750 				channel_request_xon(plci, a->ncci_ch[ncci]);
2751 				channel_xmit_xon(plci);
2752 				cleanup_ncci_data(plci, ncci);
2753 				nl_req_ncci(plci, N_DISC, (byte)ncci);
2754 				return 1;
2755 			}
2756 			a->ncci_state[ncci] = INC_ACT_PENDING;
2757 
2758 			req = N_CONNECT_ACK;
2759 			ncpi = &parms[1];
2760 			if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2761 			{
2762 
2763 				if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
2764 				    & (1L << PRIVATE_FAX_NONSTANDARD))
2765 				{
2766 					if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2767 					    && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2768 					    && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2769 					{
2770 						len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2771 						if (plci->fax_connect_info_length < len)
2772 						{
2773 							((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2774 							((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2775 						}
2776 						if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2777 						{
2778 							dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2779 						}
2780 						else
2781 						{
2782 							if (plci->fax_connect_info_length <= len)
2783 								plci->fax_connect_info_buffer[len] = 0;
2784 							len += 1 + plci->fax_connect_info_buffer[len];
2785 							if (plci->fax_connect_info_length <= len)
2786 								plci->fax_connect_info_buffer[len] = 0;
2787 							len += 1 + plci->fax_connect_info_buffer[len];
2788 							if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2789 								plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2790 							plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2791 							for (i = 0; i < fax_parms[7].length; i++)
2792 								plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2793 						}
2794 						plci->fax_connect_info_length = len;
2795 						((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2796 						start_internal_command(Id, plci, fax_connect_ack_command);
2797 						return false;
2798 					}
2799 				}
2800 
2801 				nl_req_ncci(plci, req, (byte)ncci);
2802 				if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2803 				    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2804 				{
2805 					if (plci->B3_prot == 4)
2806 						sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2807 					else
2808 						sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
2809 					plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2810 				}
2811 			}
2812 
2813 			else if (plci->B3_prot == B3_RTP)
2814 			{
2815 				plci->internal_req_buffer[0] = ncpi->length + 1;
2816 				plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2817 				for (w = 0; w < ncpi->length; w++)
2818 					plci->internal_req_buffer[2 + w] = ncpi->info[1+w];
2819 				start_internal_command(Id, plci, rtp_connect_b3_res_command);
2820 				return false;
2821 			}
2822 
2823 			else
2824 			{
2825 				if (ncpi->length > 2) {
2826 					if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
2827 					add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2828 				}
2829 				nl_req_ncci(plci, req, (byte)ncci);
2830 				sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2831 				if (plci->adjust_b_restore)
2832 				{
2833 					plci->adjust_b_restore = false;
2834 					start_internal_command(Id, plci, adjust_b_restore);
2835 				}
2836 			}
2837 			return 1;
2838 		}
2839 	}
2840 	return false;
2841 }
2842 
connect_b3_a_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)2843 static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2844 			     PLCI *plci, APPL *appl, API_PARSE *parms)
2845 {
2846 	word ncci;
2847 
2848 	ncci = (word)(Id >> 16);
2849 	dbug(1, dprintf("connect_b3_a_res(ncci=0x%x)", ncci));
2850 
2851 	if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2852 	    && (plci->State != OUTG_DIS_PENDING))
2853 	{
2854 		if (a->ncci_state[ncci] == INC_ACT_PENDING) {
2855 			a->ncci_state[ncci] = CONNECTED;
2856 			if (plci->State != INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2857 			channel_request_xon(plci, a->ncci_ch[ncci]);
2858 			channel_xmit_xon(plci);
2859 		}
2860 	}
2861 	return false;
2862 }
2863 
disconnect_b3_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)2864 static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2865 			      PLCI *plci, APPL *appl, API_PARSE *parms)
2866 {
2867 	word Info;
2868 	word ncci;
2869 	API_PARSE *ncpi;
2870 
2871 	dbug(1, dprintf("disconnect_b3_req"));
2872 
2873 	Info = _WRONG_IDENTIFIER;
2874 	ncci = (word)(Id >> 16);
2875 	if (plci && ncci)
2876 	{
2877 		Info = _WRONG_STATE;
2878 		if ((a->ncci_state[ncci] == CONNECTED)
2879 		    || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2880 		    || (a->ncci_state[ncci] == INC_CON_PENDING)
2881 		    || (a->ncci_state[ncci] == INC_ACT_PENDING))
2882 		{
2883 			a->ncci_state[ncci] = OUTG_DIS_PENDING;
2884 			channel_request_xon(plci, a->ncci_ch[ncci]);
2885 			channel_xmit_xon(plci);
2886 
2887 			if (a->ncci[ncci].data_pending
2888 			    && ((plci->B3_prot == B3_TRANSPARENT)
2889 				|| (plci->B3_prot == B3_T30)
2890 				|| (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
2891 			{
2892 				plci->send_disc = (byte)ncci;
2893 				plci->command = 0;
2894 				return false;
2895 			}
2896 			else
2897 			{
2898 				cleanup_ncci_data(plci, ncci);
2899 
2900 				if (plci->B3_prot == 2 || plci->B3_prot == 3)
2901 				{
2902 					ncpi = &parms[0];
2903 					if (ncpi->length > 3)
2904 					{
2905 						add_d(plci, (word)(ncpi->length - 3), (byte *)&(ncpi->info[4]));
2906 					}
2907 				}
2908 				nl_req_ncci(plci, N_DISC, (byte)ncci);
2909 			}
2910 			return 1;
2911 		}
2912 	}
2913 	sendf(appl,
2914 	      _DISCONNECT_B3_R | CONFIRM,
2915 	      Id,
2916 	      Number,
2917 	      "w", Info);
2918 	return false;
2919 }
2920 
disconnect_b3_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)2921 static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2922 			      PLCI *plci, APPL *appl, API_PARSE *parms)
2923 {
2924 	word ncci;
2925 	word i;
2926 
2927 	ncci = (word)(Id >> 16);
2928 	dbug(1, dprintf("disconnect_b3_res(ncci=0x%x", ncci));
2929 	if (plci && ncci) {
2930 		plci->requested_options_conn = 0;
2931 		plci->fax_connect_info_length = 0;
2932 		plci->ncpi_state = 0x00;
2933 		if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2934 		    && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
2935 		{
2936 			plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
2937 		}
2938 		for (i = 0; i < MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i] != (byte)ncci; i++);
2939 		if (i < MAX_CHANNELS_PER_PLCI) {
2940 			if (plci->channels)plci->channels--;
2941 			for (; i < MAX_CHANNELS_PER_PLCI - 1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i + 1];
2942 			plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI - 1] = 0;
2943 
2944 			ncci_free_receive_buffers(plci, ncci);
2945 
2946 			if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
2947 				if (plci->State == SUSPENDING) {
2948 					sendf(plci->appl,
2949 					      _FACILITY_I,
2950 					      Id & 0xffffL,
2951 					      0,
2952 					      "ws", (word)3, "\x03\x04\x00\x00");
2953 					sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
2954 				}
2955 				plci_remove(plci);
2956 				plci->State = IDLE;
2957 			}
2958 		}
2959 		else
2960 		{
2961 			if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
2962 			    && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
2963 			    && (a->ncci_state[ncci] == INC_DIS_PENDING))
2964 			{
2965 				ncci_free_receive_buffers(plci, ncci);
2966 
2967 				nl_req_ncci(plci, N_EDATA, (byte)ncci);
2968 
2969 				plci->adapter->ncci_state[ncci] = IDLE;
2970 				start_internal_command(Id, plci, fax_disconnect_command);
2971 				return 1;
2972 			}
2973 		}
2974 	}
2975 	return false;
2976 }
2977 
data_b3_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)2978 static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2979 			PLCI *plci, APPL *appl, API_PARSE *parms)
2980 {
2981 	NCCI *ncci_ptr;
2982 	DATA_B3_DESC *data;
2983 	word Info;
2984 	word ncci;
2985 	word i;
2986 
2987 	dbug(1, dprintf("data_b3_req"));
2988 
2989 	Info = _WRONG_IDENTIFIER;
2990 	ncci = (word)(Id >> 16);
2991 	dbug(1, dprintf("ncci=0x%x, plci=0x%x", ncci, plci));
2992 
2993 	if (plci && ncci)
2994 	{
2995 		Info = _WRONG_STATE;
2996 		if ((a->ncci_state[ncci] == CONNECTED)
2997 		    || (a->ncci_state[ncci] == INC_ACT_PENDING))
2998 		{
2999 			/* queue data */
3000 			ncci_ptr = &(a->ncci[ncci]);
3001 			i = ncci_ptr->data_out + ncci_ptr->data_pending;
3002 			if (i >= MAX_DATA_B3)
3003 				i -= MAX_DATA_B3;
3004 			data = &(ncci_ptr->DBuffer[i]);
3005 			data->Number = Number;
3006 			if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3007 			    && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3008 			{
3009 
3010 				data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3011 
3012 			}
3013 			else
3014 				data->P = TransmitBufferSet(appl, *(dword *)parms[0].info);
3015 			data->Length = GET_WORD(parms[1].info);
3016 			data->Handle = GET_WORD(parms[2].info);
3017 			data->Flags = GET_WORD(parms[3].info);
3018 			(ncci_ptr->data_pending)++;
3019 
3020 			/* check for delivery confirmation */
3021 			if (data->Flags & 0x0004)
3022 			{
3023 				i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3024 				if (i >= MAX_DATA_ACK)
3025 					i -= MAX_DATA_ACK;
3026 				ncci_ptr->DataAck[i].Number = data->Number;
3027 				ncci_ptr->DataAck[i].Handle = data->Handle;
3028 				(ncci_ptr->data_ack_pending)++;
3029 			}
3030 
3031 			send_data(plci);
3032 			return false;
3033 		}
3034 	}
3035 	if (appl)
3036 	{
3037 		if (plci)
3038 		{
3039 			if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3040 			    && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3041 			{
3042 
3043 				TransmitBufferFree(appl, (byte *)(long)(*((dword *)(parms[0].info))));
3044 
3045 			}
3046 		}
3047 		sendf(appl,
3048 		      _DATA_B3_R | CONFIRM,
3049 		      Id,
3050 		      Number,
3051 		      "ww", GET_WORD(parms[2].info), Info);
3052 	}
3053 	return false;
3054 }
3055 
data_b3_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)3056 static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3057 			PLCI *plci, APPL *appl, API_PARSE *parms)
3058 {
3059 	word n;
3060 	word ncci;
3061 	word NCCIcode;
3062 
3063 	dbug(1, dprintf("data_b3_res"));
3064 
3065 	ncci = (word)(Id >> 16);
3066 	if (plci && ncci) {
3067 		n = GET_WORD(parms[0].info);
3068 		dbug(1, dprintf("free(%d)", n));
3069 		NCCIcode = ncci | (((word) a->Id) << 8);
3070 		if (n < appl->MaxBuffer &&
3071 		    appl->DataNCCI[n] == NCCIcode &&
3072 		    (byte)(appl->DataFlags[n] >> 8) == plci->Id) {
3073 			dbug(1, dprintf("found"));
3074 			appl->DataNCCI[n] = 0;
3075 
3076 			if (channel_can_xon(plci, a->ncci_ch[ncci])) {
3077 				channel_request_xon(plci, a->ncci_ch[ncci]);
3078 			}
3079 			channel_xmit_xon(plci);
3080 
3081 			if (appl->DataFlags[n] & 4) {
3082 				nl_req_ncci(plci, N_DATA_ACK, (byte)ncci);
3083 				return 1;
3084 			}
3085 		}
3086 	}
3087 	return false;
3088 }
3089 
reset_b3_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)3090 static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3091 			 PLCI *plci, APPL *appl, API_PARSE *parms)
3092 {
3093 	word Info;
3094 	word ncci;
3095 
3096 	dbug(1, dprintf("reset_b3_req"));
3097 
3098 	Info = _WRONG_IDENTIFIER;
3099 	ncci = (word)(Id >> 16);
3100 	if (plci && ncci)
3101 	{
3102 		Info = _WRONG_STATE;
3103 		switch (plci->B3_prot)
3104 		{
3105 		case B3_ISO8208:
3106 		case B3_X25_DCE:
3107 			if (a->ncci_state[ncci] == CONNECTED)
3108 			{
3109 				nl_req_ncci(plci, N_RESET, (byte)ncci);
3110 				send_req(plci);
3111 				Info = GOOD;
3112 			}
3113 			break;
3114 		case B3_TRANSPARENT:
3115 			if (a->ncci_state[ncci] == CONNECTED)
3116 			{
3117 				start_internal_command(Id, plci, reset_b3_command);
3118 				Info = GOOD;
3119 			}
3120 			break;
3121 		}
3122 	}
3123 	/* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3124 	sendf(appl,
3125 	      _RESET_B3_R | CONFIRM,
3126 	      Id,
3127 	      Number,
3128 	      "w", Info);
3129 	return false;
3130 }
3131 
reset_b3_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)3132 static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3133 			 PLCI *plci, APPL *appl, API_PARSE *parms)
3134 {
3135 	word ncci;
3136 
3137 	dbug(1, dprintf("reset_b3_res"));
3138 
3139 	ncci = (word)(Id >> 16);
3140 	if (plci && ncci) {
3141 		switch (plci->B3_prot)
3142 		{
3143 		case B3_ISO8208:
3144 		case B3_X25_DCE:
3145 			if (a->ncci_state[ncci] == INC_RES_PENDING)
3146 			{
3147 				a->ncci_state[ncci] = CONNECTED;
3148 				nl_req_ncci(plci, N_RESET_ACK, (byte)ncci);
3149 				return true;
3150 			}
3151 			break;
3152 		}
3153 	}
3154 	return false;
3155 }
3156 
connect_b3_t90_a_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)3157 static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3158 				 PLCI *plci, APPL *appl, API_PARSE *parms)
3159 {
3160 	word ncci;
3161 	API_PARSE *ncpi;
3162 	byte req;
3163 
3164 	dbug(1, dprintf("connect_b3_t90_a_res"));
3165 
3166 	ncci = (word)(Id >> 16);
3167 	if (plci && ncci) {
3168 		if (a->ncci_state[ncci] == INC_ACT_PENDING) {
3169 			a->ncci_state[ncci] = CONNECTED;
3170 		}
3171 		else if (a->ncci_state[ncci] == INC_CON_PENDING) {
3172 			a->ncci_state[ncci] = CONNECTED;
3173 
3174 			req = N_CONNECT_ACK;
3175 
3176 			/* parms[0]==0 for CAPI original message definition! */
3177 			if (parms[0].info) {
3178 				ncpi = &parms[1];
3179 				if (ncpi->length > 2) {
3180 					if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
3181 					add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
3182 				}
3183 			}
3184 			nl_req_ncci(plci, req, (byte)ncci);
3185 			return 1;
3186 		}
3187 	}
3188 	return false;
3189 }
3190 
3191 
select_b_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)3192 static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3193 			 PLCI *plci, APPL *appl, API_PARSE *msg)
3194 {
3195 	word Info = 0;
3196 	word i;
3197 	byte tel;
3198 	API_PARSE bp_parms[7];
3199 
3200 	if (!plci || !msg)
3201 	{
3202 		Info = _WRONG_IDENTIFIER;
3203 	}
3204 	else
3205 	{
3206 		dbug(1, dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3207 				msg->length, plci->Id, plci->tel, plci->NL.Id, plci->appl, plci->SuppState));
3208 		dbug(1, dprintf("PlciState=0x%x", plci->State));
3209 		for (i = 0; i < 7; i++) bp_parms[i].length = 0;
3210 
3211 		/* check if no channel is open, no B3 connected only */
3212 		if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3213 		    || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3214 		{
3215 			Info = _WRONG_STATE;
3216 		}
3217 		/* check message format and fill bp_parms pointer */
3218 		else if (msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3219 		{
3220 			Info = _WRONG_MESSAGE_FORMAT;
3221 		}
3222 		else
3223 		{
3224 			if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT)) /* send alert tone inband to the network, */
3225 			{                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3226 				if (Id & EXT_CONTROLLER)
3227 				{
3228 					sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3229 					return 0;
3230 				}
3231 				plci->State = INC_CON_CONNECTED_ALERT;
3232 				plci->appl = appl;
3233 				__clear_bit(appl->Id - 1, plci->c_ind_mask_table);
3234 				dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
3235 				/* disconnect the other appls its quasi a connect */
3236 				for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
3237 					sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3238 			}
3239 
3240 			api_save_msg(msg, "s", &plci->saved_msg);
3241 			tel = plci->tel;
3242 			if (Id & EXT_CONTROLLER)
3243 			{
3244 				if (tel) /* external controller in use by this PLCI */
3245 				{
3246 					if (a->AdvSignalAppl && a->AdvSignalAppl != appl)
3247 					{
3248 						dbug(1, dprintf("Ext_Ctrl in use 1"));
3249 						Info = _WRONG_STATE;
3250 					}
3251 				}
3252 				else  /* external controller NOT in use by this PLCI ? */
3253 				{
3254 					if (a->AdvSignalPLCI)
3255 					{
3256 						dbug(1, dprintf("Ext_Ctrl in use 2"));
3257 						Info = _WRONG_STATE;
3258 					}
3259 					else /* activate the codec */
3260 					{
3261 						dbug(1, dprintf("Ext_Ctrl start"));
3262 						if (AdvCodecSupport(a, plci, appl, 0))
3263 						{
3264 							dbug(1, dprintf("Error in codec procedures"));
3265 							Info = _WRONG_STATE;
3266 						}
3267 						else if (plci->spoofed_msg == SPOOFING_REQUIRED) /* wait until codec is active */
3268 						{
3269 							plci->spoofed_msg = AWAITING_SELECT_B;
3270 							plci->internal_command = BLOCK_PLCI; /* lock other commands */
3271 							plci->command = 0;
3272 							dbug(1, dprintf("continue if codec loaded"));
3273 							return false;
3274 						}
3275 					}
3276 				}
3277 			}
3278 			else /* external controller bit is OFF */
3279 			{
3280 				if (tel) /* external controller in use, need to switch off */
3281 				{
3282 					if (a->AdvSignalAppl == appl)
3283 					{
3284 						CodecIdCheck(a, plci);
3285 						plci->tel = 0;
3286 						plci->adv_nl = 0;
3287 						dbug(1, dprintf("Ext_Ctrl disable"));
3288 					}
3289 					else
3290 					{
3291 						dbug(1, dprintf("Ext_Ctrl not requested"));
3292 					}
3293 				}
3294 			}
3295 			if (!Info)
3296 			{
3297 				if (plci->call_dir & CALL_DIR_OUT)
3298 					plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3299 				else if (plci->call_dir & CALL_DIR_IN)
3300 					plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3301 				start_internal_command(Id, plci, select_b_command);
3302 				return false;
3303 			}
3304 		}
3305 	}
3306 	sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", Info);
3307 	return false;
3308 }
3309 
manufacturer_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)3310 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3311 			     PLCI *plci, APPL *appl, API_PARSE *parms)
3312 {
3313 	word command;
3314 	word i;
3315 	word ncci;
3316 	API_PARSE *m;
3317 	API_PARSE m_parms[5];
3318 	word codec;
3319 	byte req;
3320 	byte ch;
3321 	byte dir;
3322 	static byte chi[2] = {0x01, 0x00};
3323 	static byte lli[2] = {0x01, 0x00};
3324 	static byte codec_cai[2] = {0x01, 0x01};
3325 	static byte null_msg = {0};
3326 	static API_PARSE null_parms = { 0, &null_msg };
3327 	PLCI *v_plci;
3328 	word Info = 0;
3329 
3330 	dbug(1, dprintf("manufacturer_req"));
3331 	for (i = 0; i < 5; i++) m_parms[i].length = 0;
3332 
3333 	if (GET_DWORD(parms[0].info) != _DI_MANU_ID) {
3334 		Info = _WRONG_MESSAGE_FORMAT;
3335 	}
3336 	command = GET_WORD(parms[1].info);
3337 	m = &parms[2];
3338 	if (!Info)
3339 	{
3340 		switch (command) {
3341 		case _DI_ASSIGN_PLCI:
3342 			if (api_parse(&m->info[1], (word)m->length, "wbbs", m_parms)) {
3343 				Info = _WRONG_MESSAGE_FORMAT;
3344 				break;
3345 			}
3346 			codec = GET_WORD(m_parms[0].info);
3347 			ch = m_parms[1].info[0];
3348 			dir = m_parms[2].info[0];
3349 			if ((i = get_plci(a))) {
3350 				plci = &a->plci[i - 1];
3351 				plci->appl = appl;
3352 				plci->command = _MANUFACTURER_R;
3353 				plci->m_command = command;
3354 				plci->number = Number;
3355 				plci->State = LOCAL_CONNECT;
3356 				Id = (((word)plci->Id << 8) | plci->adapter->Id | 0x80);
3357 				dbug(1, dprintf("ManCMD,plci=0x%x", Id));
3358 
3359 				if ((ch == 1 || ch == 2) && (dir <= 2)) {
3360 					chi[1] = (byte)(0x80 | ch);
3361 					lli[1] = 0;
3362 					plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3363 					switch (codec)
3364 					{
3365 					case 0:
3366 						Info = add_b1(plci, &m_parms[3], 0, 0);
3367 						break;
3368 					case 1:
3369 						add_p(plci, CAI, codec_cai);
3370 						break;
3371 						/* manual 'swich on' to the codec support without signalling */
3372 						/* first 'assign plci' with this function, then use */
3373 					case 2:
3374 						if (AdvCodecSupport(a, plci, appl, 0)) {
3375 							Info = _RESOURCE_ERROR;
3376 						}
3377 						else {
3378 							Info = add_b1(plci, &null_parms, 0, B1_FACILITY_LOCAL);
3379 							lli[1] = 0x10; /* local call codec stream */
3380 						}
3381 						break;
3382 					}
3383 
3384 					plci->State = LOCAL_CONNECT;
3385 					plci->manufacturer = true;
3386 					plci->command = _MANUFACTURER_R;
3387 					plci->m_command = command;
3388 					plci->number = Number;
3389 
3390 					if (!Info)
3391 					{
3392 						add_p(plci, LLI, lli);
3393 						add_p(plci, CHI, chi);
3394 						add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
3395 						sig_req(plci, ASSIGN, DSIG_ID);
3396 
3397 						if (!codec)
3398 						{
3399 							Info = add_b23(plci, &m_parms[3]);
3400 							if (!Info)
3401 							{
3402 								nl_req_ncci(plci, ASSIGN, 0);
3403 								send_req(plci);
3404 							}
3405 						}
3406 						if (!Info)
3407 						{
3408 							dbug(1, dprintf("dir=0x%x,spoof=0x%x", dir, plci->spoofed_msg));
3409 							if (plci->spoofed_msg == SPOOFING_REQUIRED)
3410 							{
3411 								api_save_msg(m_parms, "wbbs", &plci->saved_msg);
3412 								plci->spoofed_msg = AWAITING_MANUF_CON;
3413 								plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3414 								plci->command = 0;
3415 								send_req(plci);
3416 								return false;
3417 							}
3418 							if (dir == 1) {
3419 								sig_req(plci, CALL_REQ, 0);
3420 							}
3421 							else if (!dir) {
3422 								sig_req(plci, LISTEN_REQ, 0);
3423 							}
3424 							send_req(plci);
3425 						}
3426 						else
3427 						{
3428 							sendf(appl,
3429 							      _MANUFACTURER_R | CONFIRM,
3430 							      Id,
3431 							      Number,
3432 							      "dww", _DI_MANU_ID, command, Info);
3433 							return 2;
3434 						}
3435 					}
3436 				}
3437 			}
3438 			else  Info = _OUT_OF_PLCI;
3439 			break;
3440 
3441 		case _DI_IDI_CTRL:
3442 			if (!plci)
3443 			{
3444 				Info = _WRONG_IDENTIFIER;
3445 				break;
3446 			}
3447 			if (api_parse(&m->info[1], (word)m->length, "bs", m_parms)) {
3448 				Info = _WRONG_MESSAGE_FORMAT;
3449 				break;
3450 			}
3451 			req = m_parms[0].info[0];
3452 			plci->command = _MANUFACTURER_R;
3453 			plci->m_command = command;
3454 			plci->number = Number;
3455 			if (req == CALL_REQ)
3456 			{
3457 				plci->b_channel = getChannel(&m_parms[1]);
3458 				mixer_set_bchannel_id_esc(plci, plci->b_channel);
3459 				if (plci->spoofed_msg == SPOOFING_REQUIRED)
3460 				{
3461 					plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3462 					plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3463 					plci->command = 0;
3464 					break;
3465 				}
3466 			}
3467 			else if (req == LAW_REQ)
3468 			{
3469 				plci->cr_enquiry = true;
3470 			}
3471 			add_ss(plci, FTY, &m_parms[1]);
3472 			sig_req(plci, req, 0);
3473 			send_req(plci);
3474 			if (req == HANGUP)
3475 			{
3476 				if (plci->NL.Id && !plci->nl_remove_id)
3477 				{
3478 					if (plci->channels)
3479 					{
3480 						for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
3481 						{
3482 							if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3483 							{
3484 								a->ncci_state[ncci] = OUTG_DIS_PENDING;
3485 								cleanup_ncci_data(plci, ncci);
3486 								nl_req_ncci(plci, N_DISC, (byte)ncci);
3487 							}
3488 						}
3489 					}
3490 					mixer_remove(plci);
3491 					nl_req_ncci(plci, REMOVE, 0);
3492 					send_req(plci);
3493 				}
3494 			}
3495 			break;
3496 
3497 		case _DI_SIG_CTRL:
3498 			/* signalling control for loop activation B-channel */
3499 			if (!plci)
3500 			{
3501 				Info = _WRONG_IDENTIFIER;
3502 				break;
3503 			}
3504 			if (m->length) {
3505 				plci->command = _MANUFACTURER_R;
3506 				plci->number = Number;
3507 				add_ss(plci, FTY, m);
3508 				sig_req(plci, SIG_CTRL, 0);
3509 				send_req(plci);
3510 			}
3511 			else Info = _WRONG_MESSAGE_FORMAT;
3512 			break;
3513 
3514 		case _DI_RXT_CTRL:
3515 			/* activation control for receiver/transmitter B-channel */
3516 			if (!plci)
3517 			{
3518 				Info = _WRONG_IDENTIFIER;
3519 				break;
3520 			}
3521 			if (m->length) {
3522 				plci->command = _MANUFACTURER_R;
3523 				plci->number = Number;
3524 				add_ss(plci, FTY, m);
3525 				sig_req(plci, DSP_CTRL, 0);
3526 				send_req(plci);
3527 			}
3528 			else Info = _WRONG_MESSAGE_FORMAT;
3529 			break;
3530 
3531 		case _DI_ADV_CODEC:
3532 		case _DI_DSP_CTRL:
3533 			/* TEL_CTRL commands to support non standard adjustments: */
3534 			/* Ring on/off, Handset micro volume, external micro vol. */
3535 			/* handset+external speaker volume, receiver+transm. gain,*/
3536 			/* handsfree on (hookinfo off), set mixer command         */
3537 
3538 			if (command == _DI_ADV_CODEC)
3539 			{
3540 				if (!a->AdvCodecPLCI) {
3541 					Info = _WRONG_STATE;
3542 					break;
3543 				}
3544 				v_plci = a->AdvCodecPLCI;
3545 			}
3546 			else
3547 			{
3548 				if (plci
3549 				    && (m->length >= 3)
3550 				    && (m->info[1] == 0x1c)
3551 				    && (m->info[2] >= 1))
3552 				{
3553 					if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3554 					{
3555 						if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3556 						{
3557 							Info = _WRONG_STATE;
3558 							break;
3559 						}
3560 						a->adv_voice_coef_length = m->info[2] - 1;
3561 						if (a->adv_voice_coef_length > m->length - 3)
3562 							a->adv_voice_coef_length = (byte)(m->length - 3);
3563 						if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3564 							a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3565 						for (i = 0; i < a->adv_voice_coef_length; i++)
3566 							a->adv_voice_coef_buffer[i] = m->info[4 + i];
3567 						if (plci->B1_facilities & B1_FACILITY_VOICE)
3568 							adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
3569 						break;
3570 					}
3571 					else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3572 					{
3573 						if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3574 						{
3575 							Info = _FACILITY_NOT_SUPPORTED;
3576 							break;
3577 						}
3578 
3579 						plci->dtmf_parameter_length = m->info[2] - 1;
3580 						if (plci->dtmf_parameter_length > m->length - 3)
3581 							plci->dtmf_parameter_length = (byte)(m->length - 3);
3582 						if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3583 							plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3584 						for (i = 0; i < plci->dtmf_parameter_length; i++)
3585 							plci->dtmf_parameter_buffer[i] = m->info[4 + i];
3586 						if (plci->B1_facilities & B1_FACILITY_DTMFR)
3587 							dtmf_parameter_write(plci);
3588 						break;
3589 
3590 					}
3591 				}
3592 				v_plci = plci;
3593 			}
3594 
3595 			if (!v_plci)
3596 			{
3597 				Info = _WRONG_IDENTIFIER;
3598 				break;
3599 			}
3600 			if (m->length) {
3601 				add_ss(v_plci, FTY, m);
3602 				sig_req(v_plci, TEL_CTRL, 0);
3603 				send_req(v_plci);
3604 			}
3605 			else Info = _WRONG_MESSAGE_FORMAT;
3606 
3607 			break;
3608 
3609 		case _DI_OPTIONS_REQUEST:
3610 			if (api_parse(&m->info[1], (word)m->length, "d", m_parms)) {
3611 				Info = _WRONG_MESSAGE_FORMAT;
3612 				break;
3613 			}
3614 			if (GET_DWORD(m_parms[0].info) & ~a->man_profile.private_options)
3615 			{
3616 				Info = _FACILITY_NOT_SUPPORTED;
3617 				break;
3618 			}
3619 			a->requested_options_table[appl->Id - 1] = GET_DWORD(m_parms[0].info);
3620 			break;
3621 
3622 
3623 
3624 		default:
3625 			Info = _WRONG_MESSAGE_FORMAT;
3626 			break;
3627 		}
3628 	}
3629 
3630 	sendf(appl,
3631 	      _MANUFACTURER_R | CONFIRM,
3632 	      Id,
3633 	      Number,
3634 	      "dww", _DI_MANU_ID, command, Info);
3635 	return false;
3636 }
3637 
3638 
manufacturer_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)3639 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3640 			     PLCI *plci, APPL *appl, API_PARSE *msg)
3641 {
3642 	word indication;
3643 
3644 	API_PARSE m_parms[3];
3645 	API_PARSE *ncpi;
3646 	API_PARSE fax_parms[9];
3647 	word i;
3648 	byte len;
3649 
3650 
3651 	dbug(1, dprintf("manufacturer_res"));
3652 
3653 	if ((msg[0].length == 0)
3654 	    || (msg[1].length == 0)
3655 	    || (GET_DWORD(msg[0].info) != _DI_MANU_ID))
3656 	{
3657 		return false;
3658 	}
3659 	indication = GET_WORD(msg[1].info);
3660 	switch (indication)
3661 	{
3662 
3663 	case _DI_NEGOTIATE_B3:
3664 		if (!plci)
3665 			break;
3666 		if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3667 		    || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3668 		{
3669 			dbug(1, dprintf("wrong state for NEGOTIATE_B3 parameters"));
3670 			break;
3671 		}
3672 		if (api_parse(&msg[2].info[1], msg[2].length, "ws", m_parms))
3673 		{
3674 			dbug(1, dprintf("wrong format in NEGOTIATE_B3 parameters"));
3675 			break;
3676 		}
3677 		ncpi = &m_parms[1];
3678 		len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
3679 		if (plci->fax_connect_info_length < len)
3680 		{
3681 			((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3682 			((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3683 		}
3684 		if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3685 		{
3686 			dbug(1, dprintf("non-standard facilities info missing or wrong format"));
3687 		}
3688 		else
3689 		{
3690 			if (plci->fax_connect_info_length <= len)
3691 				plci->fax_connect_info_buffer[len] = 0;
3692 			len += 1 + plci->fax_connect_info_buffer[len];
3693 			if (plci->fax_connect_info_length <= len)
3694 				plci->fax_connect_info_buffer[len] = 0;
3695 			len += 1 + plci->fax_connect_info_buffer[len];
3696 			if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3697 				plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3698 			plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3699 			for (i = 0; i < fax_parms[7].length; i++)
3700 				plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
3701 		}
3702 		plci->fax_connect_info_length = len;
3703 		plci->fax_edata_ack_length = plci->fax_connect_info_length;
3704 		start_internal_command(Id, plci, fax_edata_ack_command);
3705 		break;
3706 
3707 	}
3708 	return false;
3709 }
3710 
3711 /*------------------------------------------------------------------*/
3712 /* IDI callback function                                            */
3713 /*------------------------------------------------------------------*/
3714 
callback(ENTITY * e)3715 void callback(ENTITY *e)
3716 {
3717 	DIVA_CAPI_ADAPTER *a;
3718 	APPL *appl;
3719 	PLCI *plci;
3720 	CAPI_MSG *m;
3721 	word i, j;
3722 	byte rc;
3723 	byte ch;
3724 	byte req;
3725 	byte global_req;
3726 	int no_cancel_rc;
3727 
3728 	dbug(1, dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3729 			(e->user[0] + 1) & 0x7fff, e->Id, e->Req, e->Rc, e->Ind));
3730 
3731 	a = &(adapter[(byte)e->user[0]]);
3732 	plci = &(a->plci[e->user[1]]);
3733 	no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3734 
3735 	/*
3736 	  If new protocol code and new XDI is used then CAPI should work
3737 	  fully in accordance with IDI cpec an look on callback field instead
3738 	  of Rc field for return codes.
3739 	*/
3740 	if (((e->complete == 0xff) && no_cancel_rc) ||
3741 	    (e->Rc && !no_cancel_rc)) {
3742 		rc = e->Rc;
3743 		ch = e->RcCh;
3744 		req = e->Req;
3745 		e->Rc = 0;
3746 
3747 		if (e->user[0] & 0x8000)
3748 		{
3749 			/*
3750 			  If REMOVE request was sent then we have to wait until
3751 			  return code with Id set to zero arrives.
3752 			  All other return codes should be ignored.
3753 			*/
3754 			if (req == REMOVE)
3755 			{
3756 				if (e->Id)
3757 				{
3758 					dbug(1, dprintf("cancel RC in REMOVE state"));
3759 					return;
3760 				}
3761 				channel_flow_control_remove(plci);
3762 				for (i = 0; i < 256; i++)
3763 				{
3764 					if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3765 						a->FlowControlIdTable[i] = 0;
3766 				}
3767 				plci->nl_remove_id = 0;
3768 				if (plci->rx_dma_descriptor > 0) {
3769 					diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3770 					plci->rx_dma_descriptor = 0;
3771 				}
3772 			}
3773 			if (rc == OK_FC)
3774 			{
3775 				a->FlowControlIdTable[ch] = e->Id;
3776 				a->FlowControlSkipTable[ch] = 0;
3777 
3778 				a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3779 				a->ch_flow_plci[ch] = plci->Id;
3780 				plci->nl_req = 0;
3781 			}
3782 			else
3783 			{
3784 				/*
3785 				  Cancel return codes self, if feature was requested
3786 				*/
3787 				if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3788 					a->FlowControlIdTable[ch] = 0;
3789 					if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3790 						dbug(3, dprintf("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3791 						return;
3792 					}
3793 				}
3794 
3795 				if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3796 				{
3797 					a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3798 					if (ch == e->ReqCh)
3799 						plci->nl_req = 0;
3800 				}
3801 				else
3802 					plci->nl_req = 0;
3803 			}
3804 			if (plci->nl_req)
3805 				control_rc(plci, 0, rc, ch, 0, true);
3806 			else
3807 			{
3808 				if (req == N_XON)
3809 				{
3810 					channel_x_on(plci, ch);
3811 					if (plci->internal_command)
3812 						control_rc(plci, req, rc, ch, 0, true);
3813 				}
3814 				else
3815 				{
3816 					if (plci->nl_global_req)
3817 					{
3818 						global_req = plci->nl_global_req;
3819 						plci->nl_global_req = 0;
3820 						if (rc != ASSIGN_OK) {
3821 							e->Id = 0;
3822 							if (plci->rx_dma_descriptor > 0) {
3823 								diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3824 								plci->rx_dma_descriptor = 0;
3825 							}
3826 						}
3827 						channel_xmit_xon(plci);
3828 						control_rc(plci, 0, rc, ch, global_req, true);
3829 					}
3830 					else if (plci->data_sent)
3831 					{
3832 						channel_xmit_xon(plci);
3833 						plci->data_sent = false;
3834 						plci->NL.XNum = 1;
3835 						data_rc(plci, ch);
3836 						if (plci->internal_command)
3837 							control_rc(plci, req, rc, ch, 0, true);
3838 					}
3839 					else
3840 					{
3841 						channel_xmit_xon(plci);
3842 						control_rc(plci, req, rc, ch, 0, true);
3843 					}
3844 				}
3845 			}
3846 		}
3847 		else
3848 		{
3849 			/*
3850 			  If REMOVE request was sent then we have to wait until
3851 			  return code with Id set to zero arrives.
3852 			  All other return codes should be ignored.
3853 			*/
3854 			if (req == REMOVE)
3855 			{
3856 				if (e->Id)
3857 				{
3858 					dbug(1, dprintf("cancel RC in REMOVE state"));
3859 					return;
3860 				}
3861 				plci->sig_remove_id = 0;
3862 			}
3863 			plci->sig_req = 0;
3864 			if (plci->sig_global_req)
3865 			{
3866 				global_req = plci->sig_global_req;
3867 				plci->sig_global_req = 0;
3868 				if (rc != ASSIGN_OK)
3869 					e->Id = 0;
3870 				channel_xmit_xon(plci);
3871 				control_rc(plci, 0, rc, ch, global_req, false);
3872 			}
3873 			else
3874 			{
3875 				channel_xmit_xon(plci);
3876 				control_rc(plci, req, rc, ch, 0, false);
3877 			}
3878 		}
3879 		/*
3880 		  Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3881 		  same callback. Also if new XDI and protocol code used then jump
3882 		  direct to finish.
3883 		*/
3884 		if (no_cancel_rc) {
3885 			channel_xmit_xon(plci);
3886 			goto capi_callback_suffix;
3887 		}
3888 	}
3889 
3890 	channel_xmit_xon(plci);
3891 
3892 	if (e->Ind) {
3893 		if (e->user[0] & 0x8000) {
3894 			byte Ind = e->Ind & 0x0f;
3895 			byte Ch = e->IndCh;
3896 			if (((Ind == N_DISC) || (Ind == N_DISC_ACK)) &&
3897 			    (a->ch_flow_plci[Ch] == plci->Id)) {
3898 				if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
3899 					dbug(3, dprintf("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
3900 				}
3901 				a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
3902 			}
3903 			nl_ind(plci);
3904 			if ((e->RNR != 1) &&
3905 			    (a->ch_flow_plci[Ch] == plci->Id) &&
3906 			    (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
3907 				a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
3908 				dbug(3, dprintf("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
3909 			}
3910 		} else {
3911 			sig_ind(plci);
3912 		}
3913 		e->Ind = 0;
3914 	}
3915 
3916 capi_callback_suffix:
3917 
3918 	while (!plci->req_in
3919 	       && !plci->internal_command
3920 	       && (plci->msg_in_write_pos != plci->msg_in_read_pos))
3921 	{
3922 		j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
3923 
3924 		i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
3925 
3926 		m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
3927 		appl = *((APPL **)(&((byte *)(plci->msg_in_queue))[j + i]));
3928 		dbug(1, dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
3929 				m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
3930 		if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
3931 		{
3932 			plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
3933 			plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
3934 		}
3935 		else
3936 		{
3937 			plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
3938 		}
3939 		if (plci->msg_in_read_pos == plci->msg_in_write_pos)
3940 		{
3941 			plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
3942 			plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
3943 		}
3944 		else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
3945 		{
3946 			plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
3947 			plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
3948 		}
3949 		i = api_put(appl, m);
3950 		if (i != 0)
3951 		{
3952 			if (m->header.command == _DATA_B3_R)
3953 
3954 				TransmitBufferFree(appl, (byte *)(long)(m->info.data_b3_req.Data));
3955 
3956 			dbug(1, dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
3957 			break;
3958 		}
3959 
3960 		if (plci->li_notify_update)
3961 		{
3962 			plci->li_notify_update = false;
3963 			mixer_notify_update(plci, false);
3964 		}
3965 
3966 	}
3967 	send_data(plci);
3968 	send_req(plci);
3969 }
3970 
3971 
control_rc(PLCI * plci,byte req,byte rc,byte ch,byte global_req,byte nl_rc)3972 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
3973 		       byte nl_rc)
3974 {
3975 	dword Id;
3976 	dword rId;
3977 	word Number;
3978 	word Info = 0;
3979 	word i;
3980 	word ncci;
3981 	DIVA_CAPI_ADAPTER *a;
3982 	APPL *appl;
3983 	PLCI *rplci;
3984 	byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
3985 	byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
3986 
3987 	if (!plci) {
3988 		dbug(0, dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
3989 		return;
3990 	}
3991 	dbug(1, dprintf("req0_in/out=%d/%d", plci->req_in, plci->req_out));
3992 	if (plci->req_in != plci->req_out)
3993 	{
3994 		if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
3995 		{
3996 			dbug(1, dprintf("req_1return"));
3997 			return;
3998 		}
3999 		/* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4000 	}
4001 	plci->req_in = plci->req_in_start = plci->req_out = 0;
4002 	dbug(1, dprintf("control_rc"));
4003 
4004 	appl = plci->appl;
4005 	a = plci->adapter;
4006 	ncci = a->ch_ncci[ch];
4007 	if (appl)
4008 	{
4009 		Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4010 		if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4011 		Number = plci->number;
4012 		dbug(1, dprintf("Contr_RC-Id=%08lx,plci=%x,tel=%x, entity=0x%x, command=0x%x, int_command=0x%x", Id, plci->Id, plci->tel, plci->Sig.Id, plci->command, plci->internal_command));
4013 		dbug(1, dprintf("channels=0x%x", plci->channels));
4014 		if (plci_remove_check(plci))
4015 			return;
4016 		if (req == REMOVE && rc == ASSIGN_OK)
4017 		{
4018 			sig_req(plci, HANGUP, 0);
4019 			sig_req(plci, REMOVE, 0);
4020 			send_req(plci);
4021 		}
4022 		if (plci->command)
4023 		{
4024 			switch (plci->command)
4025 			{
4026 			case C_HOLD_REQ:
4027 				dbug(1, dprintf("HoldRC=0x%x", rc));
4028 				SSparms[1] = (byte)S_HOLD;
4029 				if (rc != OK)
4030 				{
4031 					plci->SuppState = IDLE;
4032 					Info = 0x2001;
4033 				}
4034 				sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4035 				break;
4036 
4037 			case C_RETRIEVE_REQ:
4038 				dbug(1, dprintf("RetrieveRC=0x%x", rc));
4039 				SSparms[1] = (byte)S_RETRIEVE;
4040 				if (rc != OK)
4041 				{
4042 					plci->SuppState = CALL_HELD;
4043 					Info = 0x2001;
4044 				}
4045 				sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4046 				break;
4047 
4048 			case _INFO_R:
4049 				dbug(1, dprintf("InfoRC=0x%x", rc));
4050 				if (rc != OK) Info = _WRONG_STATE;
4051 				sendf(appl, _INFO_R | CONFIRM, Id, Number, "w", Info);
4052 				break;
4053 
4054 			case _CONNECT_R:
4055 				dbug(1, dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x", req, rc, global_req, nl_rc));
4056 				if (plci->State == INC_DIS_PENDING)
4057 					break;
4058 				if (plci->Sig.Id != 0xff)
4059 				{
4060 					if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4061 					    || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4062 					{
4063 						dbug(1, dprintf("No more IDs/Call_Req failed"));
4064 						sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4065 						plci_remove(plci);
4066 						plci->State = IDLE;
4067 						break;
4068 					}
4069 					if (plci->State != LOCAL_CONNECT) plci->State = OUTG_CON_PENDING;
4070 					sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4071 				}
4072 				else /* D-ch activation */
4073 				{
4074 					if (rc != ASSIGN_OK)
4075 					{
4076 						dbug(1, dprintf("No more IDs/X.25 Call_Req failed"));
4077 						sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4078 						plci_remove(plci);
4079 						plci->State = IDLE;
4080 						break;
4081 					}
4082 					sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4083 					sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "sss", "", "", "");
4084 					plci->State = INC_ACT_PENDING;
4085 				}
4086 				break;
4087 
4088 			case _CONNECT_I | RESPONSE:
4089 				if (plci->State != INC_DIS_PENDING)
4090 					plci->State = INC_CON_ACCEPT;
4091 				break;
4092 
4093 			case _DISCONNECT_R:
4094 				if (plci->State == INC_DIS_PENDING)
4095 					break;
4096 				if (plci->Sig.Id != 0xff)
4097 				{
4098 					plci->State = OUTG_DIS_PENDING;
4099 					sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
4100 				}
4101 				break;
4102 
4103 			case SUSPEND_REQ:
4104 				break;
4105 
4106 			case RESUME_REQ:
4107 				break;
4108 
4109 			case _CONNECT_B3_R:
4110 				if (rc != OK)
4111 				{
4112 					sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
4113 					break;
4114 				}
4115 				ncci = get_ncci(plci, ch, 0);
4116 				Id = (Id & 0xffff) | (((dword) ncci) << 16);
4117 				plci->channels++;
4118 				if (req == N_RESET)
4119 				{
4120 					a->ncci_state[ncci] = INC_ACT_PENDING;
4121 					sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4122 					sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
4123 				}
4124 				else
4125 				{
4126 					a->ncci_state[ncci] = OUTG_CON_PENDING;
4127 					sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4128 				}
4129 				break;
4130 
4131 			case _CONNECT_B3_I | RESPONSE:
4132 				break;
4133 
4134 			case _RESET_B3_R:
4135 /*        sendf(appl, _RESET_B3_R | CONFIRM, Id, Number, "w", 0);*/
4136 				break;
4137 
4138 			case _DISCONNECT_B3_R:
4139 				sendf(appl, _DISCONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4140 				break;
4141 
4142 			case _MANUFACTURER_R:
4143 				break;
4144 
4145 			case PERM_LIST_REQ:
4146 				if (rc != OK)
4147 				{
4148 					Info = _WRONG_IDENTIFIER;
4149 					sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4150 					plci_remove(plci);
4151 				}
4152 				else
4153 					sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4154 				break;
4155 
4156 			default:
4157 				break;
4158 			}
4159 			plci->command = 0;
4160 		}
4161 		else if (plci->internal_command)
4162 		{
4163 			switch (plci->internal_command)
4164 			{
4165 			case BLOCK_PLCI:
4166 				return;
4167 
4168 			case GET_MWI_STATE:
4169 				if (rc == OK) /* command supported, wait for indication */
4170 				{
4171 					return;
4172 				}
4173 				plci_remove(plci);
4174 				break;
4175 
4176 				/* Get Supported Services */
4177 			case GETSERV_REQ_PEND:
4178 				if (rc == OK) /* command supported, wait for indication */
4179 				{
4180 					break;
4181 				}
4182 				PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4183 				sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", 0, 3, SSstruct);
4184 				plci_remove(plci);
4185 				break;
4186 
4187 			case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
4188 			case INTERR_NUMBERS_REQ_PEND:
4189 			case CF_START_PEND:                  /* Call Forwarding Start pending */
4190 			case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
4191 			case CCBS_REQUEST_REQ_PEND:
4192 			case CCBS_DEACTIVATE_REQ_PEND:
4193 			case CCBS_INTERROGATE_REQ_PEND:
4194 				switch (plci->internal_command)
4195 				{
4196 				case INTERR_DIVERSION_REQ_PEND:
4197 					SSparms[1] = S_INTERROGATE_DIVERSION;
4198 					break;
4199 				case INTERR_NUMBERS_REQ_PEND:
4200 					SSparms[1] = S_INTERROGATE_NUMBERS;
4201 					break;
4202 				case CF_START_PEND:
4203 					SSparms[1] = S_CALL_FORWARDING_START;
4204 					break;
4205 				case CF_STOP_PEND:
4206 					SSparms[1] = S_CALL_FORWARDING_STOP;
4207 					break;
4208 				case CCBS_REQUEST_REQ_PEND:
4209 					SSparms[1] = S_CCBS_REQUEST;
4210 					break;
4211 				case CCBS_DEACTIVATE_REQ_PEND:
4212 					SSparms[1] = S_CCBS_DEACTIVATE;
4213 					break;
4214 				case CCBS_INTERROGATE_REQ_PEND:
4215 					SSparms[1] = S_CCBS_INTERROGATE;
4216 					break;
4217 				}
4218 				if (global_req == ASSIGN)
4219 				{
4220 					dbug(1, dprintf("AssignDiversion_RC=0x%x/0x%x", req, rc));
4221 					return;
4222 				}
4223 				if (!plci->appl) break;
4224 				if (rc == ISDN_GUARD_REJ)
4225 				{
4226 					Info = _CAPI_GUARD_ERROR;
4227 				}
4228 				else if (rc != OK)
4229 				{
4230 					Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4231 				}
4232 				sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7,
4233 				      plci->number, "wws", Info, (word)3, SSparms);
4234 				if (Info) plci_remove(plci);
4235 				break;
4236 
4237 				/* 3pty conference pending */
4238 			case PTY_REQ_PEND:
4239 				if (!plci->relatedPTYPLCI) break;
4240 				rplci = plci->relatedPTYPLCI;
4241 				SSparms[1] = plci->ptyState;
4242 				rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4243 				if (rplci->tel) rId |= EXT_CONTROLLER;
4244 				if (rc != OK)
4245 				{
4246 					Info = 0x300E; /* not supported */
4247 					plci->relatedPTYPLCI = NULL;
4248 					plci->ptyState = 0;
4249 				}
4250 				sendf(rplci->appl,
4251 				      _FACILITY_R | CONFIRM,
4252 				      rId,
4253 				      plci->number,
4254 				      "wws", Info, (word)3, SSparms);
4255 				break;
4256 
4257 				/* Explicit Call Transfer pending */
4258 			case ECT_REQ_PEND:
4259 				dbug(1, dprintf("ECT_RC=0x%x/0x%x", req, rc));
4260 				if (!plci->relatedPTYPLCI) break;
4261 				rplci = plci->relatedPTYPLCI;
4262 				SSparms[1] = S_ECT;
4263 				rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4264 				if (rplci->tel) rId |= EXT_CONTROLLER;
4265 				if (rc != OK)
4266 				{
4267 					Info = 0x300E; /* not supported */
4268 					plci->relatedPTYPLCI = NULL;
4269 					plci->ptyState = 0;
4270 				}
4271 				sendf(rplci->appl,
4272 				      _FACILITY_R | CONFIRM,
4273 				      rId,
4274 				      plci->number,
4275 				      "wws", Info, (word)3, SSparms);
4276 				break;
4277 
4278 			case _MANUFACTURER_R:
4279 				dbug(1, dprintf("_Manufacturer_R=0x%x/0x%x", req, rc));
4280 				if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4281 				{
4282 					dbug(1, dprintf("No more IDs"));
4283 					sendf(appl, _MANUFACTURER_R | CONFIRM, Id, Number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
4284 					plci_remove(plci);  /* after codec init, internal codec commands pending */
4285 				}
4286 				break;
4287 
4288 			case _CONNECT_R:
4289 				dbug(1, dprintf("_Connect_R=0x%x/0x%x", req, rc));
4290 				if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4291 				{
4292 					dbug(1, dprintf("No more IDs"));
4293 					sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4294 					plci_remove(plci);  /* after codec init, internal codec commands pending */
4295 				}
4296 				break;
4297 
4298 			case PERM_COD_HOOK:                     /* finished with Hook_Ind */
4299 				return;
4300 
4301 			case PERM_COD_CALL:
4302 				dbug(1, dprintf("***Codec Connect_Pending A, Rc = 0x%x", rc));
4303 				plci->internal_command = PERM_COD_CONN_PEND;
4304 				return;
4305 
4306 			case PERM_COD_ASSIGN:
4307 				dbug(1, dprintf("***Codec Assign A, Rc = 0x%x", rc));
4308 				if (rc != ASSIGN_OK) break;
4309 				sig_req(plci, CALL_REQ, 0);
4310 				send_req(plci);
4311 				plci->internal_command = PERM_COD_CALL;
4312 				return;
4313 
4314 				/* Null Call Reference Request pending */
4315 			case C_NCR_FAC_REQ:
4316 				dbug(1, dprintf("NCR_FAC=0x%x/0x%x", req, rc));
4317 				if (global_req == ASSIGN)
4318 				{
4319 					if (rc == ASSIGN_OK)
4320 					{
4321 						return;
4322 					}
4323 					else
4324 					{
4325 						sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4326 						appl->NullCREnable = false;
4327 						plci_remove(plci);
4328 					}
4329 				}
4330 				else if (req == NCR_FACILITY)
4331 				{
4332 					if (rc == OK)
4333 					{
4334 						sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", 0);
4335 					}
4336 					else
4337 					{
4338 						sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4339 						appl->NullCREnable = false;
4340 					}
4341 					plci_remove(plci);
4342 				}
4343 				break;
4344 
4345 			case HOOK_ON_REQ:
4346 				if (plci->channels)
4347 				{
4348 					if (a->ncci_state[ncci] == CONNECTED)
4349 					{
4350 						a->ncci_state[ncci] = OUTG_DIS_PENDING;
4351 						cleanup_ncci_data(plci, ncci);
4352 						nl_req_ncci(plci, N_DISC, (byte)ncci);
4353 					}
4354 					break;
4355 				}
4356 				break;
4357 
4358 			case HOOK_OFF_REQ:
4359 				if (plci->State == INC_DIS_PENDING)
4360 					break;
4361 				sig_req(plci, CALL_REQ, 0);
4362 				send_req(plci);
4363 				plci->State = OUTG_CON_PENDING;
4364 				break;
4365 
4366 
4367 			case MWI_ACTIVATE_REQ_PEND:
4368 			case MWI_DEACTIVATE_REQ_PEND:
4369 				if (global_req == ASSIGN && rc == ASSIGN_OK)
4370 				{
4371 					dbug(1, dprintf("MWI_REQ assigned"));
4372 					return;
4373 				}
4374 				else if (rc != OK)
4375 				{
4376 					if (rc == WRONG_IE)
4377 					{
4378 						Info = 0x2007; /* Illegal message parameter coding */
4379 						dbug(1, dprintf("MWI_REQ invalid parameter"));
4380 					}
4381 					else
4382 					{
4383 						Info = 0x300B; /* not supported */
4384 						dbug(1, dprintf("MWI_REQ not supported"));
4385 					}
4386 					/* 0x3010: Request not allowed in this state */
4387 					PUT_WORD(&SSparms[4], 0x300E); /* SS not supported */
4388 
4389 				}
4390 				if (plci->internal_command == MWI_ACTIVATE_REQ_PEND)
4391 				{
4392 					PUT_WORD(&SSparms[1], S_MWI_ACTIVATE);
4393 				}
4394 				else PUT_WORD(&SSparms[1], S_MWI_DEACTIVATE);
4395 
4396 				if (plci->cr_enquiry)
4397 				{
4398 					sendf(plci->appl,
4399 					      _FACILITY_R | CONFIRM,
4400 					      Id & 0xf,
4401 					      plci->number,
4402 					      "wws", Info, (word)3, SSparms);
4403 					if (rc != OK) plci_remove(plci);
4404 				}
4405 				else
4406 				{
4407 					sendf(plci->appl,
4408 					      _FACILITY_R | CONFIRM,
4409 					      Id,
4410 					      plci->number,
4411 					      "wws", Info, (word)3, SSparms);
4412 				}
4413 				break;
4414 
4415 			case CONF_BEGIN_REQ_PEND:
4416 			case CONF_ADD_REQ_PEND:
4417 			case CONF_SPLIT_REQ_PEND:
4418 			case CONF_DROP_REQ_PEND:
4419 			case CONF_ISOLATE_REQ_PEND:
4420 			case CONF_REATTACH_REQ_PEND:
4421 				dbug(1, dprintf("CONF_RC=0x%x/0x%x", req, rc));
4422 				if ((plci->internal_command == CONF_ADD_REQ_PEND) && (!plci->relatedPTYPLCI)) break;
4423 				rplci = plci;
4424 				rId = Id;
4425 				switch (plci->internal_command)
4426 				{
4427 				case CONF_BEGIN_REQ_PEND:
4428 					SSparms[1] = S_CONF_BEGIN;
4429 					break;
4430 				case CONF_ADD_REQ_PEND:
4431 					SSparms[1] = S_CONF_ADD;
4432 					rplci = plci->relatedPTYPLCI;
4433 					rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4434 					break;
4435 				case CONF_SPLIT_REQ_PEND:
4436 					SSparms[1] = S_CONF_SPLIT;
4437 					break;
4438 				case CONF_DROP_REQ_PEND:
4439 					SSparms[1] = S_CONF_DROP;
4440 					break;
4441 				case CONF_ISOLATE_REQ_PEND:
4442 					SSparms[1] = S_CONF_ISOLATE;
4443 					break;
4444 				case CONF_REATTACH_REQ_PEND:
4445 					SSparms[1] = S_CONF_REATTACH;
4446 					break;
4447 				}
4448 
4449 				if (rc != OK)
4450 				{
4451 					Info = 0x300E; /* not supported */
4452 					plci->relatedPTYPLCI = NULL;
4453 					plci->ptyState = 0;
4454 				}
4455 				sendf(rplci->appl,
4456 				      _FACILITY_R | CONFIRM,
4457 				      rId,
4458 				      plci->number,
4459 				      "wws", Info, (word)3, SSparms);
4460 				break;
4461 
4462 			case VSWITCH_REQ_PEND:
4463 				if (rc != OK)
4464 				{
4465 					if (plci->relatedPTYPLCI)
4466 					{
4467 						plci->relatedPTYPLCI->vswitchstate = 0;
4468 						plci->relatedPTYPLCI->vsprot = 0;
4469 						plci->relatedPTYPLCI->vsprotdialect = 0;
4470 					}
4471 					plci->vswitchstate = 0;
4472 					plci->vsprot = 0;
4473 					plci->vsprotdialect = 0;
4474 				}
4475 				else
4476 				{
4477 					if (plci->relatedPTYPLCI &&
4478 					    plci->vswitchstate == 1 &&
4479 					    plci->relatedPTYPLCI->vswitchstate == 3) /* join complete */
4480 						plci->vswitchstate = 3;
4481 				}
4482 				break;
4483 
4484 				/* Call Deflection Request pending (SSCT) */
4485 			case CD_REQ_PEND:
4486 				SSparms[1] = S_CALL_DEFLECTION;
4487 				if (rc != OK)
4488 				{
4489 					Info = 0x300E; /* not supported */
4490 					plci->appl->CDEnable = 0;
4491 				}
4492 				sendf(plci->appl, _FACILITY_R | CONFIRM, Id,
4493 				      plci->number, "wws", Info, (word)3, SSparms);
4494 				break;
4495 
4496 			case RTP_CONNECT_B3_REQ_COMMAND_2:
4497 				if (rc == OK)
4498 				{
4499 					ncci = get_ncci(plci, ch, 0);
4500 					Id = (Id & 0xffff) | (((dword) ncci) << 16);
4501 					plci->channels++;
4502 					a->ncci_state[ncci] = OUTG_CON_PENDING;
4503 				}
4504 				/* fall through */
4505 
4506 			default:
4507 				if (plci->internal_command_queue[0])
4508 				{
4509 					(*(plci->internal_command_queue[0]))(Id, plci, rc);
4510 					if (plci->internal_command)
4511 						return;
4512 				}
4513 				break;
4514 			}
4515 			next_internal_command(Id, plci);
4516 		}
4517 	}
4518 	else /* appl==0 */
4519 	{
4520 		Id = ((word)plci->Id << 8) | plci->adapter->Id;
4521 		if (plci->tel) Id |= EXT_CONTROLLER;
4522 
4523 		switch (plci->internal_command)
4524 		{
4525 		case BLOCK_PLCI:
4526 			return;
4527 
4528 		case START_L1_SIG_ASSIGN_PEND:
4529 		case REM_L1_SIG_ASSIGN_PEND:
4530 			if (global_req == ASSIGN)
4531 			{
4532 				break;
4533 			}
4534 			else
4535 			{
4536 				dbug(1, dprintf("***L1 Req rem PLCI"));
4537 				plci->internal_command = 0;
4538 				sig_req(plci, REMOVE, 0);
4539 				send_req(plci);
4540 			}
4541 			break;
4542 
4543 			/* Call Deflection Request pending, just no appl ptr assigned */
4544 		case CD_REQ_PEND:
4545 			SSparms[1] = S_CALL_DEFLECTION;
4546 			if (rc != OK)
4547 			{
4548 				Info = 0x300E; /* not supported */
4549 			}
4550 			for (i = 0; i < max_appl; i++)
4551 			{
4552 				if (application[i].CDEnable)
4553 				{
4554 					if (!application[i].Id) application[i].CDEnable = 0;
4555 					else
4556 					{
4557 						sendf(&application[i], _FACILITY_R | CONFIRM, Id,
4558 						      plci->number, "wws", Info, (word)3, SSparms);
4559 						if (Info) application[i].CDEnable = 0;
4560 					}
4561 				}
4562 			}
4563 			plci->internal_command = 0;
4564 			break;
4565 
4566 		case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4567 			return;
4568 
4569 		case PERM_COD_CALL:
4570 			plci->internal_command = PERM_COD_CONN_PEND;
4571 			dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc));
4572 			return;
4573 
4574 		case PERM_COD_ASSIGN:
4575 			dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc));
4576 			plci->internal_command = 0;
4577 			if (rc != ASSIGN_OK) break;
4578 			plci->internal_command = PERM_COD_CALL;
4579 			sig_req(plci, CALL_REQ, 0);
4580 			send_req(plci);
4581 			return;
4582 
4583 		case LISTEN_SIG_ASSIGN_PEND:
4584 			if (rc == ASSIGN_OK)
4585 			{
4586 				plci->internal_command = 0;
4587 				dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci->Sig.Id));
4588 				add_p(plci, ESC, "\x02\x18\x00");             /* support call waiting */
4589 				sig_req(plci, INDICATE_REQ, 0);
4590 				send_req(plci);
4591 			}
4592 			else
4593 			{
4594 				dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc));
4595 				a->listen_active--;
4596 				plci_remove(plci);
4597 				plci->State = IDLE;
4598 			}
4599 			break;
4600 
4601 		case USELAW_REQ:
4602 			if (global_req == ASSIGN)
4603 			{
4604 				if (rc == ASSIGN_OK)
4605 				{
4606 					sig_req(plci, LAW_REQ, 0);
4607 					send_req(plci);
4608 					dbug(1, dprintf("Auto-Law assigned"));
4609 				}
4610 				else
4611 				{
4612 					dbug(1, dprintf("Auto-Law assign failed"));
4613 					a->automatic_law = 3;
4614 					plci->internal_command = 0;
4615 					a->automatic_lawPLCI = NULL;
4616 				}
4617 				break;
4618 			}
4619 			else if (req == LAW_REQ && rc == OK)
4620 			{
4621 				dbug(1, dprintf("Auto-Law initiated"));
4622 				a->automatic_law = 2;
4623 				plci->internal_command = 0;
4624 			}
4625 			else
4626 			{
4627 				dbug(1, dprintf("Auto-Law not supported"));
4628 				a->automatic_law = 3;
4629 				plci->internal_command = 0;
4630 				sig_req(plci, REMOVE, 0);
4631 				send_req(plci);
4632 				a->automatic_lawPLCI = NULL;
4633 			}
4634 			break;
4635 		}
4636 		plci_remove_check(plci);
4637 	}
4638 }
4639 
data_rc(PLCI * plci,byte ch)4640 static void data_rc(PLCI *plci, byte ch)
4641 {
4642 	dword Id;
4643 	DIVA_CAPI_ADAPTER *a;
4644 	NCCI *ncci_ptr;
4645 	DATA_B3_DESC *data;
4646 	word ncci;
4647 
4648 	if (plci->appl)
4649 	{
4650 		TransmitBufferFree(plci->appl, plci->data_sent_ptr);
4651 		a = plci->adapter;
4652 		ncci = a->ch_ncci[ch];
4653 		if (ncci && (a->ncci_plci[ncci] == plci->Id))
4654 		{
4655 			ncci_ptr = &(a->ncci[ncci]);
4656 			dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr->data_out, ncci_ptr->data_pending));
4657 			if (ncci_ptr->data_pending)
4658 			{
4659 				data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4660 				if (!(data->Flags & 4) && a->ncci_state[ncci])
4661 				{
4662 					Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4663 					if (plci->tel) Id |= EXT_CONTROLLER;
4664 					sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, data->Number,
4665 					      "ww", data->Handle, 0);
4666 				}
4667 				(ncci_ptr->data_out)++;
4668 				if (ncci_ptr->data_out == MAX_DATA_B3)
4669 					ncci_ptr->data_out = 0;
4670 				(ncci_ptr->data_pending)--;
4671 			}
4672 		}
4673 	}
4674 }
4675 
data_ack(PLCI * plci,byte ch)4676 static void data_ack(PLCI *plci, byte ch)
4677 {
4678 	dword Id;
4679 	DIVA_CAPI_ADAPTER *a;
4680 	NCCI *ncci_ptr;
4681 	word ncci;
4682 
4683 	a = plci->adapter;
4684 	ncci = a->ch_ncci[ch];
4685 	ncci_ptr = &(a->ncci[ncci]);
4686 	if (ncci_ptr->data_ack_pending)
4687 	{
4688 		if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4689 		{
4690 			Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4691 			if (plci->tel) Id |= EXT_CONTROLLER;
4692 			sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4693 			      "ww", ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle, 0);
4694 		}
4695 		(ncci_ptr->data_ack_out)++;
4696 		if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4697 			ncci_ptr->data_ack_out = 0;
4698 		(ncci_ptr->data_ack_pending)--;
4699 	}
4700 }
4701 
sig_ind(PLCI * plci)4702 static void sig_ind(PLCI *plci)
4703 {
4704 	dword x_Id;
4705 	dword Id;
4706 	dword rId;
4707 	word i;
4708 	word cip;
4709 	dword cip_mask;
4710 	byte *ie;
4711 	DIVA_CAPI_ADAPTER *a;
4712 	API_PARSE saved_parms[MAX_MSG_PARMS + 1];
4713 #define MAXPARMSIDS 31
4714 	byte *parms[MAXPARMSIDS];
4715 	byte *add_i[4];
4716 	byte *multi_fac_parms[MAX_MULTI_IE];
4717 	byte *multi_pi_parms[MAX_MULTI_IE];
4718 	byte *multi_ssext_parms[MAX_MULTI_IE];
4719 	byte *multi_CiPN_parms[MAX_MULTI_IE];
4720 
4721 	byte *multi_vswitch_parms[MAX_MULTI_IE];
4722 
4723 	byte ai_len;
4724 	byte *esc_chi = "";
4725 	byte *esc_law = "";
4726 	byte *pty_cai = "";
4727 	byte *esc_cr  = "";
4728 	byte *esc_profile = "";
4729 
4730 	byte facility[256];
4731 	PLCI *tplci = NULL;
4732 	byte chi[] = "\x02\x18\x01";
4733 	byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4734 	byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4735 	/* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4736 	/* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4737 	/* SMSG is situated at the end because its 0 (for compatibility reasons */
4738 	/* (see Info_Mask Bit 4, first IE. then the message type)           */
4739 	static const word parms_id[] =
4740 		{MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4741 		 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4742 		 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4743 		 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4744 	/* 14 FTY repl by ESC_CHI */
4745 	/* 18 PI  repl by ESC_LAW */
4746 	/* removed OAD changed to 0xff for future use, OAD is multiIE now */
4747 	static const word multi_fac_id[] = {1, FTY};
4748 	static const word multi_pi_id[]  = {1, PI};
4749 	static const word multi_CiPN_id[]  = {1, OAD};
4750 	static const word multi_ssext_id[]  = {1, ESC_SSEXT};
4751 
4752 	static const word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4753 
4754 	byte *cau;
4755 	word ncci;
4756 	byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4757 	byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4758 	byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4759 	byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\x00\x00\x00\x00";
4760 	byte force_mt_info = false;
4761 	byte dir;
4762 	dword d;
4763 	word w;
4764 
4765 	a = plci->adapter;
4766 	Id = ((word)plci->Id << 8) | a->Id;
4767 	PUT_WORD(&SS_Ind[4], 0x0000);
4768 
4769 	if (plci->sig_remove_id)
4770 	{
4771 		plci->Sig.RNR = 2; /* discard */
4772 		dbug(1, dprintf("SIG discard while remove pending"));
4773 		return;
4774 	}
4775 	if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4776 	dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4777 			Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4778 	if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4779 	{
4780 		plci->Sig.RNR = 1;
4781 		return;
4782 	}
4783 	if (plci->Sig.Ind == HANGUP && plci->channels)
4784 	{
4785 		plci->Sig.RNR = 1;
4786 		plci->hangup_flow_ctrl_timer++;
4787 		/* recover the network layer after timeout */
4788 		if (plci->hangup_flow_ctrl_timer == 100)
4789 		{
4790 			dbug(1, dprintf("Exceptional disc"));
4791 			plci->Sig.RNR = 0;
4792 			plci->hangup_flow_ctrl_timer = 0;
4793 			for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4794 			{
4795 				if (a->ncci_plci[ncci] == plci->Id)
4796 				{
4797 					cleanup_ncci_data(plci, ncci);
4798 					if (plci->channels)plci->channels--;
4799 					if (plci->appl)
4800 						sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4801 				}
4802 			}
4803 			if (plci->appl)
4804 				sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4805 			plci_remove(plci);
4806 			plci->State = IDLE;
4807 		}
4808 		return;
4809 	}
4810 
4811 	/* do first parse the info with no OAD in, because OAD will be converted */
4812 	/* first the multiple facility IE, then mult. progress ind.              */
4813 	/* then the parameters for the info_ind + conn_ind                       */
4814 	IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4815 	IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4816 	IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4817 
4818 	IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4819 
4820 	IndParse(plci, parms_id, parms, 0);
4821 	IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4822 	esc_chi  = parms[14];
4823 	esc_law  = parms[18];
4824 	pty_cai  = parms[24];
4825 	esc_cr   = parms[25];
4826 	esc_profile = parms[27];
4827 	if (esc_cr[0] && plci)
4828 	{
4829 		if (plci->cr_enquiry && plci->appl)
4830 		{
4831 			plci->cr_enquiry = false;
4832 			/* d = MANU_ID            */
4833 			/* w = m_command          */
4834 			/* b = total length       */
4835 			/* b = indication type    */
4836 			/* b = length of all IEs  */
4837 			/* b = IE1                */
4838 			/* S = IE1 length + cont. */
4839 			/* b = IE2                */
4840 			/* S = IE2 length + cont. */
4841 			sendf(plci->appl,
4842 			      _MANUFACTURER_I,
4843 			      Id,
4844 			      0,
4845 			      "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4846 			      2 + 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], plci->Sig.Ind, 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], ESC, esc_cr, ESC, esc_law);
4847 		}
4848 	}
4849 	/* create the additional info structure                                  */
4850 	add_i[1] = parms[15]; /* KEY of additional info */
4851 	add_i[2] = parms[11]; /* UUI of additional info */
4852 	ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4853 
4854 	/* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4855 	/* indication returns by the card if requested by the function           */
4856 	/* AutomaticLaw() after driver init                                      */
4857 	if (a->automatic_law < 4)
4858 	{
4859 		if (esc_law[0]) {
4860 			if (esc_law[2]) {
4861 				dbug(0, dprintf("u-Law selected"));
4862 				a->u_law = 1;
4863 			}
4864 			else {
4865 				dbug(0, dprintf("a-Law selected"));
4866 				a->u_law = 0;
4867 			}
4868 			a->automatic_law = 4;
4869 			if (plci == a->automatic_lawPLCI) {
4870 				plci->internal_command = 0;
4871 				sig_req(plci, REMOVE, 0);
4872 				send_req(plci);
4873 				a->automatic_lawPLCI = NULL;
4874 			}
4875 		}
4876 		if (esc_profile[0])
4877 		{
4878 			dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4879 					UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
4880 					GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
4881 					GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
4882 
4883 			a->profile.Global_Options &= 0x000000ffL;
4884 			a->profile.B1_Protocols &= 0x000003ffL;
4885 			a->profile.B2_Protocols &= 0x00001fdfL;
4886 			a->profile.B3_Protocols &= 0x000000b7L;
4887 
4888 			a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
4889 				GL_BCHANNEL_OPERATION_SUPPORTED;
4890 			a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
4891 			a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
4892 			a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
4893 			a->manufacturer_features = GET_DWORD(&esc_profile[46]);
4894 			a->man_profile.private_options = 0;
4895 
4896 			if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
4897 			{
4898 				a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
4899 				a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
4900 			}
4901 
4902 
4903 			if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
4904 				a->man_profile.private_options |= 1L << PRIVATE_RTP;
4905 			a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
4906 			a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
4907 
4908 
4909 			if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
4910 				a->man_profile.private_options |= 1L << PRIVATE_T38;
4911 
4912 
4913 			if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
4914 				a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
4915 
4916 
4917 			if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
4918 				a->man_profile.private_options |= 1L << PRIVATE_V18;
4919 
4920 
4921 			if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
4922 				a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
4923 
4924 
4925 			if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
4926 				a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
4927 
4928 
4929 			if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
4930 				a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
4931 
4932 
4933 			if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
4934 				a->man_profile.private_options |= 1L << PRIVATE_VOWN;
4935 
4936 
4937 			if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
4938 				a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
4939 
4940 		}
4941 		else
4942 		{
4943 			a->profile.Global_Options &= 0x0000007fL;
4944 			a->profile.B1_Protocols &= 0x000003dfL;
4945 			a->profile.B2_Protocols &= 0x00001adfL;
4946 			a->profile.B3_Protocols &= 0x000000b7L;
4947 			a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
4948 		}
4949 		if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
4950 						MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
4951 		{
4952 			a->profile.Global_Options |= GL_DTMF_SUPPORTED;
4953 		}
4954 		a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
4955 		dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
4956 				UnMapController(a->Id), a->profile.Global_Options,
4957 				a->profile.B1_Protocols, a->profile.B2_Protocols,
4958 				a->profile.B3_Protocols, a->manufacturer_features));
4959 	}
4960 	/* codec plci for the handset/hook state support is just an internal id  */
4961 	if (plci != a->AdvCodecPLCI)
4962 	{
4963 		force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
4964 		force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
4965 		SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
4966 		SendInfo(plci, Id, parms, force_mt_info);
4967 
4968 		VSwitchReqInd(plci, Id, multi_vswitch_parms);
4969 
4970 	}
4971 
4972 	/* switch the codec to the b-channel                                     */
4973 	if (esc_chi[0] && plci && !plci->SuppState) {
4974 		plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
4975 		mixer_set_bchannel_id_esc(plci, plci->b_channel);
4976 		dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
4977 		if (plci->tel == ADV_VOICE && plci->appl) {
4978 			SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
4979 		}
4980 	}
4981 
4982 	if (plci->appl) plci->appl->Number++;
4983 
4984 	switch (plci->Sig.Ind) {
4985 		/* Response to Get_Supported_Services request */
4986 	case S_SUPPORTED:
4987 		dbug(1, dprintf("S_Supported"));
4988 		if (!plci->appl) break;
4989 		if (pty_cai[0] == 4)
4990 		{
4991 			PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
4992 		}
4993 		else
4994 		{
4995 			PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
4996 		}
4997 		PUT_WORD(&CF_Ind[1], 0);
4998 		PUT_WORD(&CF_Ind[4], 0);
4999 		sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
5000 		plci_remove(plci);
5001 		break;
5002 
5003 		/* Supplementary Service rejected */
5004 	case S_SERVICE_REJ:
5005 		dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5006 		if (!pty_cai[0]) break;
5007 		switch (pty_cai[5])
5008 		{
5009 		case ECT_EXECUTE:
5010 		case THREE_PTY_END:
5011 		case THREE_PTY_BEGIN:
5012 			if (!plci->relatedPTYPLCI) break;
5013 			tplci = plci->relatedPTYPLCI;
5014 			rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5015 			if (tplci->tel) rId |= EXT_CONTROLLER;
5016 			if (pty_cai[5] == ECT_EXECUTE)
5017 			{
5018 				PUT_WORD(&SS_Ind[1], S_ECT);
5019 
5020 				plci->vswitchstate = 0;
5021 				plci->relatedPTYPLCI->vswitchstate = 0;
5022 
5023 			}
5024 			else
5025 			{
5026 				PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5027 			}
5028 			if (pty_cai[2] != 0xff)
5029 			{
5030 				PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5031 			}
5032 			else
5033 			{
5034 				PUT_WORD(&SS_Ind[4], 0x300E);
5035 			}
5036 			plci->relatedPTYPLCI = NULL;
5037 			plci->ptyState = 0;
5038 			sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5039 			break;
5040 
5041 		case CALL_DEFLECTION:
5042 			if (pty_cai[2] != 0xff)
5043 			{
5044 				PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5045 			}
5046 			else
5047 			{
5048 				PUT_WORD(&SS_Ind[4], 0x300E);
5049 			}
5050 			PUT_WORD(&SS_Ind[1], pty_cai[5]);
5051 			for (i = 0; i < max_appl; i++)
5052 			{
5053 				if (application[i].CDEnable)
5054 				{
5055 					if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5056 					application[i].CDEnable = false;
5057 				}
5058 			}
5059 			break;
5060 
5061 		case DEACTIVATION_DIVERSION:
5062 		case ACTIVATION_DIVERSION:
5063 		case DIVERSION_INTERROGATE_CFU:
5064 		case DIVERSION_INTERROGATE_CFB:
5065 		case DIVERSION_INTERROGATE_CFNR:
5066 		case DIVERSION_INTERROGATE_NUM:
5067 		case CCBS_REQUEST:
5068 		case CCBS_DEACTIVATE:
5069 		case CCBS_INTERROGATE:
5070 			if (!plci->appl) break;
5071 			if (pty_cai[2] != 0xff)
5072 			{
5073 				PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5074 			}
5075 			else
5076 			{
5077 				PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5078 			}
5079 			switch (pty_cai[5])
5080 			{
5081 			case DEACTIVATION_DIVERSION:
5082 				dbug(1, dprintf("Deact_Div"));
5083 				Interr_Err_Ind[0] = 0x9;
5084 				Interr_Err_Ind[3] = 0x6;
5085 				PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5086 				break;
5087 			case ACTIVATION_DIVERSION:
5088 				dbug(1, dprintf("Act_Div"));
5089 				Interr_Err_Ind[0] = 0x9;
5090 				Interr_Err_Ind[3] = 0x6;
5091 				PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5092 				break;
5093 			case DIVERSION_INTERROGATE_CFU:
5094 			case DIVERSION_INTERROGATE_CFB:
5095 			case DIVERSION_INTERROGATE_CFNR:
5096 				dbug(1, dprintf("Interr_Div"));
5097 				Interr_Err_Ind[0] = 0xa;
5098 				Interr_Err_Ind[3] = 0x7;
5099 				PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5100 				break;
5101 			case DIVERSION_INTERROGATE_NUM:
5102 				dbug(1, dprintf("Interr_Num"));
5103 				Interr_Err_Ind[0] = 0xa;
5104 				Interr_Err_Ind[3] = 0x7;
5105 				PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5106 				break;
5107 			case CCBS_REQUEST:
5108 				dbug(1, dprintf("CCBS Request"));
5109 				Interr_Err_Ind[0] = 0xd;
5110 				Interr_Err_Ind[3] = 0xa;
5111 				PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5112 				break;
5113 			case CCBS_DEACTIVATE:
5114 				dbug(1, dprintf("CCBS Deactivate"));
5115 				Interr_Err_Ind[0] = 0x9;
5116 				Interr_Err_Ind[3] = 0x6;
5117 				PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5118 				break;
5119 			case CCBS_INTERROGATE:
5120 				dbug(1, dprintf("CCBS Interrogate"));
5121 				Interr_Err_Ind[0] = 0xb;
5122 				Interr_Err_Ind[3] = 0x8;
5123 				PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5124 				break;
5125 			}
5126 			PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5127 			sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5128 			plci_remove(plci);
5129 			break;
5130 		case ACTIVATION_MWI:
5131 		case DEACTIVATION_MWI:
5132 			if (pty_cai[5] == ACTIVATION_MWI)
5133 			{
5134 				PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5135 			}
5136 			else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5137 
5138 			if (pty_cai[2] != 0xff)
5139 			{
5140 				PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5141 			}
5142 			else
5143 			{
5144 				PUT_WORD(&SS_Ind[4], 0x300E);
5145 			}
5146 
5147 			if (plci->cr_enquiry)
5148 			{
5149 				sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5150 				plci_remove(plci);
5151 			}
5152 			else
5153 			{
5154 				sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5155 			}
5156 			break;
5157 		case CONF_ADD: /* ERROR */
5158 		case CONF_BEGIN:
5159 		case CONF_DROP:
5160 		case CONF_ISOLATE:
5161 		case CONF_REATTACH:
5162 			CONF_Ind[0] = 9;
5163 			CONF_Ind[3] = 6;
5164 			switch (pty_cai[5])
5165 			{
5166 			case CONF_BEGIN:
5167 				PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5168 				plci->ptyState = 0;
5169 				break;
5170 			case CONF_DROP:
5171 				CONF_Ind[0] = 5;
5172 				CONF_Ind[3] = 2;
5173 				PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5174 				plci->ptyState = CONNECTED;
5175 				break;
5176 			case CONF_ISOLATE:
5177 				CONF_Ind[0] = 5;
5178 				CONF_Ind[3] = 2;
5179 				PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5180 				plci->ptyState = CONNECTED;
5181 				break;
5182 			case CONF_REATTACH:
5183 				CONF_Ind[0] = 5;
5184 				CONF_Ind[3] = 2;
5185 				PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5186 				plci->ptyState = CONNECTED;
5187 				break;
5188 			case CONF_ADD:
5189 				PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5190 				plci->relatedPTYPLCI = NULL;
5191 				tplci = plci->relatedPTYPLCI;
5192 				if (tplci) tplci->ptyState = CONNECTED;
5193 				plci->ptyState = CONNECTED;
5194 				break;
5195 			}
5196 
5197 			if (pty_cai[2] != 0xff)
5198 			{
5199 				PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5200 			}
5201 			else
5202 			{
5203 				PUT_WORD(&CONF_Ind[4], 0x3303); /* Time-out: network did not respond
5204 								  within the required time */
5205 			}
5206 
5207 			PUT_DWORD(&CONF_Ind[6], 0x0);
5208 			sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5209 			break;
5210 		}
5211 		break;
5212 
5213 		/* Supplementary Service indicates success */
5214 	case S_SERVICE:
5215 		dbug(1, dprintf("Service_Ind"));
5216 		PUT_WORD(&CF_Ind[4], 0);
5217 		switch (pty_cai[5])
5218 		{
5219 		case THREE_PTY_END:
5220 		case THREE_PTY_BEGIN:
5221 		case ECT_EXECUTE:
5222 			if (!plci->relatedPTYPLCI) break;
5223 			tplci = plci->relatedPTYPLCI;
5224 			rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5225 			if (tplci->tel) rId |= EXT_CONTROLLER;
5226 			if (pty_cai[5] == ECT_EXECUTE)
5227 			{
5228 				PUT_WORD(&SS_Ind[1], S_ECT);
5229 
5230 				if (plci->vswitchstate != 3)
5231 				{
5232 
5233 					plci->ptyState = IDLE;
5234 					plci->relatedPTYPLCI = NULL;
5235 					plci->ptyState = 0;
5236 
5237 				}
5238 
5239 				dbug(1, dprintf("ECT OK"));
5240 				sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5241 
5242 
5243 
5244 			}
5245 			else
5246 			{
5247 				switch (plci->ptyState)
5248 				{
5249 				case S_3PTY_BEGIN:
5250 					plci->ptyState = CONNECTED;
5251 					dbug(1, dprintf("3PTY ON"));
5252 					break;
5253 
5254 				case S_3PTY_END:
5255 					plci->ptyState = IDLE;
5256 					plci->relatedPTYPLCI = NULL;
5257 					plci->ptyState = 0;
5258 					dbug(1, dprintf("3PTY OFF"));
5259 					break;
5260 				}
5261 				PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5262 				sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5263 			}
5264 			break;
5265 
5266 		case CALL_DEFLECTION:
5267 			PUT_WORD(&SS_Ind[1], pty_cai[5]);
5268 			for (i = 0; i < max_appl; i++)
5269 			{
5270 				if (application[i].CDEnable)
5271 				{
5272 					if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5273 					application[i].CDEnable = false;
5274 				}
5275 			}
5276 			break;
5277 
5278 		case DEACTIVATION_DIVERSION:
5279 		case ACTIVATION_DIVERSION:
5280 			if (!plci->appl) break;
5281 			PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5282 			PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5283 			sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5284 			plci_remove(plci);
5285 			break;
5286 
5287 		case DIVERSION_INTERROGATE_CFU:
5288 		case DIVERSION_INTERROGATE_CFB:
5289 		case DIVERSION_INTERROGATE_CFNR:
5290 		case DIVERSION_INTERROGATE_NUM:
5291 		case CCBS_REQUEST:
5292 		case CCBS_DEACTIVATE:
5293 		case CCBS_INTERROGATE:
5294 			if (!plci->appl) break;
5295 			switch (pty_cai[5])
5296 			{
5297 			case DIVERSION_INTERROGATE_CFU:
5298 			case DIVERSION_INTERROGATE_CFB:
5299 			case DIVERSION_INTERROGATE_CFNR:
5300 				dbug(1, dprintf("Interr_Div"));
5301 				PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5302 				pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5303 				break;
5304 			case DIVERSION_INTERROGATE_NUM:
5305 				dbug(1, dprintf("Interr_Num"));
5306 				PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5307 				pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5308 				break;
5309 			case CCBS_REQUEST:
5310 				dbug(1, dprintf("CCBS Request"));
5311 				PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5312 				pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5313 				break;
5314 			case CCBS_DEACTIVATE:
5315 				dbug(1, dprintf("CCBS Deactivate"));
5316 				PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5317 				pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5318 				break;
5319 			case CCBS_INTERROGATE:
5320 				dbug(1, dprintf("CCBS Interrogate"));
5321 				PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5322 				pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5323 				break;
5324 			}
5325 			PUT_WORD(&pty_cai[4], 0); /* Supplementary Service Reason */
5326 			PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5327 			sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5328 			plci_remove(plci);
5329 			break;
5330 
5331 		case ACTIVATION_MWI:
5332 		case DEACTIVATION_MWI:
5333 			if (pty_cai[5] == ACTIVATION_MWI)
5334 			{
5335 				PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5336 			}
5337 			else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5338 			if (plci->cr_enquiry)
5339 			{
5340 				sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5341 				plci_remove(plci);
5342 			}
5343 			else
5344 			{
5345 				sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5346 			}
5347 			break;
5348 		case MWI_INDICATION:
5349 			if (pty_cai[0] >= 0x12)
5350 			{
5351 				PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5352 				pty_cai[2] = pty_cai[0] - 2; /* len Parameter */
5353 				pty_cai[5] = pty_cai[0] - 5; /* Supplementary Service-specific parameter len */
5354 				if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5355 				{
5356 					if (plci->internal_command == GET_MWI_STATE) /* result on Message Waiting Listen */
5357 					{
5358 						sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5359 						plci_remove(plci);
5360 						return;
5361 					}
5362 					else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5363 					pty_cai[0] = 0;
5364 				}
5365 				else
5366 				{
5367 					for (i = 0; i < max_appl; i++)
5368 					{
5369 						if (a->Notification_Mask[i]&SMASK_MWI)
5370 						{
5371 							sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5372 							pty_cai[0] = 0;
5373 						}
5374 					}
5375 				}
5376 
5377 				if (!pty_cai[0])
5378 				{ /* acknowledge */
5379 					facility[2] = 0; /* returncode */
5380 				}
5381 				else facility[2] = 0xff;
5382 			}
5383 			else
5384 			{
5385 				/* reject */
5386 				facility[2] = 0xff; /* returncode */
5387 			}
5388 			facility[0] = 2;
5389 			facility[1] = MWI_RESPONSE; /* Function */
5390 			add_p(plci, CAI, facility);
5391 			add_p(plci, ESC, multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5392 			sig_req(plci, S_SERVICE, 0);
5393 			send_req(plci);
5394 			plci->command = 0;
5395 			next_internal_command(Id, plci);
5396 			break;
5397 		case CONF_ADD: /* OK */
5398 		case CONF_BEGIN:
5399 		case CONF_DROP:
5400 		case CONF_ISOLATE:
5401 		case CONF_REATTACH:
5402 		case CONF_PARTYDISC:
5403 			CONF_Ind[0] = 9;
5404 			CONF_Ind[3] = 6;
5405 			switch (pty_cai[5])
5406 			{
5407 			case CONF_BEGIN:
5408 				PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5409 				if (pty_cai[0] == 6)
5410 				{
5411 					d = pty_cai[6];
5412 					PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5413 				}
5414 				else
5415 				{
5416 					PUT_DWORD(&CONF_Ind[6], 0x0);
5417 				}
5418 				break;
5419 			case CONF_ISOLATE:
5420 				PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5421 				CONF_Ind[0] = 5;
5422 				CONF_Ind[3] = 2;
5423 				break;
5424 			case CONF_REATTACH:
5425 				PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5426 				CONF_Ind[0] = 5;
5427 				CONF_Ind[3] = 2;
5428 				break;
5429 			case CONF_DROP:
5430 				PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5431 				CONF_Ind[0] = 5;
5432 				CONF_Ind[3] = 2;
5433 				break;
5434 			case CONF_ADD:
5435 				PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5436 				d = pty_cai[6];
5437 				PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5438 				tplci = plci->relatedPTYPLCI;
5439 				if (tplci) tplci->ptyState = CONNECTED;
5440 				break;
5441 			case CONF_PARTYDISC:
5442 				CONF_Ind[0] = 7;
5443 				CONF_Ind[3] = 4;
5444 				PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5445 				d = pty_cai[6];
5446 				PUT_DWORD(&CONF_Ind[4], d); /* PartyID */
5447 				break;
5448 			}
5449 			plci->ptyState = CONNECTED;
5450 			sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5451 			break;
5452 		case CCBS_INFO_RETAIN:
5453 		case CCBS_ERASECALLLINKAGEID:
5454 		case CCBS_STOP_ALERTING:
5455 			CONF_Ind[0] = 5;
5456 			CONF_Ind[3] = 2;
5457 			switch (pty_cai[5])
5458 			{
5459 			case CCBS_INFO_RETAIN:
5460 				PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5461 				break;
5462 			case CCBS_STOP_ALERTING:
5463 				PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5464 				break;
5465 			case CCBS_ERASECALLLINKAGEID:
5466 				PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5467 				CONF_Ind[0] = 7;
5468 				CONF_Ind[3] = 4;
5469 				CONF_Ind[6] = 0;
5470 				CONF_Ind[7] = 0;
5471 				break;
5472 			}
5473 			w = pty_cai[6];
5474 			PUT_WORD(&CONF_Ind[4], w); /* PartyID */
5475 
5476 			if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5477 			{
5478 				sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5479 			}
5480 			else
5481 			{
5482 				for (i = 0; i < max_appl; i++)
5483 					if (a->Notification_Mask[i] & SMASK_CCBS)
5484 						sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5485 			}
5486 			break;
5487 		}
5488 		break;
5489 	case CALL_HOLD_REJ:
5490 		cau = parms[7];
5491 		if (cau)
5492 		{
5493 			i = _L3_CAUSE | cau[2];
5494 			if (cau[2] == 0) i = 0x3603;
5495 		}
5496 		else
5497 		{
5498 			i = 0x3603;
5499 		}
5500 		PUT_WORD(&SS_Ind[1], S_HOLD);
5501 		PUT_WORD(&SS_Ind[4], i);
5502 		if (plci->SuppState == HOLD_REQUEST)
5503 		{
5504 			plci->SuppState = IDLE;
5505 			sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5506 		}
5507 		break;
5508 
5509 	case CALL_HOLD_ACK:
5510 		if (plci->SuppState == HOLD_REQUEST)
5511 		{
5512 			plci->SuppState = CALL_HELD;
5513 			CodecIdCheck(a, plci);
5514 			start_internal_command(Id, plci, hold_save_command);
5515 		}
5516 		break;
5517 
5518 	case CALL_RETRIEVE_REJ:
5519 		cau = parms[7];
5520 		if (cau)
5521 		{
5522 			i = _L3_CAUSE | cau[2];
5523 			if (cau[2] == 0) i = 0x3603;
5524 		}
5525 		else
5526 		{
5527 			i = 0x3603;
5528 		}
5529 		PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5530 		PUT_WORD(&SS_Ind[4], i);
5531 		if (plci->SuppState == RETRIEVE_REQUEST)
5532 		{
5533 			plci->SuppState = CALL_HELD;
5534 			CodecIdCheck(a, plci);
5535 			sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5536 		}
5537 		break;
5538 
5539 	case CALL_RETRIEVE_ACK:
5540 		PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5541 		if (plci->SuppState == RETRIEVE_REQUEST)
5542 		{
5543 			plci->SuppState = IDLE;
5544 			plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5545 			plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5546 			if (plci->tel)
5547 			{
5548 				mixer_set_bchannel_id_esc(plci, plci->b_channel);
5549 				dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5550 				SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5551 				if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5552 				{
5553 					dbug(1, dprintf("Get B-ch"));
5554 					start_internal_command(Id, plci, retrieve_restore_command);
5555 				}
5556 				else
5557 					sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5558 			}
5559 			else
5560 				start_internal_command(Id, plci, retrieve_restore_command);
5561 		}
5562 		break;
5563 
5564 	case INDICATE_IND:
5565 		if (plci->State != LISTENING) {
5566 			sig_req(plci, HANGUP, 0);
5567 			send_req(plci);
5568 			break;
5569 		}
5570 		cip = find_cip(a, parms[4], parms[6]);
5571 		cip_mask = 1L << cip;
5572 		dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5573 		bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5574 		if (!remove_started && !a->adapter_disabled)
5575 		{
5576 			group_optimization(a, plci);
5577 			for_each_set_bit(i, plci->group_optimization_mask_table, max_appl) {
5578 				if (application[i].Id
5579 				    && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5580 				    && CPN_filter_ok(parms[0], a, i)) {
5581 					dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5582 					__set_bit(i, plci->c_ind_mask_table);
5583 					dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
5584 					plci->State = INC_CON_PENDING;
5585 					plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5586 						CALL_DIR_IN | CALL_DIR_ANSWER;
5587 					if (esc_chi[0]) {
5588 						plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5589 						mixer_set_bchannel_id_esc(plci, plci->b_channel);
5590 					}
5591 					/* if a listen on the ext controller is done, check if hook states */
5592 					/* are supported or if just a on board codec must be activated     */
5593 					if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5594 						if (a->profile.Global_Options & HANDSET)
5595 							plci->tel = ADV_VOICE;
5596 						else if (a->profile.Global_Options & ON_BOARD_CODEC)
5597 							plci->tel = CODEC;
5598 						if (plci->tel) Id |= EXT_CONTROLLER;
5599 						a->codec_listen[i] = plci;
5600 					}
5601 
5602 					sendf(&application[i], _CONNECT_I, Id, 0,
5603 					      "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5604 					      parms[0],    /* CalledPartyNumber   */
5605 					      multi_CiPN_parms[0],    /* CallingPartyNumber  */
5606 					      parms[2],    /* CalledPartySubad    */
5607 					      parms[3],    /* CallingPartySubad   */
5608 					      parms[4],    /* BearerCapability    */
5609 					      parms[5],    /* LowLC               */
5610 					      parms[6],    /* HighLC              */
5611 					      ai_len,      /* nested struct add_i */
5612 					      add_i[0],    /* B channel info    */
5613 					      add_i[1],    /* keypad facility   */
5614 					      add_i[2],    /* user user data    */
5615 					      add_i[3],    /* nested facility   */
5616 					      multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5617 						);
5618 					SendSSExtInd(&application[i],
5619 						     plci,
5620 						     Id,
5621 						     multi_ssext_parms);
5622 					SendSetupInfo(&application[i],
5623 						      plci,
5624 						      Id,
5625 						      parms,
5626 						      SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5627 				}
5628 			}
5629 			dbug(1, dprintf("c_ind_mask =%*pb", MAX_APPL, plci->c_ind_mask_table));
5630 		}
5631 		if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL)) {
5632 			sig_req(plci, HANGUP, 0);
5633 			send_req(plci);
5634 			plci->State = IDLE;
5635 		}
5636 		plci->notifiedcall = 0;
5637 		a->listen_active--;
5638 		listen_check(a);
5639 		break;
5640 
5641 	case CALL_PEND_NOTIFY:
5642 		plci->notifiedcall = 1;
5643 		listen_check(a);
5644 		break;
5645 
5646 	case CALL_IND:
5647 	case CALL_CON:
5648 		if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5649 		{
5650 			if (plci->internal_command == PERM_COD_CONN_PEND)
5651 			{
5652 				if (plci->State == ADVANCED_VOICE_NOSIG)
5653 				{
5654 					dbug(1, dprintf("***Codec OK"));
5655 					if (a->AdvSignalPLCI)
5656 					{
5657 						tplci = a->AdvSignalPLCI;
5658 						if (tplci->spoofed_msg)
5659 						{
5660 							dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5661 							tplci->command = 0;
5662 							tplci->internal_command = 0;
5663 							x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5664 							switch (tplci->spoofed_msg)
5665 							{
5666 							case CALL_RES:
5667 								tplci->command = _CONNECT_I | RESPONSE;
5668 								api_load_msg(&tplci->saved_msg, saved_parms);
5669 								add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5670 								if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5671 								{
5672 									/* early B3 connect (CIP mask bit 9) no release after a disc */
5673 									add_p(tplci, LLI, "\x01\x01");
5674 								}
5675 								add_s(tplci, CONN_NR, &saved_parms[2]);
5676 								add_s(tplci, LLC, &saved_parms[4]);
5677 								add_ai(tplci, &saved_parms[5]);
5678 								tplci->State = INC_CON_ACCEPT;
5679 								sig_req(tplci, CALL_RES, 0);
5680 								send_req(tplci);
5681 								break;
5682 
5683 							case AWAITING_SELECT_B:
5684 								dbug(1, dprintf("Select_B continue"));
5685 								start_internal_command(x_Id, tplci, select_b_command);
5686 								break;
5687 
5688 							case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5689 								if (!tplci->Sig.Id)
5690 								{
5691 									dbug(1, dprintf("No SigID!"));
5692 									sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5693 									plci_remove(tplci);
5694 									break;
5695 								}
5696 								tplci->command = _MANUFACTURER_R;
5697 								api_load_msg(&tplci->saved_msg, saved_parms);
5698 								dir = saved_parms[2].info[0];
5699 								if (dir == 1) {
5700 									sig_req(tplci, CALL_REQ, 0);
5701 								}
5702 								else if (!dir) {
5703 									sig_req(tplci, LISTEN_REQ, 0);
5704 								}
5705 								send_req(tplci);
5706 								sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5707 								break;
5708 
5709 							case (CALL_REQ | AWAITING_MANUF_CON):
5710 								sig_req(tplci, CALL_REQ, 0);
5711 								send_req(tplci);
5712 								break;
5713 
5714 							case CALL_REQ:
5715 								if (!tplci->Sig.Id)
5716 								{
5717 									dbug(1, dprintf("No SigID!"));
5718 									sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5719 									plci_remove(tplci);
5720 									break;
5721 								}
5722 								tplci->command = _CONNECT_R;
5723 								api_load_msg(&tplci->saved_msg, saved_parms);
5724 								add_s(tplci, CPN, &saved_parms[1]);
5725 								add_s(tplci, DSA, &saved_parms[3]);
5726 								add_ai(tplci, &saved_parms[9]);
5727 								sig_req(tplci, CALL_REQ, 0);
5728 								send_req(tplci);
5729 								break;
5730 
5731 							case CALL_RETRIEVE:
5732 								tplci->command = C_RETRIEVE_REQ;
5733 								sig_req(tplci, CALL_RETRIEVE, 0);
5734 								send_req(tplci);
5735 								break;
5736 							}
5737 							tplci->spoofed_msg = 0;
5738 							if (tplci->internal_command == 0)
5739 								next_internal_command(x_Id, tplci);
5740 						}
5741 					}
5742 					next_internal_command(Id, plci);
5743 					break;
5744 				}
5745 				dbug(1, dprintf("***Codec Hook Init Req"));
5746 				plci->internal_command = PERM_COD_HOOK;
5747 				add_p(plci, FTY, "\x01\x09");             /* Get Hook State*/
5748 				sig_req(plci, TEL_CTRL, 0);
5749 				send_req(plci);
5750 			}
5751 		}
5752 		else if (plci->command != _MANUFACTURER_R  /* old style permanent connect */
5753 			 && plci->State != INC_ACT_PENDING)
5754 		{
5755 			mixer_set_bchannel_id_esc(plci, plci->b_channel);
5756 			if (plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5757 			{
5758 				chi[2] = plci->b_channel;
5759 				SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5760 			}
5761 			sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5762 			plci->State = INC_ACT_PENDING;
5763 		}
5764 		break;
5765 
5766 	case TEL_CTRL:
5767 		ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5768 		if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5769 			switch (ie[1] & 0x91) {
5770 			case 0x80:   /* hook off */
5771 			case 0x81:
5772 				if (plci->internal_command == PERM_COD_HOOK)
5773 				{
5774 					dbug(1, dprintf("init:hook_off"));
5775 					plci->hook_state = ie[1];
5776 					next_internal_command(Id, plci);
5777 					break;
5778 				}
5779 				else /* ignore doubled hook indications */
5780 				{
5781 					if (((plci->hook_state) & 0xf0) == 0x80)
5782 					{
5783 						dbug(1, dprintf("ignore hook"));
5784 						break;
5785 					}
5786 					plci->hook_state = ie[1]&0x91;
5787 				}
5788 				/* check for incoming call pending */
5789 				/* and signal '+'.Appl must decide */
5790 				/* with connect_res if call must   */
5791 				/* accepted or not                 */
5792 				for (i = 0, tplci = NULL; i < max_appl; i++) {
5793 					if (a->codec_listen[i]
5794 					    && (a->codec_listen[i]->State == INC_CON_PENDING
5795 						|| a->codec_listen[i]->State == INC_CON_ALERT)) {
5796 						tplci = a->codec_listen[i];
5797 						tplci->appl = &application[i];
5798 					}
5799 				}
5800 				/* no incoming call, do outgoing call */
5801 				/* and signal '+' if outg. setup   */
5802 				if (!a->AdvSignalPLCI && !tplci) {
5803 					if ((i = get_plci(a))) {
5804 						a->AdvSignalPLCI = &a->plci[i - 1];
5805 						tplci = a->AdvSignalPLCI;
5806 						tplci->tel  = ADV_VOICE;
5807 						PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5808 						if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5809 							/* early B3 connect (CIP mask bit 9) no release after a disc */
5810 							add_p(tplci, LLI, "\x01\x01");
5811 						}
5812 						add_p(tplci, CAI, voice_cai);
5813 						add_p(tplci, OAD, a->TelOAD);
5814 						add_p(tplci, OSA, a->TelOSA);
5815 						add_p(tplci, SHIFT | 6, NULL);
5816 						add_p(tplci, SIN, "\x02\x01\x00");
5817 						add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5818 						sig_req(tplci, ASSIGN, DSIG_ID);
5819 						a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5820 						a->AdvSignalPLCI->command = 0;
5821 						tplci->appl = a->AdvSignalAppl;
5822 						tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5823 						send_req(tplci);
5824 					}
5825 
5826 				}
5827 
5828 				if (!tplci) break;
5829 				Id = ((word)tplci->Id << 8) | a->Id;
5830 				Id |= EXT_CONTROLLER;
5831 				sendf(tplci->appl,
5832 				      _FACILITY_I,
5833 				      Id,
5834 				      0,
5835 				      "ws", (word)0, "\x01+");
5836 				break;
5837 
5838 			case 0x90:   /* hook on  */
5839 			case 0x91:
5840 				if (plci->internal_command == PERM_COD_HOOK)
5841 				{
5842 					dbug(1, dprintf("init:hook_on"));
5843 					plci->hook_state = ie[1] & 0x91;
5844 					next_internal_command(Id, plci);
5845 					break;
5846 				}
5847 				else /* ignore doubled hook indications */
5848 				{
5849 					if (((plci->hook_state) & 0xf0) == 0x90) break;
5850 					plci->hook_state = ie[1] & 0x91;
5851 				}
5852 				/* hangup the adv. voice call and signal '-' to the appl */
5853 				if (a->AdvSignalPLCI) {
5854 					Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5855 					if (plci->tel) Id |= EXT_CONTROLLER;
5856 					sendf(a->AdvSignalAppl,
5857 					      _FACILITY_I,
5858 					      Id,
5859 					      0,
5860 					      "ws", (word)0, "\x01-");
5861 					a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5862 					a->AdvSignalPLCI->command = 0;
5863 					sig_req(a->AdvSignalPLCI, HANGUP, 0);
5864 					send_req(a->AdvSignalPLCI);
5865 				}
5866 				break;
5867 			}
5868 		}
5869 		break;
5870 
5871 	case RESUME:
5872 		__clear_bit(plci->appl->Id - 1, plci->c_ind_mask_table);
5873 		PUT_WORD(&resume_cau[4], GOOD);
5874 		sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
5875 		break;
5876 
5877 	case SUSPEND:
5878 		bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5879 
5880 		if (plci->NL.Id && !plci->nl_remove_id) {
5881 			mixer_remove(plci);
5882 			nl_req_ncci(plci, REMOVE, 0);
5883 		}
5884 		if (!plci->sig_remove_id) {
5885 			plci->internal_command = 0;
5886 			sig_req(plci, REMOVE, 0);
5887 		}
5888 		send_req(plci);
5889 		if (!plci->channels) {
5890 			sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
5891 			sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
5892 		}
5893 		break;
5894 
5895 	case SUSPEND_REJ:
5896 		break;
5897 
5898 	case HANGUP:
5899 		plci->hangup_flow_ctrl_timer = 0;
5900 		if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
5901 		cau = parms[7];
5902 		if (cau) {
5903 			i = _L3_CAUSE | cau[2];
5904 			if (cau[2] == 0) i = 0;
5905 			else if (cau[2] == 8) i = _L1_ERROR;
5906 			else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
5907 			else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
5908 		}
5909 		else {
5910 			i = _L3_ERROR;
5911 		}
5912 
5913 		if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
5914 		{
5915 			for_each_set_bit(i, plci->c_ind_mask_table, max_appl)
5916 				sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
5917 		}
5918 		else
5919 		{
5920 			bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
5921 		}
5922 		if (!plci->appl)
5923 		{
5924 			if (plci->State == LISTENING)
5925 			{
5926 				plci->notifiedcall = 0;
5927 				a->listen_active--;
5928 			}
5929 			plci->State = INC_DIS_PENDING;
5930 			if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
5931 			{
5932 				plci->State = IDLE;
5933 				if (plci->NL.Id && !plci->nl_remove_id)
5934 				{
5935 					mixer_remove(plci);
5936 					nl_req_ncci(plci, REMOVE, 0);
5937 				}
5938 				if (!plci->sig_remove_id)
5939 				{
5940 					plci->internal_command = 0;
5941 					sig_req(plci, REMOVE, 0);
5942 				}
5943 				send_req(plci);
5944 			}
5945 		}
5946 		else
5947 		{
5948 			/* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
5949 			/* result in a second HANGUP! Don't generate another        */
5950 			/* DISCONNECT                                               */
5951 			if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
5952 			{
5953 				if (plci->State == RESUMING)
5954 				{
5955 					PUT_WORD(&resume_cau[4], i);
5956 					sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
5957 				}
5958 				plci->State = INC_DIS_PENDING;
5959 				sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
5960 			}
5961 		}
5962 		break;
5963 
5964 	case SSEXT_IND:
5965 		SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5966 		break;
5967 
5968 	case VSWITCH_REQ:
5969 		VSwitchReqInd(plci, Id, multi_vswitch_parms);
5970 		break;
5971 	case VSWITCH_IND:
5972 		if (plci->relatedPTYPLCI &&
5973 		    plci->vswitchstate == 3 &&
5974 		    plci->relatedPTYPLCI->vswitchstate == 3 &&
5975 		    parms[MAXPARMSIDS - 1][0])
5976 		{
5977 			add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
5978 			sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
5979 			send_req(plci->relatedPTYPLCI);
5980 		}
5981 		else VSwitchReqInd(plci, Id, multi_vswitch_parms);
5982 		break;
5983 
5984 	}
5985 }
5986 
5987 
SendSetupInfo(APPL * appl,PLCI * plci,dword Id,byte ** parms,byte Info_Sent_Flag)5988 static void SendSetupInfo(APPL *appl, PLCI *plci, dword Id, byte **parms, byte Info_Sent_Flag)
5989 {
5990 	word i;
5991 	byte *ie;
5992 	word Info_Number;
5993 	byte *Info_Element;
5994 	word Info_Mask = 0;
5995 
5996 	dbug(1, dprintf("SetupInfo"));
5997 
5998 	for (i = 0; i < MAXPARMSIDS; i++) {
5999 		ie = parms[i];
6000 		Info_Number = 0;
6001 		Info_Element = ie;
6002 		if (ie[0]) {
6003 			switch (i) {
6004 			case 0:
6005 				dbug(1, dprintf("CPN "));
6006 				Info_Number = 0x0070;
6007 				Info_Mask = 0x80;
6008 				Info_Sent_Flag = true;
6009 				break;
6010 			case 8:  /* display      */
6011 				dbug(1, dprintf("display(%d)", i));
6012 				Info_Number = 0x0028;
6013 				Info_Mask = 0x04;
6014 				Info_Sent_Flag = true;
6015 				break;
6016 			case 16: /* Channel Id */
6017 				dbug(1, dprintf("CHI"));
6018 				Info_Number = 0x0018;
6019 				Info_Mask = 0x100;
6020 				Info_Sent_Flag = true;
6021 				mixer_set_bchannel_id(plci, Info_Element);
6022 				break;
6023 			case 19: /* Redirected Number */
6024 				dbug(1, dprintf("RDN"));
6025 				Info_Number = 0x0074;
6026 				Info_Mask = 0x400;
6027 				Info_Sent_Flag = true;
6028 				break;
6029 			case 20: /* Redirected Number extended */
6030 				dbug(1, dprintf("RDX"));
6031 				Info_Number = 0x0073;
6032 				Info_Mask = 0x400;
6033 				Info_Sent_Flag = true;
6034 				break;
6035 			case 22: /* Redirecing Number  */
6036 				dbug(1, dprintf("RIN"));
6037 				Info_Number = 0x0076;
6038 				Info_Mask = 0x400;
6039 				Info_Sent_Flag = true;
6040 				break;
6041 			default:
6042 				Info_Number = 0;
6043 				break;
6044 			}
6045 		}
6046 
6047 		if (i == MAXPARMSIDS - 2) { /* to indicate the message type "Setup" */
6048 			Info_Number = 0x8000 | 5;
6049 			Info_Mask = 0x10;
6050 			Info_Element = "";
6051 		}
6052 
6053 		if (Info_Sent_Flag && Info_Number) {
6054 			if (plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask) {
6055 				sendf(appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6056 			}
6057 		}
6058 	}
6059 }
6060 
6061 
SendInfo(PLCI * plci,dword Id,byte ** parms,byte iesent)6062 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6063 {
6064 	word i;
6065 	word j;
6066 	word k;
6067 	byte *ie;
6068 	word Info_Number;
6069 	byte *Info_Element;
6070 	word Info_Mask = 0;
6071 	static byte charges[5] = {4, 0, 0, 0, 0};
6072 	static byte cause[] = {0x02, 0x80, 0x00};
6073 	APPL *appl;
6074 
6075 	dbug(1, dprintf("InfoParse "));
6076 
6077 	if (
6078 		!plci->appl
6079 		&& !plci->State
6080 		&& plci->Sig.Ind != NCR_FACILITY
6081 		)
6082 	{
6083 		dbug(1, dprintf("NoParse "));
6084 		return;
6085 	}
6086 	cause[2] = 0;
6087 	for (i = 0; i < MAXPARMSIDS; i++) {
6088 		ie = parms[i];
6089 		Info_Number = 0;
6090 		Info_Element = ie;
6091 		if (ie[0]) {
6092 			switch (i) {
6093 			case 0:
6094 				dbug(1, dprintf("CPN "));
6095 				Info_Number = 0x0070;
6096 				Info_Mask   = 0x80;
6097 				break;
6098 			case 7: /* ESC_CAU */
6099 				dbug(1, dprintf("cau(0x%x)", ie[2]));
6100 				Info_Number = 0x0008;
6101 				Info_Mask = 0x00;
6102 				cause[2] = ie[2];
6103 				Info_Element = NULL;
6104 				break;
6105 			case 8:  /* display      */
6106 				dbug(1, dprintf("display(%d)", i));
6107 				Info_Number = 0x0028;
6108 				Info_Mask = 0x04;
6109 				break;
6110 			case 9:  /* Date display */
6111 				dbug(1, dprintf("date(%d)", i));
6112 				Info_Number = 0x0029;
6113 				Info_Mask = 0x02;
6114 				break;
6115 			case 10: /* charges */
6116 				for (j = 0; j < 4; j++) charges[1 + j] = 0;
6117 				for (j = 0; j < ie[0] && !(ie[1 + j] & 0x80); j++);
6118 				for (k = 1, j++; j < ie[0] && k <= 4; j++, k++) charges[k] = ie[1 + j];
6119 				Info_Number = 0x4000;
6120 				Info_Mask = 0x40;
6121 				Info_Element = charges;
6122 				break;
6123 			case 11: /* user user info */
6124 				dbug(1, dprintf("uui"));
6125 				Info_Number = 0x007E;
6126 				Info_Mask = 0x08;
6127 				break;
6128 			case 12: /* congestion receiver ready */
6129 				dbug(1, dprintf("clRDY"));
6130 				Info_Number = 0x00B0;
6131 				Info_Mask = 0x08;
6132 				Info_Element = "";
6133 				break;
6134 			case 13: /* congestion receiver not ready */
6135 				dbug(1, dprintf("clNRDY"));
6136 				Info_Number = 0x00BF;
6137 				Info_Mask = 0x08;
6138 				Info_Element = "";
6139 				break;
6140 			case 15: /* Keypad Facility */
6141 				dbug(1, dprintf("KEY"));
6142 				Info_Number = 0x002C;
6143 				Info_Mask = 0x20;
6144 				break;
6145 			case 16: /* Channel Id */
6146 				dbug(1, dprintf("CHI"));
6147 				Info_Number = 0x0018;
6148 				Info_Mask = 0x100;
6149 				mixer_set_bchannel_id(plci, Info_Element);
6150 				break;
6151 			case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6152 				dbug(1, dprintf("q9cau(0x%x)", ie[2]));
6153 				if (!cause[2] || cause[2] < 0x80) break;  /* eg. layer 1 error */
6154 				Info_Number = 0x0008;
6155 				Info_Mask = 0x01;
6156 				if (cause[2] != ie[2]) Info_Element = cause;
6157 				break;
6158 			case 19: /* Redirected Number */
6159 				dbug(1, dprintf("RDN"));
6160 				Info_Number = 0x0074;
6161 				Info_Mask = 0x400;
6162 				break;
6163 			case 22: /* Redirecing Number  */
6164 				dbug(1, dprintf("RIN"));
6165 				Info_Number = 0x0076;
6166 				Info_Mask = 0x400;
6167 				break;
6168 			case 23: /* Notification Indicator  */
6169 				dbug(1, dprintf("NI"));
6170 				Info_Number = (word)NI;
6171 				Info_Mask = 0x210;
6172 				break;
6173 			case 26: /* Call State  */
6174 				dbug(1, dprintf("CST"));
6175 				Info_Number = (word)CST;
6176 				Info_Mask = 0x01; /* do with cause i.e. for now */
6177 				break;
6178 			case MAXPARMSIDS - 2:  /* Escape Message Type, must be the last indication */
6179 				dbug(1, dprintf("ESC/MT[0x%x]", ie[3]));
6180 				Info_Number = 0x8000 | ie[3];
6181 				if (iesent) Info_Mask = 0xffff;
6182 				else  Info_Mask = 0x10;
6183 				Info_Element = "";
6184 				break;
6185 			default:
6186 				Info_Number  = 0;
6187 				Info_Mask    = 0;
6188 				Info_Element = "";
6189 				break;
6190 			}
6191 		}
6192 
6193 		if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6194 		{
6195 			for (j = 0; j < max_appl; j++)
6196 			{
6197 				appl = &application[j];
6198 				if (Info_Number
6199 				    && appl->Id
6200 				    && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6201 				{
6202 					dbug(1, dprintf("NCR_Ind"));
6203 					iesent = true;
6204 					sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6205 				}
6206 			}
6207 		}
6208 		else if (!plci->appl)
6209 		{ /* overlap receiving broadcast */
6210 			if (Info_Number == CPN
6211 			    || Info_Number == KEY
6212 			    || Info_Number == NI
6213 			    || Info_Number == DSP
6214 			    || Info_Number == UUI)
6215 			{
6216 				for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
6217 					dbug(1, dprintf("Ovl_Ind"));
6218 					iesent = true;
6219 					sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6220 				}
6221 			}
6222 		}               /* all other signalling states */
6223 		else if (Info_Number
6224 			 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6225 		{
6226 			dbug(1, dprintf("Std_Ind"));
6227 			iesent = true;
6228 			sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6229 		}
6230 	}
6231 }
6232 
6233 
SendMultiIE(PLCI * plci,dword Id,byte ** parms,byte ie_type,dword info_mask,byte setupParse)6234 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6235 			dword info_mask, byte setupParse)
6236 {
6237 	word i;
6238 	word j;
6239 	byte *ie;
6240 	word Info_Number;
6241 	byte *Info_Element;
6242 	APPL *appl;
6243 	word Info_Mask = 0;
6244 	byte iesent = 0;
6245 
6246 	if (
6247 		!plci->appl
6248 		&& !plci->State
6249 		&& plci->Sig.Ind != NCR_FACILITY
6250 		&& !setupParse
6251 		)
6252 	{
6253 		dbug(1, dprintf("NoM-IEParse "));
6254 		return 0;
6255 	}
6256 	dbug(1, dprintf("M-IEParse "));
6257 
6258 	for (i = 0; i < MAX_MULTI_IE; i++)
6259 	{
6260 		ie = parms[i];
6261 		Info_Number = 0;
6262 		Info_Element = ie;
6263 		if (ie[0])
6264 		{
6265 			dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci->Sig.Ind, ie_type));
6266 			Info_Number = (word)ie_type;
6267 			Info_Mask = (word)info_mask;
6268 		}
6269 
6270 		if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6271 		{
6272 			for (j = 0; j < max_appl; j++)
6273 			{
6274 				appl = &application[j];
6275 				if (Info_Number
6276 				    && appl->Id
6277 				    && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6278 				{
6279 					iesent = true;
6280 					dbug(1, dprintf("Mlt_NCR_Ind"));
6281 					sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6282 				}
6283 			}
6284 		}
6285 		else if (!plci->appl && Info_Number)
6286 		{                                        /* overlap receiving broadcast */
6287 			for_each_set_bit(j, plci->c_ind_mask_table, max_appl) {
6288 				iesent = true;
6289 				dbug(1, dprintf("Mlt_Ovl_Ind"));
6290 				sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6291 			}
6292 		}                                        /* all other signalling states */
6293 		else if (Info_Number
6294 			 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6295 		{
6296 			iesent = true;
6297 			dbug(1, dprintf("Mlt_Std_Ind"));
6298 			sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6299 		}
6300 	}
6301 	return iesent;
6302 }
6303 
SendSSExtInd(APPL * appl,PLCI * plci,dword Id,byte ** parms)6304 static void SendSSExtInd(APPL *appl, PLCI *plci, dword Id, byte **parms)
6305 {
6306 	word i;
6307 	/* Format of multi_ssext_parms[i][]:
6308 	   0 byte length
6309 	   1 byte SSEXTIE
6310 	   2 byte SSEXT_REQ/SSEXT_IND
6311 	   3 byte length
6312 	   4 word SSExtCommand
6313 	   6... Params
6314 	*/
6315 	if (
6316 		plci
6317 		&& plci->State
6318 		&& plci->Sig.Ind != NCR_FACILITY
6319 		)
6320 		for (i = 0; i < MAX_MULTI_IE; i++)
6321 		{
6322 			if (parms[i][0] < 6) continue;
6323 			if (parms[i][2] == SSEXT_REQ) continue;
6324 
6325 			if (appl)
6326 			{
6327 				parms[i][0] = 0; /* kill it */
6328 				sendf(appl, _MANUFACTURER_I,
6329 				      Id,
6330 				      0,
6331 				      "dwS",
6332 				      _DI_MANU_ID,
6333 				      _DI_SSEXT_CTRL,
6334 				      &parms[i][3]);
6335 			}
6336 			else if (plci->appl)
6337 			{
6338 				parms[i][0] = 0; /* kill it */
6339 				sendf(plci->appl, _MANUFACTURER_I,
6340 				      Id,
6341 				      0,
6342 				      "dwS",
6343 				      _DI_MANU_ID,
6344 				      _DI_SSEXT_CTRL,
6345 				      &parms[i][3]);
6346 			}
6347 		}
6348 };
6349 
nl_ind(PLCI * plci)6350 static void nl_ind(PLCI *plci)
6351 {
6352 	byte ch;
6353 	word ncci;
6354 	dword Id;
6355 	DIVA_CAPI_ADAPTER *a;
6356 	word NCCIcode;
6357 	APPL *APPLptr;
6358 	word count;
6359 	word Num;
6360 	word i, ncpi_state;
6361 	byte len, ncci_state;
6362 	word msg;
6363 	word info = 0;
6364 	word fax_feature_bits;
6365 	byte fax_send_edata_ack;
6366 	static byte v120_header_buffer[2 + 3];
6367 	static word fax_info[] = {
6368 		0,                     /* T30_SUCCESS                        */
6369 		_FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
6370 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
6371 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
6372 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
6373 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
6374 		_FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
6375 		_FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
6376 		_FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
6377 		_FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
6378 		_FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
6379 		_FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
6380 		_FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
6381 		_FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
6382 		_FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
6383 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
6384 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
6385 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
6386 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
6387 		_FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
6388 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
6389 		_FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
6390 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
6391 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
6392 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
6393 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
6394 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
6395 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
6396 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
6397 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
6398 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
6399 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
6400 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
6401 		0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
6402 		0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
6403 		0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
6404 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
6405 		_FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
6406 		_FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
6407 		_FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
6408 		_FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
6409 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6410 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
6411 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
6412 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
6413 		_FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
6414 		_FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
6415 	};
6416 
6417 	byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6418 
6419 
6420 	static word rtp_info[] = {
6421 		GOOD,                  /* RTP_SUCCESS                       */
6422 		0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
6423 	};
6424 
6425 	static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6426 		{
6427 			0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6428 			0x00000000, 0x00000000, 0x00000000, 0x00000000
6429 		};
6430 
6431 	ch = plci->NL.IndCh;
6432 	a = plci->adapter;
6433 	ncci = a->ch_ncci[ch];
6434 	Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6435 	if (plci->tel) Id |= EXT_CONTROLLER;
6436 	APPLptr = plci->appl;
6437 	dbug(1, dprintf("NL_IND-Id(NL:0x%x)=0x%08lx,plci=%x,tel=%x,state=0x%x,ch=0x%x,chs=%d,Ind=%x",
6438 			plci->NL.Id, Id, plci->Id, plci->tel, plci->State, ch, plci->channels, plci->NL.Ind & 0x0f));
6439 
6440 	/* in the case if no connect_active_Ind was sent to the appl we wait for */
6441 
6442 	if (plci->nl_remove_id)
6443 	{
6444 		plci->NL.RNR = 2; /* discard */
6445 		dbug(1, dprintf("NL discard while remove pending"));
6446 		return;
6447 	}
6448 	if ((plci->NL.Ind & 0x0f) == N_CONNECT)
6449 	{
6450 		if (plci->State == INC_DIS_PENDING
6451 		    || plci->State == OUTG_DIS_PENDING
6452 		    || plci->State == IDLE)
6453 		{
6454 			plci->NL.RNR = 2; /* discard */
6455 			dbug(1, dprintf("discard n_connect"));
6456 			return;
6457 		}
6458 		if (plci->State < INC_ACT_PENDING)
6459 		{
6460 			plci->NL.RNR = 1; /* flow control */
6461 			channel_x_off(plci, ch, N_XON_CONNECT_IND);
6462 			return;
6463 		}
6464 	}
6465 
6466 	if (!APPLptr)                         /* no application or invalid data */
6467 	{                                    /* while reloading the DSP        */
6468 		dbug(1, dprintf("discard1"));
6469 		plci->NL.RNR = 2;
6470 		return;
6471 	}
6472 
6473 	if (((plci->NL.Ind & 0x0f) == N_UDATA)
6474 	    && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6475 		|| (plci->B2_prot == 7)
6476 		|| (plci->B3_prot == 7)))
6477 	{
6478 		plci->ncpi_buffer[0] = 0;
6479 
6480 		ncpi_state = plci->ncpi_state;
6481 		if (plci->NL.complete == 1)
6482 		{
6483 			byte *data = &plci->NL.RBuffer->P[0];
6484 
6485 			if ((plci->NL.RBuffer->length >= 12)
6486 			    && ((*data == DSP_UDATA_INDICATION_DCD_ON)
6487 				|| (*data == DSP_UDATA_INDICATION_CTS_ON)))
6488 			{
6489 				word conn_opt, ncpi_opt = 0x00;
6490 /*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6491 
6492 				if (*data == DSP_UDATA_INDICATION_DCD_ON)
6493 					plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6494 				if (*data == DSP_UDATA_INDICATION_CTS_ON)
6495 					plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6496 
6497 				data++;    /* indication code */
6498 				data += 2; /* timestamp */
6499 				if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6500 					ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6501 				data++;    /* connected norm */
6502 				conn_opt = GET_WORD(data);
6503 				data += 2; /* connected options */
6504 
6505 				PUT_WORD(&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6506 
6507 				if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6508 				{
6509 					ncpi_opt |= MDM_NCPI_ECM_V42;
6510 				}
6511 				else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6512 				{
6513 					ncpi_opt |= MDM_NCPI_ECM_MNP;
6514 				}
6515 				else
6516 				{
6517 					ncpi_opt |= MDM_NCPI_TRANSPARENT;
6518 				}
6519 				if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6520 				{
6521 					ncpi_opt |= MDM_NCPI_COMPRESSED;
6522 				}
6523 				PUT_WORD(&(plci->ncpi_buffer[3]), ncpi_opt);
6524 				plci->ncpi_buffer[0] = 4;
6525 
6526 				plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6527 			}
6528 		}
6529 		if (plci->B3_prot == 7)
6530 		{
6531 			if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6532 			    && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6533 			    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6534 			{
6535 				a->ncci_state[ncci] = INC_ACT_PENDING;
6536 				sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6537 				plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6538 			}
6539 		}
6540 
6541 		if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
6542 		      & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6543 		    || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6544 		    || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6545 
6546 		{
6547 			plci->NL.RNR = 2;
6548 			return;
6549 		}
6550 	}
6551 
6552 	if (plci->NL.complete == 2)
6553 	{
6554 		if (((plci->NL.Ind & 0x0f) == N_UDATA)
6555 		    && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6556 		{
6557 			switch (plci->RData[0].P[0])
6558 			{
6559 
6560 			case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6561 				if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6562 					sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01X");
6563 				break;
6564 			case DTMF_UDATA_INDICATION_ANSWER_TONE:
6565 				if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6566 					sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01Y");
6567 				break;
6568 			case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6569 				dtmf_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6570 				break;
6571 			case DTMF_UDATA_INDICATION_DIGITS_SENT:
6572 				dtmf_confirmation(Id, plci);
6573 				break;
6574 
6575 
6576 			case UDATA_INDICATION_MIXER_TAP_DATA:
6577 				capidtmf_recv_process_block(&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6578 				i = capidtmf_indication(&(plci->capidtmf_state), dtmf_code_buffer + 1);
6579 				if (i != 0)
6580 				{
6581 					dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6582 					dtmf_indication(Id, plci, dtmf_code_buffer, (word)(i + 1));
6583 				}
6584 				break;
6585 
6586 
6587 			case UDATA_INDICATION_MIXER_COEFS_SET:
6588 				mixer_indication_coefs_set(Id, plci);
6589 				break;
6590 			case UDATA_INDICATION_XCONNECT_FROM:
6591 				mixer_indication_xconnect_from(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6592 				break;
6593 			case UDATA_INDICATION_XCONNECT_TO:
6594 				mixer_indication_xconnect_to(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6595 				break;
6596 
6597 
6598 			case LEC_UDATA_INDICATION_DISABLE_DETECT:
6599 				ec_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6600 				break;
6601 
6602 
6603 
6604 			default:
6605 				break;
6606 			}
6607 		}
6608 		else
6609 		{
6610 			if ((plci->RData[0].PLength != 0)
6611 			    && ((plci->B2_prot == B2_V120_ASYNC)
6612 				|| (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6613 				|| (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6614 			{
6615 
6616 				sendf(plci->appl, _DATA_B3_I, Id, 0,
6617 				      "dwww",
6618 				      plci->RData[1].P,
6619 				      (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6620 				      plci->RNum,
6621 				      plci->RFlags);
6622 
6623 			}
6624 			else
6625 			{
6626 
6627 				sendf(plci->appl, _DATA_B3_I, Id, 0,
6628 				      "dwww",
6629 				      plci->RData[0].P,
6630 				      plci->RData[0].PLength,
6631 				      plci->RNum,
6632 				      plci->RFlags);
6633 
6634 			}
6635 		}
6636 		return;
6637 	}
6638 
6639 	fax_feature_bits = 0;
6640 	if ((plci->NL.Ind & 0x0f) == N_CONNECT ||
6641 	    (plci->NL.Ind & 0x0f) == N_CONNECT_ACK ||
6642 	    (plci->NL.Ind & 0x0f) == N_DISC ||
6643 	    (plci->NL.Ind & 0x0f) == N_EDATA ||
6644 	    (plci->NL.Ind & 0x0f) == N_DISC_ACK)
6645 	{
6646 		info = 0;
6647 		plci->ncpi_buffer[0] = 0;
6648 		switch (plci->B3_prot) {
6649 		case  0: /*XPARENT*/
6650 		case  1: /*T.90 NL*/
6651 			break;    /* no network control protocol info - jfr */
6652 		case  2: /*ISO8202*/
6653 		case  3: /*X25 DCE*/
6654 			for (i = 0; i < plci->NL.RLength; i++) plci->ncpi_buffer[4 + i] = plci->NL.RBuffer->P[i];
6655 			plci->ncpi_buffer[0] = (byte)(i + 3);
6656 			plci->ncpi_buffer[1] = (byte)(plci->NL.Ind & N_D_BIT ? 1 : 0);
6657 			plci->ncpi_buffer[2] = 0;
6658 			plci->ncpi_buffer[3] = 0;
6659 			break;
6660 		case  4: /*T.30 - FAX*/
6661 		case  5: /*T.30 - FAX*/
6662 			if (plci->NL.RLength >= sizeof(T30_INFO))
6663 			{
6664 				dbug(1, dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6665 				len = 9;
6666 				PUT_WORD(&(plci->ncpi_buffer[1]), ((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6667 				fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6668 				i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6669 				if (plci->B3_prot == 5)
6670 				{
6671 					if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6672 						i |= 0x8000; /* This is not an ECM connection */
6673 					if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6674 						i |= 0x4000; /* This is a connection with MMR compression */
6675 					if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6676 						i |= 0x2000; /* This is a connection with MR compression */
6677 					if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6678 						i |= 0x0004; /* More documents */
6679 					if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6680 						i |= 0x0002; /* Fax-polling indication */
6681 				}
6682 				dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits, i));
6683 				PUT_WORD(&(plci->ncpi_buffer[3]), i);
6684 				PUT_WORD(&(plci->ncpi_buffer[5]), ((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6685 				plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6686 				plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6687 				plci->ncpi_buffer[len] = 0;
6688 				if (((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6689 				{
6690 					plci->ncpi_buffer[len] = 20;
6691 					for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6692 						plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6693 				}
6694 				if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6695 				{
6696 					if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6697 						info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6698 					else
6699 						info = _FAX_PROTOCOL_ERROR;
6700 				}
6701 
6702 				if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6703 				    & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6704 				{
6705 					i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6706 					while (i < plci->NL.RBuffer->length)
6707 						plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6708 				}
6709 
6710 				plci->ncpi_buffer[0] = len;
6711 				fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6712 				PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6713 
6714 				plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6715 				if (((plci->NL.Ind & 0x0f) == N_CONNECT_ACK)
6716 				    || (((plci->NL.Ind & 0x0f) == N_CONNECT)
6717 					&& (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6718 				    || (((plci->NL.Ind & 0x0f) == N_EDATA)
6719 					&& ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6720 					    || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6721 					    || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6722 				{
6723 					plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6724 				}
6725 				if (((plci->NL.Ind & 0x0f) == N_DISC)
6726 				    || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)
6727 				    || (((plci->NL.Ind & 0x0f) == N_EDATA)
6728 					&& (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6729 				{
6730 					plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6731 				}
6732 			}
6733 			break;
6734 
6735 		case B3_RTP:
6736 			if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6737 			{
6738 				if (plci->NL.RLength != 0)
6739 				{
6740 					info = rtp_info[plci->NL.RBuffer->P[0]];
6741 					plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6742 					for (i = 1; i < plci->NL.RLength; i++)
6743 						plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6744 				}
6745 			}
6746 			break;
6747 
6748 		}
6749 		plci->NL.RNR = 2;
6750 	}
6751 	switch (plci->NL.Ind & 0x0f) {
6752 	case N_EDATA:
6753 		if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6754 		{
6755 			dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6756 					((T30_INFO *)plci->NL.RBuffer->P)->code));
6757 			fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6758 
6759 			if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6760 			    && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6761 			    && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6762 			    && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6763 			    && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6764 			    && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6765 			{
6766 				((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6767 				sendf(plci->appl, _MANUFACTURER_I, Id, 0, "dwbS", _DI_MANU_ID, _DI_NEGOTIATE_B3,
6768 				      (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6769 				plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6770 				if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6771 					fax_send_edata_ack = false;
6772 			}
6773 
6774 			if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6775 			{
6776 				switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6777 				{
6778 				case EDATA_T30_DIS:
6779 					if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6780 					    && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6781 					    && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6782 					    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6783 					{
6784 						a->ncci_state[ncci] = INC_ACT_PENDING;
6785 						if (plci->B3_prot == 4)
6786 							sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6787 						else
6788 							sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6789 						plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6790 					}
6791 					break;
6792 
6793 				case EDATA_T30_TRAIN_OK:
6794 					if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6795 					    && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6796 					    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6797 					{
6798 						if (plci->B3_prot == 4)
6799 							sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6800 						else
6801 							sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6802 						plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6803 					}
6804 					break;
6805 
6806 				case EDATA_T30_EOP_CAPI:
6807 					if (a->ncci_state[ncci] == CONNECTED)
6808 					{
6809 						sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", GOOD, plci->ncpi_buffer);
6810 						a->ncci_state[ncci] = INC_DIS_PENDING;
6811 						plci->ncpi_state = 0;
6812 						fax_send_edata_ack = false;
6813 					}
6814 					break;
6815 				}
6816 			}
6817 			else
6818 			{
6819 				switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6820 				{
6821 				case EDATA_T30_TRAIN_OK:
6822 					if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6823 					    && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6824 					    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6825 					{
6826 						if (plci->B3_prot == 4)
6827 							sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6828 						else
6829 							sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6830 						plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6831 					}
6832 					break;
6833 				}
6834 			}
6835 			if (fax_send_edata_ack)
6836 			{
6837 				((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6838 				plci->fax_edata_ack_length = 1;
6839 				start_internal_command(Id, plci, fax_edata_ack_command);
6840 			}
6841 		}
6842 		else
6843 		{
6844 			dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6845 		}
6846 		break;
6847 	case N_CONNECT:
6848 		if (!a->ch_ncci[ch])
6849 		{
6850 			ncci = get_ncci(plci, ch, 0);
6851 			Id = (Id & 0xffff) | (((dword) ncci) << 16);
6852 		}
6853 		dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6854 				ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6855 
6856 		msg = _CONNECT_B3_I;
6857 		if (a->ncci_state[ncci] == IDLE)
6858 			plci->channels++;
6859 		else if (plci->B3_prot == 1)
6860 			msg = _CONNECT_B3_T90_ACTIVE_I;
6861 
6862 		a->ncci_state[ncci] = INC_CON_PENDING;
6863 		if (plci->B3_prot == 4)
6864 			sendf(plci->appl, msg, Id, 0, "s", "");
6865 		else
6866 			sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6867 		break;
6868 	case N_CONNECT_ACK:
6869 		dbug(1, dprintf("N_connect_Ack"));
6870 		if (plci->internal_command_queue[0]
6871 		    && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6872 			|| (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6873 			|| (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6874 		{
6875 			(*(plci->internal_command_queue[0]))(Id, plci, 0);
6876 			if (!plci->internal_command)
6877 				next_internal_command(Id, plci);
6878 			break;
6879 		}
6880 		msg = _CONNECT_B3_ACTIVE_I;
6881 		if (plci->B3_prot == 1)
6882 		{
6883 			if (a->ncci_state[ncci] != OUTG_CON_PENDING)
6884 				msg = _CONNECT_B3_T90_ACTIVE_I;
6885 			a->ncci_state[ncci] = INC_ACT_PENDING;
6886 			sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6887 		}
6888 		else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
6889 		{
6890 			if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6891 			    && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6892 			    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6893 			{
6894 				a->ncci_state[ncci] = INC_ACT_PENDING;
6895 				if (plci->B3_prot == 4)
6896 					sendf(plci->appl, msg, Id, 0, "s", "");
6897 				else
6898 					sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6899 				plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6900 			}
6901 		}
6902 		else
6903 		{
6904 			a->ncci_state[ncci] = INC_ACT_PENDING;
6905 			sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
6906 		}
6907 		if (plci->adjust_b_restore)
6908 		{
6909 			plci->adjust_b_restore = false;
6910 			start_internal_command(Id, plci, adjust_b_restore);
6911 		}
6912 		break;
6913 	case N_DISC:
6914 	case N_DISC_ACK:
6915 		if (plci->internal_command_queue[0]
6916 		    && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
6917 			|| (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
6918 			|| (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
6919 		{
6920 			(*(plci->internal_command_queue[0]))(Id, plci, 0);
6921 			if (!plci->internal_command)
6922 				next_internal_command(Id, plci);
6923 		}
6924 		ncci_state = a->ncci_state[ncci];
6925 		ncci_remove(plci, ncci, false);
6926 
6927 		/* with N_DISC or N_DISC_ACK the IDI frees the respective   */
6928 		/* channel, so we cannot store the state in ncci_state! The */
6929 		/* information which channel we received a N_DISC is thus   */
6930 		/* stored in the inc_dis_ncci_table buffer.                 */
6931 		for (i = 0; plci->inc_dis_ncci_table[i]; i++);
6932 		plci->inc_dis_ncci_table[i] = (byte) ncci;
6933 
6934 		/* need a connect_b3_ind before a disconnect_b3_ind with FAX */
6935 		if (!plci->channels
6936 		    && (plci->B1_resource == 16)
6937 		    && (plci->State <= CONNECTED))
6938 		{
6939 			len = 9;
6940 			i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
6941 			PUT_WORD(&plci->ncpi_buffer[1], i);
6942 			PUT_WORD(&plci->ncpi_buffer[3], 0);
6943 			i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
6944 			PUT_WORD(&plci->ncpi_buffer[5], i);
6945 			PUT_WORD(&plci->ncpi_buffer[7], 0);
6946 			plci->ncpi_buffer[len] = 0;
6947 			plci->ncpi_buffer[0] = len;
6948 			if (plci->B3_prot == 4)
6949 				sendf(plci->appl, _CONNECT_B3_I, Id, 0, "s", "");
6950 			else
6951 			{
6952 
6953 				if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6954 				    & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6955 				{
6956 					plci->ncpi_buffer[++len] = 0;
6957 					plci->ncpi_buffer[++len] = 0;
6958 					plci->ncpi_buffer[++len] = 0;
6959 					plci->ncpi_buffer[0] = len;
6960 				}
6961 
6962 				sendf(plci->appl, _CONNECT_B3_I, Id, 0, "S", plci->ncpi_buffer);
6963 			}
6964 			sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
6965 			plci->ncpi_state = 0;
6966 			sig_req(plci, HANGUP, 0);
6967 			send_req(plci);
6968 			plci->State = OUTG_DIS_PENDING;
6969 			/* disc here */
6970 		}
6971 		else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6972 			 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6973 			 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
6974 		{
6975 			if (ncci_state == IDLE)
6976 			{
6977 				if (plci->channels)
6978 					plci->channels--;
6979 				if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
6980 					if (plci->State == SUSPENDING) {
6981 						sendf(plci->appl,
6982 						      _FACILITY_I,
6983 						      Id & 0xffffL,
6984 						      0,
6985 						      "ws", (word)3, "\x03\x04\x00\x00");
6986 						sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
6987 					}
6988 					plci_remove(plci);
6989 					plci->State = IDLE;
6990 				}
6991 			}
6992 		}
6993 		else if (plci->channels)
6994 		{
6995 			sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
6996 			plci->ncpi_state = 0;
6997 			if ((ncci_state == OUTG_REJ_PENDING)
6998 			    && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
6999 			{
7000 				sig_req(plci, HANGUP, 0);
7001 				send_req(plci);
7002 				plci->State = OUTG_DIS_PENDING;
7003 			}
7004 		}
7005 		break;
7006 	case N_RESET:
7007 		a->ncci_state[ncci] = INC_RES_PENDING;
7008 		sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7009 		break;
7010 	case N_RESET_ACK:
7011 		a->ncci_state[ncci] = CONNECTED;
7012 		sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7013 		break;
7014 
7015 	case N_UDATA:
7016 		if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7017 		{
7018 			plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7019 			plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7020 			plci->NL.R = plci->RData;
7021 			plci->NL.RNum = 1;
7022 			return;
7023 		}
7024 		/* fall through */
7025 	case N_BDATA:
7026 	case N_DATA:
7027 		if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7028 		    || (a->ncci_state[ncci] == IDLE)
7029 		    || (a->ncci_state[ncci] == INC_DIS_PENDING))
7030 		{
7031 			plci->NL.RNR = 2;
7032 			break;
7033 		}
7034 		if ((a->ncci_state[ncci] != CONNECTED)
7035 		    && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7036 		    && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7037 		{
7038 			dbug(1, dprintf("flow control"));
7039 			plci->NL.RNR = 1; /* flow control  */
7040 			channel_x_off(plci, ch, 0);
7041 			break;
7042 		}
7043 
7044 		NCCIcode = ncci | (((word)a->Id) << 8);
7045 
7046 		/* count all buffers within the Application pool    */
7047 		/* belonging to the same NCCI. If this is below the */
7048 		/* number of buffers available per NCCI we accept   */
7049 		/* this packet, otherwise we reject it              */
7050 		count = 0;
7051 		Num = 0xffff;
7052 		for (i = 0; i < APPLptr->MaxBuffer; i++) {
7053 			if (NCCIcode == APPLptr->DataNCCI[i]) count++;
7054 			if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
7055 		}
7056 
7057 		if (count >= APPLptr->MaxNCCIData || Num == 0xffff)
7058 		{
7059 			dbug(3, dprintf("Flow-Control"));
7060 			plci->NL.RNR = 1;
7061 			if (++(APPLptr->NCCIDataFlowCtrlTimer) >=
7062 			    (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7063 			{
7064 				plci->NL.RNR = 2;
7065 				dbug(3, dprintf("DiscardData"));
7066 			} else {
7067 				channel_x_off(plci, ch, 0);
7068 			}
7069 			break;
7070 		}
7071 		else
7072 		{
7073 			APPLptr->NCCIDataFlowCtrlTimer = 0;
7074 		}
7075 
7076 		plci->RData[0].P = ReceiveBufferGet(APPLptr, Num);
7077 		if (!plci->RData[0].P) {
7078 			plci->NL.RNR = 1;
7079 			channel_x_off(plci, ch, 0);
7080 			break;
7081 		}
7082 
7083 		APPLptr->DataNCCI[Num] = NCCIcode;
7084 		APPLptr->DataFlags[Num] = (plci->Id << 8) | (plci->NL.Ind >> 4);
7085 		dbug(3, dprintf("Buffer(%d), Max = %d", Num, APPLptr->MaxBuffer));
7086 
7087 		plci->RNum = Num;
7088 		plci->RFlags = plci->NL.Ind >> 4;
7089 		plci->RData[0].PLength = APPLptr->MaxDataLength;
7090 		plci->NL.R = plci->RData;
7091 		if ((plci->NL.RLength != 0)
7092 		    && ((plci->B2_prot == B2_V120_ASYNC)
7093 			|| (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7094 			|| (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7095 		{
7096 			plci->RData[1].P = plci->RData[0].P;
7097 			plci->RData[1].PLength = plci->RData[0].PLength;
7098 			plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7099 			if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7100 				plci->RData[0].PLength = 1;
7101 			else
7102 				plci->RData[0].PLength = 2;
7103 			if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7104 				plci->RFlags |= 0x0010;
7105 			if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7106 				plci->RFlags |= 0x8000;
7107 			plci->NL.RNum = 2;
7108 		}
7109 		else
7110 		{
7111 			if ((plci->NL.Ind & 0x0f) == N_UDATA)
7112 				plci->RFlags |= 0x0010;
7113 
7114 			else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7115 				plci->RFlags |= 0x0001;
7116 
7117 			plci->NL.RNum = 1;
7118 		}
7119 		break;
7120 	case N_DATA_ACK:
7121 		data_ack(plci, ch);
7122 		break;
7123 	default:
7124 		plci->NL.RNR = 2;
7125 		break;
7126 	}
7127 }
7128 
7129 /*------------------------------------------------------------------*/
7130 /* find a free PLCI */
7131 /*------------------------------------------------------------------*/
7132 
get_plci(DIVA_CAPI_ADAPTER * a)7133 static word get_plci(DIVA_CAPI_ADAPTER *a)
7134 {
7135 	word i, j;
7136 	PLCI *plci;
7137 
7138 	for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
7139 	if (i == a->max_plci) {
7140 		dbug(1, dprintf("get_plci: out of PLCIs"));
7141 		return 0;
7142 	}
7143 	plci = &a->plci[i];
7144 	plci->Id = (byte)(i + 1);
7145 
7146 	plci->Sig.Id = 0;
7147 	plci->NL.Id = 0;
7148 	plci->sig_req = 0;
7149 	plci->nl_req = 0;
7150 
7151 	plci->appl = NULL;
7152 	plci->relatedPTYPLCI = NULL;
7153 	plci->State = IDLE;
7154 	plci->SuppState = IDLE;
7155 	plci->channels = 0;
7156 	plci->tel = 0;
7157 	plci->B1_resource = 0;
7158 	plci->B2_prot = 0;
7159 	plci->B3_prot = 0;
7160 
7161 	plci->command = 0;
7162 	plci->m_command = 0;
7163 	init_internal_command_queue(plci);
7164 	plci->number = 0;
7165 	plci->req_in_start = 0;
7166 	plci->req_in = 0;
7167 	plci->req_out = 0;
7168 	plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7169 	plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7170 	plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7171 
7172 	plci->data_sent = false;
7173 	plci->send_disc = 0;
7174 	plci->sig_global_req = 0;
7175 	plci->sig_remove_id = 0;
7176 	plci->nl_global_req = 0;
7177 	plci->nl_remove_id = 0;
7178 	plci->adv_nl = 0;
7179 	plci->manufacturer = false;
7180 	plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7181 	plci->spoofed_msg = 0;
7182 	plci->ptyState = 0;
7183 	plci->cr_enquiry = false;
7184 	plci->hangup_flow_ctrl_timer = 0;
7185 
7186 	plci->ncci_ring_list = 0;
7187 	for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
7188 	bitmap_zero(plci->c_ind_mask_table, MAX_APPL);
7189 	bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
7190 	plci->fax_connect_info_length = 0;
7191 	plci->nsf_control_bits = 0;
7192 	plci->ncpi_state = 0x00;
7193 	plci->ncpi_buffer[0] = 0;
7194 
7195 	plci->requested_options_conn = 0;
7196 	plci->requested_options = 0;
7197 	plci->notifiedcall = 0;
7198 	plci->vswitchstate = 0;
7199 	plci->vsprot = 0;
7200 	plci->vsprotdialect = 0;
7201 	init_b1_config(plci);
7202 	dbug(1, dprintf("get_plci(%x)", plci->Id));
7203 	return i + 1;
7204 }
7205 
7206 /*------------------------------------------------------------------*/
7207 /* put a parameter in the parameter buffer                          */
7208 /*------------------------------------------------------------------*/
7209 
add_p(PLCI * plci,byte code,byte * p)7210 static void add_p(PLCI *plci, byte code, byte *p)
7211 {
7212 	word p_length;
7213 
7214 	p_length = 0;
7215 	if (p) p_length = p[0];
7216 	add_ie(plci, code, p, p_length);
7217 }
7218 
7219 /*------------------------------------------------------------------*/
7220 /* put a structure in the parameter buffer                          */
7221 /*------------------------------------------------------------------*/
add_s(PLCI * plci,byte code,API_PARSE * p)7222 static void add_s(PLCI *plci, byte code, API_PARSE *p)
7223 {
7224 	if (p) add_ie(plci, code, p->info, (word)p->length);
7225 }
7226 
7227 /*------------------------------------------------------------------*/
7228 /* put multiple structures in the parameter buffer                  */
7229 /*------------------------------------------------------------------*/
add_ss(PLCI * plci,byte code,API_PARSE * p)7230 static void add_ss(PLCI *plci, byte code, API_PARSE *p)
7231 {
7232 	byte i;
7233 
7234 	if (p) {
7235 		dbug(1, dprintf("add_ss(%x,len=%d)", code, p->length));
7236 		for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7237 			dbug(1, dprintf("add_ss_ie(%x,len=%d)", p->info[i - 1], p->info[i]));
7238 			add_ie(plci, p->info[i - 1], (byte *)&(p->info[i]), (word)p->info[i]);
7239 		}
7240 	}
7241 }
7242 
7243 /*------------------------------------------------------------------*/
7244 /* return the channel number sent by the application in a esc_chi   */
7245 /*------------------------------------------------------------------*/
getChannel(API_PARSE * p)7246 static byte getChannel(API_PARSE *p)
7247 {
7248 	byte i;
7249 
7250 	if (p) {
7251 		for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7252 			if (p->info[i] == 2) {
7253 				if (p->info[i - 1] == ESC && p->info[i + 1] == CHI) return (p->info[i + 2]);
7254 			}
7255 		}
7256 	}
7257 	return 0;
7258 }
7259 
7260 
7261 /*------------------------------------------------------------------*/
7262 /* put an information element in the parameter buffer               */
7263 /*------------------------------------------------------------------*/
7264 
add_ie(PLCI * plci,byte code,byte * p,word p_length)7265 static void add_ie(PLCI *plci, byte code, byte *p, word p_length)
7266 {
7267 	word i;
7268 
7269 	if (!(code & 0x80) && !p_length) return;
7270 
7271 	if (plci->req_in == plci->req_in_start) {
7272 		plci->req_in += 2;
7273 	}
7274 	else {
7275 		plci->req_in--;
7276 	}
7277 	plci->RBuffer[plci->req_in++] = code;
7278 
7279 	if (p) {
7280 		plci->RBuffer[plci->req_in++] = (byte)p_length;
7281 		for (i = 0; i < p_length; i++) plci->RBuffer[plci->req_in++] = p[1 + i];
7282 	}
7283 
7284 	plci->RBuffer[plci->req_in++] = 0;
7285 }
7286 
7287 /*------------------------------------------------------------------*/
7288 /* put a unstructured data into the buffer                          */
7289 /*------------------------------------------------------------------*/
7290 
add_d(PLCI * plci,word length,byte * p)7291 static void add_d(PLCI *plci, word length, byte *p)
7292 {
7293 	word i;
7294 
7295 	if (plci->req_in == plci->req_in_start) {
7296 		plci->req_in += 2;
7297 	}
7298 	else {
7299 		plci->req_in--;
7300 	}
7301 	for (i = 0; i < length; i++) plci->RBuffer[plci->req_in++] = p[i];
7302 }
7303 
7304 /*------------------------------------------------------------------*/
7305 /* put parameters from the Additional Info parameter in the         */
7306 /* parameter buffer                                                 */
7307 /*------------------------------------------------------------------*/
7308 
add_ai(PLCI * plci,API_PARSE * ai)7309 static void add_ai(PLCI *plci, API_PARSE *ai)
7310 {
7311 	word i;
7312 	API_PARSE ai_parms[5];
7313 
7314 	for (i = 0; i < 5; i++) ai_parms[i].length = 0;
7315 
7316 	if (!ai->length)
7317 		return;
7318 	if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7319 		return;
7320 
7321 	add_s(plci, KEY, &ai_parms[1]);
7322 	add_s(plci, UUI, &ai_parms[2]);
7323 	add_ss(plci, FTY, &ai_parms[3]);
7324 }
7325 
7326 /*------------------------------------------------------------------*/
7327 /* put parameter for b1 protocol in the parameter buffer            */
7328 /*------------------------------------------------------------------*/
7329 
add_b1(PLCI * plci,API_PARSE * bp,word b_channel_info,word b1_facilities)7330 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7331 		   word b1_facilities)
7332 {
7333 	API_PARSE bp_parms[8];
7334 	API_PARSE mdm_cfg[9];
7335 	API_PARSE global_config[2];
7336 	byte cai[256];
7337 	byte resource[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7338 	byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7339 	word i;
7340 
7341 	API_PARSE mdm_cfg_v18[4];
7342 	word j, n, w;
7343 	dword d;
7344 
7345 
7346 	for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7347 	for (i = 0; i < 2; i++) global_config[i].length = 0;
7348 
7349 	dbug(1, dprintf("add_b1"));
7350 	api_save_msg(bp, "s", &plci->B_protocol);
7351 
7352 	if (b_channel_info == 2) {
7353 		plci->B1_resource = 0;
7354 		adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7355 		add_p(plci, CAI, "\x01\x00");
7356 		dbug(1, dprintf("Cai=1,0 (no resource)"));
7357 		return 0;
7358 	}
7359 
7360 	if (plci->tel == CODEC_PERMANENT) return 0;
7361 	else if (plci->tel == CODEC) {
7362 		plci->B1_resource = 1;
7363 		adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7364 		add_p(plci, CAI, "\x01\x01");
7365 		dbug(1, dprintf("Cai=1,1 (Codec)"));
7366 		return 0;
7367 	}
7368 	else if (plci->tel == ADV_VOICE) {
7369 		plci->B1_resource = add_b1_facilities(plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7370 		adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7371 		voice_cai[1] = plci->B1_resource;
7372 		PUT_WORD(&voice_cai[5], plci->appl->MaxDataLength);
7373 		add_p(plci, CAI, voice_cai);
7374 		dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai[1]));
7375 		return 0;
7376 	}
7377 	plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7378 	if (plci->call_dir & CALL_DIR_OUT)
7379 		plci->call_dir |= CALL_DIR_ORIGINATE;
7380 	else if (plci->call_dir & CALL_DIR_IN)
7381 		plci->call_dir |= CALL_DIR_ANSWER;
7382 
7383 	if (!bp->length) {
7384 		plci->B1_resource = 0x5;
7385 		adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7386 		add_p(plci, CAI, "\x01\x05");
7387 		return 0;
7388 	}
7389 
7390 	dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7391 	if (bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7392 	if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7393 	{
7394 		bp_parms[6].length = 0;
7395 		if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7396 		{
7397 			dbug(1, dprintf("b-form.!"));
7398 			return _WRONG_MESSAGE_FORMAT;
7399 		}
7400 	}
7401 	else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7402 	{
7403 		dbug(1, dprintf("b-form.!"));
7404 		return _WRONG_MESSAGE_FORMAT;
7405 	}
7406 
7407 	if (bp_parms[6].length)
7408 	{
7409 		if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7410 		{
7411 			return _WRONG_MESSAGE_FORMAT;
7412 		}
7413 		switch (GET_WORD(global_config[0].info))
7414 		{
7415 		case 1:
7416 			plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7417 			break;
7418 		case 2:
7419 			plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7420 			break;
7421 		}
7422 	}
7423 	dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7424 
7425 
7426 	if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7427 	    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7428 	{
7429 		plci->B1_resource = add_b1_facilities(plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7430 		adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7431 		cai[1] = plci->B1_resource;
7432 		cai[2] = 0;
7433 		cai[3] = 0;
7434 		cai[4] = 0;
7435 		PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7436 		for (i = 0; i < bp_parms[3].length; i++)
7437 			cai[7 + i] = bp_parms[3].info[1 + i];
7438 		cai[0] = 6 + bp_parms[3].length;
7439 		add_p(plci, CAI, cai);
7440 		return 0;
7441 	}
7442 
7443 
7444 	if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7445 	    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7446 	{
7447 		plci->B1_resource = add_b1_facilities(plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7448 		adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7449 		cai[1] = plci->B1_resource;
7450 		cai[2] = 0;
7451 		cai[3] = 0;
7452 		cai[4] = 0;
7453 		PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7454 		cai[0] = 6;
7455 		add_p(plci, CAI, cai);
7456 		return 0;
7457 	}
7458 
7459 
7460 	if ((GET_WORD(bp_parms[0].info) >= 32)
7461 	    || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7462 		&& ((GET_WORD(bp_parms[0].info) != 3)
7463 		    || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7464 		    || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7465 	{
7466 		return _B1_NOT_SUPPORTED;
7467 	}
7468 	plci->B1_resource = add_b1_facilities(plci, resource[GET_WORD(bp_parms[0].info)],
7469 					      (word)(b1_facilities & ~B1_FACILITY_VOICE));
7470 	adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7471 	cai[0] = 6;
7472 	cai[1] = plci->B1_resource;
7473 	for (i = 2; i < sizeof(cai); i++) cai[i] = 0;
7474 
7475 	if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7476 	    || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7477 	    || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7478 	{ /* B1 - modem */
7479 		for (i = 0; i < 7; i++) mdm_cfg[i].length = 0;
7480 
7481 		if (bp_parms[3].length)
7482 		{
7483 			if (api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwww", mdm_cfg))
7484 			{
7485 				return (_WRONG_MESSAGE_FORMAT);
7486 			}
7487 
7488 			cai[2] = 0; /* Bit rate for adaptation */
7489 
7490 			dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7491 
7492 			PUT_WORD(&cai[13], 0);                          /* Min Tx speed */
7493 			PUT_WORD(&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7494 			PUT_WORD(&cai[17], 0);                          /* Min Rx speed */
7495 			PUT_WORD(&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7496 
7497 			cai[3] = 0; /* Async framing parameters */
7498 			switch (GET_WORD(mdm_cfg[2].info))
7499 			{       /* Parity     */
7500 			case 1: /* odd parity */
7501 				cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7502 				dbug(1, dprintf("MDM: odd parity"));
7503 				break;
7504 
7505 			case 2: /* even parity */
7506 				cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7507 				dbug(1, dprintf("MDM: even parity"));
7508 				break;
7509 
7510 			default:
7511 				dbug(1, dprintf("MDM: no parity"));
7512 				break;
7513 			}
7514 
7515 			switch (GET_WORD(mdm_cfg[3].info))
7516 			{       /* stop bits   */
7517 			case 1: /* 2 stop bits */
7518 				cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7519 				dbug(1, dprintf("MDM: 2 stop bits"));
7520 				break;
7521 
7522 			default:
7523 				dbug(1, dprintf("MDM: 1 stop bit"));
7524 				break;
7525 			}
7526 
7527 			switch (GET_WORD(mdm_cfg[1].info))
7528 			{     /* char length */
7529 			case 5:
7530 				cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7531 				dbug(1, dprintf("MDM: 5 bits"));
7532 				break;
7533 
7534 			case 6:
7535 				cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7536 				dbug(1, dprintf("MDM: 6 bits"));
7537 				break;
7538 
7539 			case 7:
7540 				cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7541 				dbug(1, dprintf("MDM: 7 bits"));
7542 				break;
7543 
7544 			default:
7545 				dbug(1, dprintf("MDM: 8 bits"));
7546 				break;
7547 			}
7548 
7549 			cai[7] = 0; /* Line taking options */
7550 			cai[8] = 0; /* Modulation negotiation options */
7551 			cai[9] = 0; /* Modulation options */
7552 
7553 			if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7554 			{
7555 				cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7556 				dbug(1, dprintf("MDM: Reverse direction"));
7557 			}
7558 
7559 			if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7560 			{
7561 				cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7562 				dbug(1, dprintf("MDM: Disable retrain"));
7563 			}
7564 
7565 			if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7566 			{
7567 				cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7568 				dbug(1, dprintf("MDM: Disable ring tone"));
7569 			}
7570 
7571 			if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7572 			{
7573 				cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7574 				dbug(1, dprintf("MDM: 1800 guard tone"));
7575 			}
7576 			else if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_550)
7577 			{
7578 				cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7579 				dbug(1, dprintf("MDM: 550 guard tone"));
7580 			}
7581 
7582 			if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7583 			{
7584 				cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7585 				dbug(1, dprintf("MDM: V100"));
7586 			}
7587 			else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7588 			{
7589 				cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7590 				dbug(1, dprintf("MDM: IN CLASS"));
7591 			}
7592 			else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7593 			{
7594 				cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7595 				dbug(1, dprintf("MDM: DISABLED"));
7596 			}
7597 			cai[0] = 20;
7598 
7599 			if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7600 			    && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7601 			{
7602 				plci->requested_options |= 1L << PRIVATE_V18;
7603 			}
7604 			if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7605 				plci->requested_options |= 1L << PRIVATE_VOWN;
7606 
7607 			if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
7608 			    & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7609 			{
7610 				if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwws", mdm_cfg))
7611 				{
7612 					i = 27;
7613 					if (mdm_cfg[6].length >= 4)
7614 					{
7615 						d = GET_DWORD(&mdm_cfg[6].info[1]);
7616 						cai[7] |= (byte) d;          /* line taking options */
7617 						cai[9] |= (byte)(d >> 8);    /* modulation options */
7618 						cai[++i] = (byte)(d >> 16);  /* vown modulation options */
7619 						cai[++i] = (byte)(d >> 24);
7620 						if (mdm_cfg[6].length >= 8)
7621 						{
7622 							d = GET_DWORD(&mdm_cfg[6].info[5]);
7623 							cai[10] |= (byte) d;        /* disabled modulations mask */
7624 							cai[11] |= (byte)(d >> 8);
7625 							if (mdm_cfg[6].length >= 12)
7626 							{
7627 								d = GET_DWORD(&mdm_cfg[6].info[9]);
7628 								cai[12] = (byte) d;          /* enabled modulations mask */
7629 								cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */
7630 								cai[++i] = (byte)(d >> 16);
7631 								cai[++i] = (byte)(d >> 24);
7632 								cai[++i] = 0;
7633 								if (mdm_cfg[6].length >= 14)
7634 								{
7635 									w = GET_WORD(&mdm_cfg[6].info[13]);
7636 									if (w != 0)
7637 										PUT_WORD(&cai[13], w);  /* min tx speed */
7638 									if (mdm_cfg[6].length >= 16)
7639 									{
7640 										w = GET_WORD(&mdm_cfg[6].info[15]);
7641 										if (w != 0)
7642 											PUT_WORD(&cai[15], w);  /* max tx speed */
7643 										if (mdm_cfg[6].length >= 18)
7644 										{
7645 											w = GET_WORD(&mdm_cfg[6].info[17]);
7646 											if (w != 0)
7647 												PUT_WORD(&cai[17], w);  /* min rx speed */
7648 											if (mdm_cfg[6].length >= 20)
7649 											{
7650 												w = GET_WORD(&mdm_cfg[6].info[19]);
7651 												if (w != 0)
7652 													PUT_WORD(&cai[19], w);  /* max rx speed */
7653 												if (mdm_cfg[6].length >= 22)
7654 												{
7655 													w = GET_WORD(&mdm_cfg[6].info[21]);
7656 													cai[23] = (byte)(-((short) w));  /* transmit level */
7657 													if (mdm_cfg[6].length >= 24)
7658 													{
7659 														w = GET_WORD(&mdm_cfg[6].info[23]);
7660 														cai[22] |= (byte) w;        /* info options mask */
7661 														cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */
7662 													}
7663 												}
7664 											}
7665 										}
7666 									}
7667 								}
7668 							}
7669 						}
7670 					}
7671 					cai[27] = i - 27;
7672 					i++;
7673 					if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwwss", mdm_cfg))
7674 					{
7675 						if (!api_parse(&mdm_cfg[7].info[1], (word)mdm_cfg[7].length, "sss", mdm_cfg_v18))
7676 						{
7677 							for (n = 0; n < 3; n++)
7678 							{
7679 								cai[i] = (byte)(mdm_cfg_v18[n].length);
7680 								for (j = 1; j < ((word)(cai[i] + 1)); j++)
7681 									cai[i + j] = mdm_cfg_v18[n].info[j];
7682 								i += cai[i] + 1;
7683 							}
7684 						}
7685 					}
7686 					cai[0] = (byte)(i - 1);
7687 				}
7688 			}
7689 
7690 		}
7691 	}
7692 	if (GET_WORD(bp_parms[0].info) == 2 ||                         /* V.110 async */
7693 	    GET_WORD(bp_parms[0].info) == 3)                           /* V.110 sync */
7694 	{
7695 		if (bp_parms[3].length) {
7696 			dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms[3].info[1])));
7697 			switch (GET_WORD(&bp_parms[3].info[1])) {                 /* Rate */
7698 			case 0:
7699 			case 56000:
7700 				if (GET_WORD(bp_parms[0].info) == 3) {                  /* V.110 sync 56k */
7701 					dbug(1, dprintf("56k sync HSCX"));
7702 					cai[1] = 8;
7703 					cai[2] = 0;
7704 					cai[3] = 0;
7705 				}
7706 				else if (GET_WORD(bp_parms[0].info) == 2) {
7707 					dbug(1, dprintf("56k async DSP"));
7708 					cai[2] = 9;
7709 				}
7710 				break;
7711 			case 50:     cai[2] = 1;  break;
7712 			case 75:     cai[2] = 1;  break;
7713 			case 110:    cai[2] = 1;  break;
7714 			case 150:    cai[2] = 1;  break;
7715 			case 200:    cai[2] = 1;  break;
7716 			case 300:    cai[2] = 1;  break;
7717 			case 600:    cai[2] = 1;  break;
7718 			case 1200:   cai[2] = 2;  break;
7719 			case 2400:   cai[2] = 3;  break;
7720 			case 4800:   cai[2] = 4;  break;
7721 			case 7200:   cai[2] = 10; break;
7722 			case 9600:   cai[2] = 5;  break;
7723 			case 12000:  cai[2] = 13; break;
7724 			case 24000:  cai[2] = 0;  break;
7725 			case 14400:  cai[2] = 11; break;
7726 			case 19200:  cai[2] = 6;  break;
7727 			case 28800:  cai[2] = 12; break;
7728 			case 38400:  cai[2] = 7;  break;
7729 			case 48000:  cai[2] = 8;  break;
7730 			case 76:     cai[2] = 15; break;  /* 75/1200     */
7731 			case 1201:   cai[2] = 14; break;  /* 1200/75     */
7732 			case 56001:  cai[2] = 9;  break;  /* V.110 56000 */
7733 
7734 			default:
7735 				return _B1_PARM_NOT_SUPPORTED;
7736 			}
7737 			cai[3] = 0;
7738 			if (cai[1] == 13)                                        /* v.110 async */
7739 			{
7740 				if (bp_parms[3].length >= 8)
7741 				{
7742 					switch (GET_WORD(&bp_parms[3].info[3]))
7743 					{       /* char length */
7744 					case 5:
7745 						cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7746 						break;
7747 					case 6:
7748 						cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7749 						break;
7750 					case 7:
7751 						cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7752 						break;
7753 					}
7754 					switch (GET_WORD(&bp_parms[3].info[5]))
7755 					{       /* Parity     */
7756 					case 1: /* odd parity */
7757 						cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7758 						break;
7759 					case 2: /* even parity */
7760 						cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7761 						break;
7762 					}
7763 					switch (GET_WORD(&bp_parms[3].info[7]))
7764 					{       /* stop bits   */
7765 					case 1: /* 2 stop bits */
7766 						cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7767 						break;
7768 					}
7769 				}
7770 			}
7771 		}
7772 		else if (cai[1] == 8 || GET_WORD(bp_parms[0].info) == 3) {
7773 			dbug(1, dprintf("V.110 default 56k sync"));
7774 			cai[1] = 8;
7775 			cai[2] = 0;
7776 			cai[3] = 0;
7777 		}
7778 		else {
7779 			dbug(1, dprintf("V.110 default 9600 async"));
7780 			cai[2] = 5;
7781 		}
7782 	}
7783 	PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7784 	dbug(1, dprintf("CAI[%d]=%x,%x,%x,%x,%x,%x", cai[0], cai[1], cai[2], cai[3], cai[4], cai[5], cai[6]));
7785 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7786 
7787 	add_p(plci, CAI, cai);
7788 	return 0;
7789 }
7790 
7791 /*------------------------------------------------------------------*/
7792 /* put parameter for b2 and B3  protocol in the parameter buffer    */
7793 /*------------------------------------------------------------------*/
7794 
add_b23(PLCI * plci,API_PARSE * bp)7795 static word add_b23(PLCI *plci, API_PARSE *bp)
7796 {
7797 	word i, fax_control_bits;
7798 	byte pos, len;
7799 	byte SAPI = 0x40;  /* default SAPI 16 for x.31 */
7800 	API_PARSE bp_parms[8];
7801 	API_PARSE *b1_config;
7802 	API_PARSE *b2_config;
7803 	API_PARSE b2_config_parms[8];
7804 	API_PARSE *b3_config;
7805 	API_PARSE b3_config_parms[6];
7806 	API_PARSE global_config[2];
7807 
7808 	static byte llc[3] = {2,0,0};
7809 	static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7810 	static byte nlc[256];
7811 	static byte lli[12] = {1,1};
7812 
7813 	const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7814 	const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7815 
7816 	const byte llc3[] = {4,3,2,2,6,6,0};
7817 	const byte header[] = {0,2,3,3,0,0,0};
7818 
7819 	for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7820 	for (i = 0; i < 6; i++) b2_config_parms[i].length = 0;
7821 	for (i = 0; i < 5; i++) b3_config_parms[i].length = 0;
7822 
7823 	lli[0] = 1;
7824 	lli[1] = 1;
7825 	if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7826 		lli[1] |= 2;
7827 	if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7828 		lli[1] |= 4;
7829 
7830 	if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7831 		lli[1] |= 0x10;
7832 		if (plci->rx_dma_descriptor <= 0) {
7833 			plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
7834 			if (plci->rx_dma_descriptor >= 0)
7835 				plci->rx_dma_descriptor++;
7836 		}
7837 		if (plci->rx_dma_descriptor > 0) {
7838 			lli[0] = 6;
7839 			lli[1] |= 0x40;
7840 			lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7841 			lli[3] = (byte)plci->rx_dma_magic;
7842 			lli[4] = (byte)(plci->rx_dma_magic >>  8);
7843 			lli[5] = (byte)(plci->rx_dma_magic >> 16);
7844 			lli[6] = (byte)(plci->rx_dma_magic >> 24);
7845 		}
7846 	}
7847 
7848 	if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7849 		lli[1] |= 0x20;
7850 	}
7851 
7852 	dbug(1, dprintf("add_b23"));
7853 	api_save_msg(bp, "s", &plci->B_protocol);
7854 
7855 	if (!bp->length && plci->tel)
7856 	{
7857 		plci->adv_nl = true;
7858 		dbug(1, dprintf("Default adv.Nl"));
7859 		add_p(plci, LLI, lli);
7860 		plci->B2_prot = 1 /*XPARENT*/;
7861 		plci->B3_prot = 0 /*XPARENT*/;
7862 		llc[1] = 2;
7863 		llc[2] = 4;
7864 		add_p(plci, LLC, llc);
7865 		dlc[0] = 2;
7866 		PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7867 		add_p(plci, DLC, dlc);
7868 		return 0;
7869 	}
7870 
7871 	if (!bp->length) /*default*/
7872 	{
7873 		dbug(1, dprintf("ret default"));
7874 		add_p(plci, LLI, lli);
7875 		plci->B2_prot = 0 /*X.75   */;
7876 		plci->B3_prot = 0 /*XPARENT*/;
7877 		llc[1] = 1;
7878 		llc[2] = 4;
7879 		add_p(plci, LLC, llc);
7880 		dlc[0] = 2;
7881 		PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7882 		add_p(plci, DLC, dlc);
7883 		return 0;
7884 	}
7885 	dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7886 	if ((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT;
7887 
7888 	if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7889 	{
7890 		bp_parms[6].length = 0;
7891 		if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7892 		{
7893 			dbug(1, dprintf("b-form.!"));
7894 			return _WRONG_MESSAGE_FORMAT;
7895 		}
7896 	}
7897 	else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7898 	{
7899 		dbug(1, dprintf("b-form.!"));
7900 		return _WRONG_MESSAGE_FORMAT;
7901 	}
7902 
7903 	if (plci->tel == ADV_VOICE) /* transparent B on advanced voice */
7904 	{
7905 		if (GET_WORD(bp_parms[1].info) != 1
7906 		    || GET_WORD(bp_parms[2].info) != 0) return _B2_NOT_SUPPORTED;
7907 		plci->adv_nl = true;
7908 	}
7909 	else if (plci->tel) return _B2_NOT_SUPPORTED;
7910 
7911 
7912 	if ((GET_WORD(bp_parms[1].info) == B2_RTP)
7913 	    && (GET_WORD(bp_parms[2].info) == B3_RTP)
7914 	    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7915 	{
7916 		add_p(plci, LLI, lli);
7917 		plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
7918 		plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
7919 		llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
7920 		llc[2] = 4;
7921 		add_p(plci, LLC, llc);
7922 		dlc[0] = 2;
7923 		PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
7924 		dlc[3] = 3; /* Addr A */
7925 		dlc[4] = 1; /* Addr B */
7926 		dlc[5] = 7; /* modulo mode */
7927 		dlc[6] = 7; /* window size */
7928 		dlc[7] = 0; /* XID len Lo  */
7929 		dlc[8] = 0; /* XID len Hi  */
7930 		for (i = 0; i < bp_parms[4].length; i++)
7931 			dlc[9 + i] = bp_parms[4].info[1 + i];
7932 		dlc[0] = (byte)(8 + bp_parms[4].length);
7933 		add_p(plci, DLC, dlc);
7934 		for (i = 0; i < bp_parms[5].length; i++)
7935 			nlc[1 + i] = bp_parms[5].info[1 + i];
7936 		nlc[0] = (byte)(bp_parms[5].length);
7937 		add_p(plci, NLC, nlc);
7938 		return 0;
7939 	}
7940 
7941 
7942 
7943 	if ((GET_WORD(bp_parms[1].info) >= 32)
7944 	    || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
7945 		&& ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
7946 		    || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
7947 
7948 	{
7949 		return _B2_NOT_SUPPORTED;
7950 	}
7951 	if ((GET_WORD(bp_parms[2].info) >= 32)
7952 	    || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
7953 	{
7954 		return _B3_NOT_SUPPORTED;
7955 	}
7956 	if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
7957 	    && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7958 		|| (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7959 		|| (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
7960 	{
7961 		return (add_modem_b23(plci, bp_parms));
7962 	}
7963 
7964 	add_p(plci, LLI, lli);
7965 
7966 	plci->B2_prot = (byte)GET_WORD(bp_parms[1].info);
7967 	plci->B3_prot = (byte)GET_WORD(bp_parms[2].info);
7968 	if (plci->B2_prot == 12) SAPI = 0; /* default SAPI D-channel */
7969 
7970 	if (bp_parms[6].length)
7971 	{
7972 		if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7973 		{
7974 			return _WRONG_MESSAGE_FORMAT;
7975 		}
7976 		switch (GET_WORD(global_config[0].info))
7977 		{
7978 		case 1:
7979 			plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7980 			break;
7981 		case 2:
7982 			plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7983 			break;
7984 		}
7985 	}
7986 	dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7987 
7988 
7989 	if (plci->B2_prot == B2_PIAFS)
7990 		llc[1] = PIAFS_CRC;
7991 	else
7992 /* IMPLEMENT_PIAFS */
7993 	{
7994 		llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
7995 			llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
7996 	}
7997 	llc[2] = llc3[GET_WORD(bp_parms[2].info)];
7998 
7999 	add_p(plci, LLC, llc);
8000 
8001 	dlc[0] = 2;
8002 	PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8003 		 header[GET_WORD(bp_parms[2].info)]);
8004 
8005 	b1_config = &bp_parms[3];
8006 	nlc[0] = 0;
8007 	if (plci->B3_prot == 4
8008 	    || plci->B3_prot == 5)
8009 	{
8010 		for (i = 0; i < sizeof(T30_INFO); i++) nlc[i] = 0;
8011 		nlc[0] = sizeof(T30_INFO);
8012 		if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8013 			((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8014 		((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8015 		if (b1_config->length >= 2)
8016 		{
8017 			((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1]) / 2400);
8018 		}
8019 	}
8020 	b2_config = &bp_parms[4];
8021 
8022 
8023 	if (llc[1] == PIAFS_CRC)
8024 	{
8025 		if (plci->B3_prot != B3_TRANSPARENT)
8026 		{
8027 			return _B_STACK_NOT_SUPPORTED;
8028 		}
8029 		if (b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8030 			return _WRONG_MESSAGE_FORMAT;
8031 		}
8032 		PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8033 		dlc[3] = 0; /* Addr A */
8034 		dlc[4] = 0; /* Addr B */
8035 		dlc[5] = 0; /* modulo mode */
8036 		dlc[6] = 0; /* window size */
8037 		if (b2_config->length >= 7) {
8038 			dlc[7] = 7;
8039 			dlc[8] = 0;
8040 			dlc[9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8041 			dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8042 			dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8043 			dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8044 			dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8045 			dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8046 			dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8047 			dlc[0] = 15;
8048 			if (b2_config->length >= 8) { /* PIAFS control abilities */
8049 				dlc[7] = 10;
8050 				dlc[16] = 2; /* Length of PIAFS extension */
8051 				dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8052 				dlc[18] = b2_config_parms[4].info[0]; /* value */
8053 				dlc[0] = 18;
8054 			}
8055 		}
8056 		else /* default values, 64K, variable, no compression */
8057 		{
8058 			dlc[7] = 7;
8059 			dlc[8] = 0;
8060 			dlc[9] = 0x03; /* PIAFS protocol Speed configuration */
8061 			dlc[10] = 0x03; /* V.42bis P0 */
8062 			dlc[11] = 0;    /* V.42bis P0 */
8063 			dlc[12] = 0;    /* V.42bis P1 */
8064 			dlc[13] = 0;    /* V.42bis P1 */
8065 			dlc[14] = 0;    /* V.42bis P2 */
8066 			dlc[15] = 0;    /* V.42bis P2 */
8067 			dlc[0] = 15;
8068 		}
8069 		add_p(plci, DLC, dlc);
8070 	}
8071 	else
8072 
8073 		if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8074 		{
8075 			if (plci->B3_prot != B3_TRANSPARENT)
8076 				return _B_STACK_NOT_SUPPORTED;
8077 
8078 			dlc[0] = 6;
8079 			PUT_WORD(&dlc[1], GET_WORD(&dlc[1]) + 2);
8080 			dlc[3] = 0x08;
8081 			dlc[4] = 0x01;
8082 			dlc[5] = 127;
8083 			dlc[6] = 7;
8084 			if (b2_config->length != 0)
8085 			{
8086 				if ((llc[1] == V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8087 					return _WRONG_MESSAGE_FORMAT;
8088 				}
8089 				dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8090 				dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8091 				if (b2_config->info[3] != 128)
8092 				{
8093 					dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8094 					return _B2_PARM_NOT_SUPPORTED;
8095 				}
8096 				dlc[5] = (byte)(b2_config->info[3] - 1);
8097 				dlc[6] = b2_config->info[4];
8098 				if (llc[1] == V120_V42BIS) {
8099 					if (b2_config->length >= 10) {
8100 						dlc[7] = 6;
8101 						dlc[8] = 0;
8102 						dlc[9] = b2_config_parms[4].info[0];
8103 						dlc[10] = b2_config_parms[4].info[1];
8104 						dlc[11] = b2_config_parms[5].info[0];
8105 						dlc[12] = b2_config_parms[5].info[1];
8106 						dlc[13] = b2_config_parms[6].info[0];
8107 						dlc[14] = b2_config_parms[6].info[1];
8108 						dlc[0] = 14;
8109 						dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8110 						dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8111 						dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8112 					}
8113 					else {
8114 						dlc[6] = 14;
8115 					}
8116 				}
8117 			}
8118 		}
8119 		else
8120 		{
8121 			if (b2_config->length)
8122 			{
8123 				dbug(1, dprintf("B2-Config"));
8124 				if (llc[1] == X75_V42BIS) {
8125 					if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8126 					{
8127 						return _WRONG_MESSAGE_FORMAT;
8128 					}
8129 				}
8130 				else {
8131 					if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8132 					{
8133 						return _WRONG_MESSAGE_FORMAT;
8134 					}
8135 				}
8136 				/* if B2 Protocol is LAPD, b2_config structure is different */
8137 				if (llc[1] == 6)
8138 				{
8139 					dlc[0] = 4;
8140 					if (b2_config->length >= 1) dlc[2] = b2_config->info[1];      /* TEI */
8141 					else dlc[2] = 0x01;
8142 					if ((b2_config->length >= 2) && (plci->B2_prot == 12))
8143 					{
8144 						SAPI = b2_config->info[2];    /* SAPI */
8145 					}
8146 					dlc[1] = SAPI;
8147 					if ((b2_config->length >= 3) && (b2_config->info[3] == 128))
8148 					{
8149 						dlc[3] = 127;      /* Mode */
8150 					}
8151 					else
8152 					{
8153 						dlc[3] = 7;        /* Mode */
8154 					}
8155 
8156 					if (b2_config->length >= 4) dlc[4] = b2_config->info[4];      /* Window */
8157 					else dlc[4] = 1;
8158 					dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8159 					if (b2_config->length > 5) return _B2_PARM_NOT_SUPPORTED;
8160 				}
8161 				else
8162 				{
8163 					dlc[0] = (byte)(b2_config_parms[4].length + 6);
8164 					dlc[3] = b2_config->info[1];
8165 					dlc[4] = b2_config->info[2];
8166 					if (b2_config->info[3] != 8 && b2_config->info[3] != 128) {
8167 						dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8168 						return _B2_PARM_NOT_SUPPORTED;
8169 					}
8170 
8171 					dlc[5] = (byte)(b2_config->info[3] - 1);
8172 					dlc[6] = b2_config->info[4];
8173 					if (dlc[6] > dlc[5]) {
8174 						dbug(1, dprintf("2D-dlc= %x %x %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4], dlc[5], dlc[6]));
8175 						return _B2_PARM_NOT_SUPPORTED;
8176 					}
8177 
8178 					if (llc[1] == X75_V42BIS) {
8179 						if (b2_config->length >= 10) {
8180 							dlc[7] = 6;
8181 							dlc[8] = 0;
8182 							dlc[9] = b2_config_parms[4].info[0];
8183 							dlc[10] = b2_config_parms[4].info[1];
8184 							dlc[11] = b2_config_parms[5].info[0];
8185 							dlc[12] = b2_config_parms[5].info[1];
8186 							dlc[13] = b2_config_parms[6].info[0];
8187 							dlc[14] = b2_config_parms[6].info[1];
8188 							dlc[0] = 14;
8189 							dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8190 							dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8191 							dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8192 						}
8193 						else {
8194 							dlc[6] = 14;
8195 						}
8196 
8197 					}
8198 					else {
8199 						PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8200 						for (i = 0; i < b2_config_parms[4].length; i++)
8201 							dlc[11 + i] = b2_config_parms[4].info[1 + i];
8202 					}
8203 				}
8204 			}
8205 		}
8206 	add_p(plci, DLC, dlc);
8207 
8208 	b3_config = &bp_parms[5];
8209 	if (b3_config->length)
8210 	{
8211 		if (plci->B3_prot == 4
8212 		    || plci->B3_prot == 5)
8213 		{
8214 			if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8215 			{
8216 				return _WRONG_MESSAGE_FORMAT;
8217 			}
8218 			i = GET_WORD((byte *)(b3_config_parms[0].info));
8219 			((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8220 								    ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8221 			((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8222 			fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8223 			if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8224 				fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8225 			if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8226 			{
8227 
8228 				if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8229 				    & (1L << PRIVATE_FAX_PAPER_FORMATS))
8230 				{
8231 					((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8232 						T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8233 						T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8234 				}
8235 
8236 				((T30_INFO *)&nlc[1])->recording_properties =
8237 					T30_RECORDING_WIDTH_ISO_A3 |
8238 					(T30_RECORDING_LENGTH_UNLIMITED << 2) |
8239 					(T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8240 			}
8241 			if (plci->B3_prot == 5)
8242 			{
8243 				if (i & 0x0002) /* Accept incoming fax-polling requests */
8244 					fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8245 				if (i & 0x2000) /* Do not use MR compression */
8246 					fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8247 				if (i & 0x4000) /* Do not use MMR compression */
8248 					fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8249 				if (i & 0x8000) /* Do not use ECM */
8250 					fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8251 				if (plci->fax_connect_info_length != 0)
8252 				{
8253 					((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8254 					((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8255 					((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8256 					fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8257 						(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8258 				}
8259 			}
8260 			/* copy station id to NLC */
8261 			for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
8262 			{
8263 				if (i < b3_config_parms[2].length)
8264 				{
8265 					((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1 + i];
8266 				}
8267 				else
8268 				{
8269 					((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8270 				}
8271 			}
8272 			((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8273 			/* copy head line to NLC */
8274 			if (b3_config_parms[3].length)
8275 			{
8276 
8277 				pos = (byte)(fax_head_line_time(&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8278 				if (pos != 0)
8279 				{
8280 					if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8281 						pos = 0;
8282 					else
8283 					{
8284 						nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8285 						nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8286 						len = (byte)b3_config_parms[2].length;
8287 						if (len > 20)
8288 							len = 20;
8289 						if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8290 						{
8291 							for (i = 0; i < len; i++)
8292 								nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1 + i];
8293 							nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8294 							nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8295 						}
8296 					}
8297 				}
8298 
8299 				len = (byte)b3_config_parms[3].length;
8300 				if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8301 					len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8302 				((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8303 				nlc[0] += (byte)(pos + len);
8304 				for (i = 0; i < len; i++)
8305 					nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] =  ((byte *)b3_config_parms[3].info)[1 + i];
8306 			} else
8307 				((T30_INFO *)&nlc[1])->head_line_len = 0;
8308 
8309 			plci->nsf_control_bits = 0;
8310 			if (plci->B3_prot == 5)
8311 			{
8312 				if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8313 				    && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8314 				{
8315 					plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8316 				}
8317 				if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8318 				    && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8319 				{
8320 					plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8321 				}
8322 				if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8323 				    & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8324 				{
8325 					if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8326 					    & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8327 					{
8328 						fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8329 						if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8330 							fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8331 					}
8332 					len = nlc[0];
8333 					pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8334 					if (pos < plci->fax_connect_info_length)
8335 					{
8336 						for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8337 							nlc[++len] = plci->fax_connect_info_buffer[pos++];
8338 					}
8339 					else
8340 						nlc[++len] = 0;
8341 					if (pos < plci->fax_connect_info_length)
8342 					{
8343 						for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8344 							nlc[++len] = plci->fax_connect_info_buffer[pos++];
8345 					}
8346 					else
8347 						nlc[++len] = 0;
8348 					if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8349 					    & (1L << PRIVATE_FAX_NONSTANDARD))
8350 					{
8351 						if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8352 						{
8353 							if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos + 1] >= 2))
8354 								plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos + 2]);
8355 							for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8356 								nlc[++len] = plci->fax_connect_info_buffer[pos++];
8357 						}
8358 						else
8359 						{
8360 							if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8361 							{
8362 								dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8363 								nlc[++len] = 0;
8364 							}
8365 							else
8366 							{
8367 								if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8368 									plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8369 								nlc[++len] = (byte)(b3_config_parms[4].length);
8370 								for (i = 0; i < b3_config_parms[4].length; i++)
8371 									nlc[++len] = b3_config_parms[4].info[1 + i];
8372 							}
8373 						}
8374 					}
8375 					nlc[0] = len;
8376 					if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8377 					    && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8378 					{
8379 						((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8380 					}
8381 				}
8382 			}
8383 
8384 			PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8385 			len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8386 			for (i = 0; i < len; i++)
8387 				plci->fax_connect_info_buffer[i] = nlc[1 + i];
8388 			((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8389 			i += ((T30_INFO *)&nlc[1])->head_line_len;
8390 			while (i < nlc[0])
8391 				plci->fax_connect_info_buffer[len++] = nlc[++i];
8392 			plci->fax_connect_info_length = len;
8393 		}
8394 		else
8395 		{
8396 			nlc[0] = 14;
8397 			if (b3_config->length != 16)
8398 				return _B3_PARM_NOT_SUPPORTED;
8399 			for (i = 0; i < 12; i++) nlc[1 + i] = b3_config->info[1 + i];
8400 			if (GET_WORD(&b3_config->info[13]) != 8 && GET_WORD(&b3_config->info[13]) != 128)
8401 				return _B3_PARM_NOT_SUPPORTED;
8402 			nlc[13] = b3_config->info[13];
8403 			if (GET_WORD(&b3_config->info[15]) >= nlc[13])
8404 				return _B3_PARM_NOT_SUPPORTED;
8405 			nlc[14] = b3_config->info[15];
8406 		}
8407 	}
8408 	else
8409 	{
8410 		if (plci->B3_prot == 4
8411 		    || plci->B3_prot == 5 /*T.30 - FAX*/) return _B3_PARM_NOT_SUPPORTED;
8412 	}
8413 	add_p(plci, NLC, nlc);
8414 	return 0;
8415 }
8416 
8417 /*----------------------------------------------------------------*/
8418 /*      make the same as add_b23, but only for the modem related  */
8419 /*      L2 and L3 B-Chan protocol.                                */
8420 /*                                                                */
8421 /*      Enabled L2 and L3 Configurations:                         */
8422 /*        If L1 == Modem all negotiation                          */
8423 /*          only L2 == Modem with full negotiation is allowed     */
8424 /*        If L1 == Modem async or sync                            */
8425 /*          only L2 == Transparent is allowed                     */
8426 /*        L3 == Modem or L3 == Transparent are allowed            */
8427 /*      B2 Configuration for modem:                               */
8428 /*          word : enable/disable compression, bitoptions         */
8429 /*      B3 Configuration for modem:                               */
8430 /*          empty                                                 */
8431 /*----------------------------------------------------------------*/
add_modem_b23(PLCI * plci,API_PARSE * bp_parms)8432 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms)
8433 {
8434 	static byte lli[12] = {1,1};
8435 	static byte llc[3] = {2,0,0};
8436 	static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8437 	API_PARSE mdm_config[2];
8438 	word i;
8439 	word b2_config = 0;
8440 
8441 	for (i = 0; i < 2; i++) mdm_config[i].length = 0;
8442 	for (i = 0; i < sizeof(dlc); i++) dlc[i] = 0;
8443 
8444 	if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8445 	     && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8446 	    || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8447 		&& (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8448 	{
8449 		return (_B_STACK_NOT_SUPPORTED);
8450 	}
8451 	if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8452 	    && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8453 	{
8454 		return (_B_STACK_NOT_SUPPORTED);
8455 	}
8456 
8457 	plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8458 	plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8459 
8460 	if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8461 	{
8462 		if (api_parse(&bp_parms[4].info[1],
8463 			      (word)bp_parms[4].length, "w",
8464 			      mdm_config))
8465 		{
8466 			return (_WRONG_MESSAGE_FORMAT);
8467 		}
8468 		b2_config = GET_WORD(mdm_config[0].info);
8469 	}
8470 
8471 	/* OK, L2 is modem */
8472 
8473 	lli[0] = 1;
8474 	lli[1] = 1;
8475 	if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8476 		lli[1] |= 2;
8477 	if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8478 		lli[1] |= 4;
8479 
8480 	if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8481 		lli[1] |= 0x10;
8482 		if (plci->rx_dma_descriptor <= 0) {
8483 			plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
8484 			if (plci->rx_dma_descriptor >= 0)
8485 				plci->rx_dma_descriptor++;
8486 		}
8487 		if (plci->rx_dma_descriptor > 0) {
8488 			lli[1] |= 0x40;
8489 			lli[0] = 6;
8490 			lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8491 			lli[3] = (byte)plci->rx_dma_magic;
8492 			lli[4] = (byte)(plci->rx_dma_magic >>  8);
8493 			lli[5] = (byte)(plci->rx_dma_magic >> 16);
8494 			lli[6] = (byte)(plci->rx_dma_magic >> 24);
8495 		}
8496 	}
8497 
8498 	if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8499 		lli[1] |= 0x20;
8500 	}
8501 
8502 	llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8503 		/*V42*/ 10 : /*V42_IN*/ 9;
8504 	llc[2] = 4;                      /* pass L3 always transparent */
8505 	add_p(plci, LLI, lli);
8506 	add_p(plci, LLC, llc);
8507 	i =  1;
8508 	PUT_WORD(&dlc[i], plci->appl->MaxDataLength);
8509 	i += 2;
8510 	if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8511 	{
8512 		if (bp_parms[4].length)
8513 		{
8514 			dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8515 			dlc[i++] = 3; /* Addr A */
8516 			dlc[i++] = 1; /* Addr B */
8517 			dlc[i++] = 7; /* modulo mode */
8518 			dlc[i++] = 7; /* window size */
8519 			dlc[i++] = 0; /* XID len Lo  */
8520 			dlc[i++] = 0; /* XID len Hi  */
8521 
8522 			if (b2_config & MDM_B2_DISABLE_V42bis)
8523 			{
8524 				dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8525 			}
8526 			if (b2_config & MDM_B2_DISABLE_MNP)
8527 			{
8528 				dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8529 			}
8530 			if (b2_config & MDM_B2_DISABLE_TRANS)
8531 			{
8532 				dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8533 			}
8534 			if (b2_config & MDM_B2_DISABLE_V42)
8535 			{
8536 				dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8537 			}
8538 			if (b2_config & MDM_B2_DISABLE_COMP)
8539 			{
8540 				dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8541 			}
8542 			i++;
8543 		}
8544 	}
8545 	else
8546 	{
8547 		dlc[i++] = 3; /* Addr A */
8548 		dlc[i++] = 1; /* Addr B */
8549 		dlc[i++] = 7; /* modulo mode */
8550 		dlc[i++] = 7; /* window size */
8551 		dlc[i++] = 0; /* XID len Lo  */
8552 		dlc[i++] = 0; /* XID len Hi  */
8553 		dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8554 			DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8555 			DLC_MODEMPROT_DISABLE_V42_DETECT |
8556 			DLC_MODEMPROT_DISABLE_COMPRESSION;
8557 	}
8558 	dlc[0] = (byte)(i - 1);
8559 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8560 	add_p(plci, DLC, dlc);
8561 	return (0);
8562 }
8563 
8564 
8565 /*------------------------------------------------------------------*/
8566 /* send a request for the signaling entity                          */
8567 /*------------------------------------------------------------------*/
8568 
sig_req(PLCI * plci,byte req,byte Id)8569 static void sig_req(PLCI *plci, byte req, byte Id)
8570 {
8571 	if (!plci) return;
8572 	if (plci->adapter->adapter_disabled) return;
8573 	dbug(1, dprintf("sig_req(%x)", req));
8574 	if (req == REMOVE)
8575 		plci->sig_remove_id = plci->Sig.Id;
8576 	if (plci->req_in == plci->req_in_start) {
8577 		plci->req_in += 2;
8578 		plci->RBuffer[plci->req_in++] = 0;
8579 	}
8580 	PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8581 	plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
8582 	plci->RBuffer[plci->req_in++] = req;  /* request */
8583 	plci->RBuffer[plci->req_in++] = 0;    /* channel */
8584 	plci->req_in_start = plci->req_in;
8585 }
8586 
8587 /*------------------------------------------------------------------*/
8588 /* send a request for the network layer entity                      */
8589 /*------------------------------------------------------------------*/
8590 
nl_req_ncci(PLCI * plci,byte req,byte ncci)8591 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8592 {
8593 	if (!plci) return;
8594 	if (plci->adapter->adapter_disabled) return;
8595 	dbug(1, dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8596 	if (req == REMOVE)
8597 	{
8598 		plci->nl_remove_id = plci->NL.Id;
8599 		ncci_remove(plci, 0, (byte)(ncci != 0));
8600 		ncci = 0;
8601 	}
8602 	if (plci->req_in == plci->req_in_start) {
8603 		plci->req_in += 2;
8604 		plci->RBuffer[plci->req_in++] = 0;
8605 	}
8606 	PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8607 	plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */
8608 	plci->RBuffer[plci->req_in++] = req;  /* request */
8609 	plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
8610 	plci->req_in_start = plci->req_in;
8611 }
8612 
send_req(PLCI * plci)8613 static void send_req(PLCI *plci)
8614 {
8615 	ENTITY *e;
8616 	word l;
8617 /*  word i; */
8618 
8619 	if (!plci) return;
8620 	if (plci->adapter->adapter_disabled) return;
8621 	channel_xmit_xon(plci);
8622 
8623 	/* if nothing to do, return */
8624 	if (plci->req_in == plci->req_out) return;
8625 	dbug(1, dprintf("send_req(in=%d,out=%d)", plci->req_in, plci->req_out));
8626 
8627 	if (plci->nl_req || plci->sig_req) return;
8628 
8629 	l = GET_WORD(&plci->RBuffer[plci->req_out]);
8630 	plci->req_out += 2;
8631 	plci->XData[0].P = &plci->RBuffer[plci->req_out];
8632 	plci->req_out += l;
8633 	if (plci->RBuffer[plci->req_out] == 1)
8634 	{
8635 		e = &plci->NL;
8636 		plci->req_out++;
8637 		e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8638 		e->ReqCh = plci->RBuffer[plci->req_out++];
8639 		if (!(e->Id & 0x1f))
8640 		{
8641 			e->Id = NL_ID;
8642 			plci->RBuffer[plci->req_out - 4] = CAI;
8643 			plci->RBuffer[plci->req_out - 3] = 1;
8644 			plci->RBuffer[plci->req_out - 2] = (plci->Sig.Id == 0xff) ? 0 : plci->Sig.Id;
8645 			plci->RBuffer[plci->req_out - 1] = 0;
8646 			l += 3;
8647 			plci->nl_global_req = plci->nl_req;
8648 		}
8649 		dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8650 	}
8651 	else
8652 	{
8653 		e = &plci->Sig;
8654 		if (plci->RBuffer[plci->req_out])
8655 			e->Id = plci->RBuffer[plci->req_out];
8656 		plci->req_out++;
8657 		e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8658 		e->ReqCh = plci->RBuffer[plci->req_out++];
8659 		if (!(e->Id & 0x1f))
8660 			plci->sig_global_req = plci->sig_req;
8661 		dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8662 	}
8663 	plci->XData[0].PLength = l;
8664 	e->X = plci->XData;
8665 	plci->adapter->request(e);
8666 	dbug(1, dprintf("send_ok"));
8667 }
8668 
send_data(PLCI * plci)8669 static void send_data(PLCI *plci)
8670 {
8671 	DIVA_CAPI_ADAPTER *a;
8672 	DATA_B3_DESC *data;
8673 	NCCI   *ncci_ptr;
8674 	word ncci;
8675 
8676 	if (!plci->nl_req && plci->ncci_ring_list)
8677 	{
8678 		a = plci->adapter;
8679 		ncci = plci->ncci_ring_list;
8680 		do
8681 		{
8682 			ncci = a->ncci_next[ncci];
8683 			ncci_ptr = &(a->ncci[ncci]);
8684 			if (!(a->ncci_ch[ncci]
8685 			      && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8686 			{
8687 				if (ncci_ptr->data_pending)
8688 				{
8689 					if ((a->ncci_state[ncci] == CONNECTED)
8690 					    || (a->ncci_state[ncci] == INC_ACT_PENDING)
8691 					    || (plci->send_disc == ncci))
8692 					{
8693 						data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8694 						if ((plci->B2_prot == B2_V120_ASYNC)
8695 						    || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8696 						    || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8697 						{
8698 							plci->NData[1].P = TransmitBufferGet(plci->appl, data->P);
8699 							plci->NData[1].PLength = data->Length;
8700 							if (data->Flags & 0x10)
8701 								plci->NData[0].P = v120_break_header;
8702 							else
8703 								plci->NData[0].P = v120_default_header;
8704 							plci->NData[0].PLength = 1;
8705 							plci->NL.XNum = 2;
8706 							plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8707 						}
8708 						else
8709 						{
8710 							plci->NData[0].P = TransmitBufferGet(plci->appl, data->P);
8711 							plci->NData[0].PLength = data->Length;
8712 							if (data->Flags & 0x10)
8713 								plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8714 
8715 							else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8716 								plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8717 
8718 							else
8719 								plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8720 						}
8721 						plci->NL.X = plci->NData;
8722 						plci->NL.ReqCh = a->ncci_ch[ncci];
8723 						dbug(1, dprintf("%x:DREQ(%x:%x)", a->Id, plci->NL.Id, plci->NL.Req));
8724 						plci->data_sent = true;
8725 						plci->data_sent_ptr = data->P;
8726 						a->request(&plci->NL);
8727 					}
8728 					else {
8729 						cleanup_ncci_data(plci, ncci);
8730 					}
8731 				}
8732 				else if (plci->send_disc == ncci)
8733 				{
8734 					/* dprintf("N_DISC"); */
8735 					plci->NData[0].PLength = 0;
8736 					plci->NL.ReqCh = a->ncci_ch[ncci];
8737 					plci->NL.Req = plci->nl_req = N_DISC;
8738 					a->request(&plci->NL);
8739 					plci->command = _DISCONNECT_B3_R;
8740 					plci->send_disc = 0;
8741 				}
8742 			}
8743 		} while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8744 		plci->ncci_ring_list = ncci;
8745 	}
8746 }
8747 
listen_check(DIVA_CAPI_ADAPTER * a)8748 static void listen_check(DIVA_CAPI_ADAPTER *a)
8749 {
8750 	word i, j;
8751 	PLCI *plci;
8752 	byte activnotifiedcalls = 0;
8753 
8754 	dbug(1, dprintf("listen_check(%d,%d)", a->listen_active, a->max_listen));
8755 	if (!remove_started && !a->adapter_disabled)
8756 	{
8757 		for (i = 0; i < a->max_plci; i++)
8758 		{
8759 			plci = &(a->plci[i]);
8760 			if (plci->notifiedcall) activnotifiedcalls++;
8761 		}
8762 		dbug(1, dprintf("listen_check(%d)", activnotifiedcalls));
8763 
8764 		for (i = a->listen_active; i < ((word)(a->max_listen + activnotifiedcalls)); i++) {
8765 			if ((j = get_plci(a))) {
8766 				a->listen_active++;
8767 				plci = &a->plci[j - 1];
8768 				plci->State = LISTENING;
8769 
8770 				add_p(plci, OAD, "\x01\xfd");
8771 
8772 				add_p(plci, KEY, "\x04\x43\x41\x32\x30");
8773 
8774 				add_p(plci, CAI, "\x01\xc0");
8775 				add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
8776 				add_p(plci, LLI, "\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */
8777 				add_p(plci, SHIFT | 6, NULL);
8778 				add_p(plci, SIN, "\x02\x00\x00");
8779 				plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
8780 				sig_req(plci, ASSIGN, DSIG_ID);
8781 				send_req(plci);
8782 			}
8783 		}
8784 	}
8785 }
8786 
8787 /*------------------------------------------------------------------*/
8788 /* functions for all parameters sent in INDs                        */
8789 /*------------------------------------------------------------------*/
8790 
IndParse(PLCI * plci,const word * parms_id,byte ** parms,byte multiIEsize)8791 static void IndParse(PLCI *plci, const word *parms_id, byte **parms, byte multiIEsize)
8792 {
8793 	word ploc;            /* points to current location within packet */
8794 	byte w;
8795 	byte wlen;
8796 	byte codeset, lock;
8797 	byte *in;
8798 	word i;
8799 	word code;
8800 	word mIEindex = 0;
8801 	ploc = 0;
8802 	codeset = 0;
8803 	lock = 0;
8804 
8805 	in = plci->Sig.RBuffer->P;
8806 	for (i = 0; i < parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
8807 	{                            /* element but parms array is larger      */
8808 		parms[i] = (byte *)"";
8809 	}
8810 	for (i = 0; i < multiIEsize; i++)
8811 	{
8812 		parms[i] = (byte *)"";
8813 	}
8814 
8815 	while (ploc < plci->Sig.RBuffer->length - 1) {
8816 
8817 		/* read information element id and length                   */
8818 		w = in[ploc];
8819 
8820 		if (w & 0x80) {
8821 /*    w &=0xf0; removed, cannot detect congestion levels */
8822 /*    upper 4 bit masked with w==SHIFT now               */
8823 			wlen = 0;
8824 		}
8825 		else {
8826 			wlen = (byte)(in[ploc + 1] + 1);
8827 		}
8828 		/* check if length valid (not exceeding end of packet)      */
8829 		if ((ploc + wlen) > 270) return;
8830 		if (lock & 0x80) lock &= 0x7f;
8831 		else codeset = lock;
8832 
8833 		if ((w & 0xf0) == SHIFT) {
8834 			codeset = in[ploc];
8835 			if (!(codeset & 0x08)) lock = (byte)(codeset & 7);
8836 			codeset &= 7;
8837 			lock |= 0x80;
8838 		}
8839 		else {
8840 			if (w == ESC && wlen >= 3) code = in[ploc + 2] | 0x800;
8841 			else code = w;
8842 			code |= (codeset << 8);
8843 
8844 			for (i = 1; i < parms_id[0] + 1 && parms_id[i] != code; i++);
8845 
8846 			if (i < parms_id[0] + 1) {
8847 				if (!multiIEsize) { /* with multiIEs use next field index,          */
8848 					mIEindex = i - 1;    /* with normal IEs use same index like parms_id */
8849 				}
8850 
8851 				parms[mIEindex] = &in[ploc + 1];
8852 				dbug(1, dprintf("mIE[%d]=0x%x", *parms[mIEindex], in[ploc]));
8853 				if (parms_id[i] == OAD
8854 				    || parms_id[i] == CONN_NR
8855 				    || parms_id[i] == CAD) {
8856 					if (in[ploc + 2] & 0x80) {
8857 						in[ploc + 0] = (byte)(in[ploc + 1] + 1);
8858 						in[ploc + 1] = (byte)(in[ploc + 2] & 0x7f);
8859 						in[ploc + 2] = 0x80;
8860 						parms[mIEindex] = &in[ploc];
8861 					}
8862 				}
8863 				mIEindex++;       /* effects multiIEs only */
8864 			}
8865 		}
8866 
8867 		ploc += (wlen + 1);
8868 	}
8869 	return;
8870 }
8871 
8872 /*------------------------------------------------------------------*/
8873 /* try to match a cip from received BC and HLC                      */
8874 /*------------------------------------------------------------------*/
8875 
ie_compare(byte * ie1,byte * ie2)8876 static byte ie_compare(byte *ie1, byte *ie2)
8877 {
8878 	word i;
8879 	if (!ie1 || !ie2) return false;
8880 	if (!ie1[0]) return false;
8881 	for (i = 0; i < (word)(ie1[0] + 1); i++) if (ie1[i] != ie2[i]) return false;
8882 	return true;
8883 }
8884 
find_cip(DIVA_CAPI_ADAPTER * a,byte * bc,byte * hlc)8885 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
8886 {
8887 	word i;
8888 	word j;
8889 
8890 	for (i = 9; i && !ie_compare(bc, cip_bc[i][a->u_law]); i--);
8891 
8892 	for (j = 16; j < 29 &&
8893 		     (!ie_compare(bc, cip_bc[j][a->u_law]) || !ie_compare(hlc, cip_hlc[j])); j++);
8894 	if (j == 29) return i;
8895 	return j;
8896 }
8897 
8898 
AddInfo(byte ** add_i,byte ** fty_i,byte * esc_chi,byte * facility)8899 static byte AddInfo(byte **add_i,
8900 		    byte **fty_i,
8901 		    byte *esc_chi,
8902 		    byte *facility)
8903 {
8904 	byte i;
8905 	byte j;
8906 	byte k;
8907 	byte flen;
8908 	byte len = 0;
8909 	/* facility is a nested structure */
8910 	/* FTY can be more than once      */
8911 
8912 	if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
8913 	{
8914 		add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
8915 	}
8916 
8917 	else
8918 	{
8919 		add_i[0] = (byte *)"";
8920 	}
8921 	if (!fty_i[0][0])
8922 	{
8923 		add_i[3] = (byte *)"";
8924 	}
8925 	else
8926 	{    /* facility array found  */
8927 		for (i = 0, j = 1; i < MAX_MULTI_IE && fty_i[i][0]; i++)
8928 		{
8929 			dbug(1, dprintf("AddIFac[%d]", fty_i[i][0]));
8930 			len += fty_i[i][0];
8931 			len += 2;
8932 			flen = fty_i[i][0];
8933 			facility[j++] = 0x1c; /* copy fac IE */
8934 			for (k = 0; k <= flen; k++, j++)
8935 			{
8936 				facility[j] = fty_i[i][k];
8937 /*      dbug(1, dprintf("%x ",facility[j])); */
8938 			}
8939 		}
8940 		facility[0] = len;
8941 		add_i[3] = facility;
8942 	}
8943 /*  dbug(1, dprintf("FacArrLen=%d ",len)); */
8944 	len = add_i[0][0] + add_i[1][0] + add_i[2][0] + add_i[3][0];
8945 	len += 4;                          /* calculate length of all */
8946 	return (len);
8947 }
8948 
8949 /*------------------------------------------------------------------*/
8950 /* voice and codec features                                         */
8951 /*------------------------------------------------------------------*/
8952 
SetVoiceChannel(PLCI * plci,byte * chi,DIVA_CAPI_ADAPTER * a)8953 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
8954 {
8955 	byte voice_chi[] = "\x02\x18\x01";
8956 	byte channel;
8957 
8958 	channel = chi[chi[0]] & 0x3;
8959 	dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel));
8960 	voice_chi[2] = (channel) ? channel : 1;
8961 	add_p(plci, FTY, "\x02\x01\x07");             /* B On, default on 1 */
8962 	add_p(plci, ESC, voice_chi);                  /* Channel */
8963 	sig_req(plci, TEL_CTRL, 0);
8964 	send_req(plci);
8965 	if (a->AdvSignalPLCI)
8966 	{
8967 		adv_voice_write_coefs(a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
8968 	}
8969 }
8970 
VoiceChannelOff(PLCI * plci)8971 static void VoiceChannelOff(PLCI *plci)
8972 {
8973 	dbug(1, dprintf("ExtDevOFF"));
8974 	add_p(plci, FTY, "\x02\x01\x08");             /* B Off */
8975 	sig_req(plci, TEL_CTRL, 0);
8976 	send_req(plci);
8977 	if (plci->adapter->AdvSignalPLCI)
8978 	{
8979 		adv_voice_clear_config(plci->adapter->AdvSignalPLCI);
8980 	}
8981 }
8982 
8983 
AdvCodecSupport(DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,byte hook_listen)8984 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
8985 			    byte hook_listen)
8986 {
8987 	word j;
8988 	PLCI *splci;
8989 
8990 	/* check if hardware supports handset with hook states (adv.codec) */
8991 	/* or if just a on board codec is supported                        */
8992 	/* the advanced codec plci is just for internal use                */
8993 
8994 	/* diva Pro with on-board codec:                                   */
8995 	if (a->profile.Global_Options & HANDSET)
8996 	{
8997 		/* new call, but hook states are already signalled */
8998 		if (a->AdvCodecFLAG)
8999 		{
9000 			if (a->AdvSignalAppl != appl || a->AdvSignalPLCI)
9001 			{
9002 				dbug(1, dprintf("AdvSigPlci=0x%x", a->AdvSignalPLCI));
9003 				return 0x2001; /* codec in use by another application */
9004 			}
9005 			if (plci != NULL)
9006 			{
9007 				a->AdvSignalPLCI = plci;
9008 				plci->tel = ADV_VOICE;
9009 			}
9010 			return 0;                      /* adv codec still used */
9011 		}
9012 		if ((j = get_plci(a)))
9013 		{
9014 			splci = &a->plci[j - 1];
9015 			splci->tel = CODEC_PERMANENT;
9016 			/* hook_listen indicates if a facility_req with handset/hook support */
9017 			/* was sent. Otherwise if just a call on an external device was made */
9018 			/* the codec will be used but the hook info will be discarded (just  */
9019 			/* the external controller is in use                                 */
9020 			if (hook_listen) splci->State = ADVANCED_VOICE_SIG;
9021 			else
9022 			{
9023 				splci->State = ADVANCED_VOICE_NOSIG;
9024 				if (plci)
9025 				{
9026 					plci->spoofed_msg = SPOOFING_REQUIRED;
9027 				}
9028 				/* indicate D-ch connect if  */
9029 			}                                        /* codec is connected OK     */
9030 			if (plci != NULL)
9031 			{
9032 				a->AdvSignalPLCI = plci;
9033 				plci->tel = ADV_VOICE;
9034 			}
9035 			a->AdvSignalAppl = appl;
9036 			a->AdvCodecFLAG = true;
9037 			a->AdvCodecPLCI = splci;
9038 			add_p(splci, CAI, "\x01\x15");
9039 			add_p(splci, LLI, "\x01\x00");
9040 			add_p(splci, ESC, "\x02\x18\x00");
9041 			add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9042 			splci->internal_command = PERM_COD_ASSIGN;
9043 			dbug(1, dprintf("Codec Assign"));
9044 			sig_req(splci, ASSIGN, DSIG_ID);
9045 			send_req(splci);
9046 		}
9047 		else
9048 		{
9049 			return 0x2001; /* wrong state, no more plcis */
9050 		}
9051 	}
9052 	else if (a->profile.Global_Options & ON_BOARD_CODEC)
9053 	{
9054 		if (hook_listen) return 0x300B;               /* Facility not supported */
9055 		/* no hook with SCOM      */
9056 		if (plci != NULL) plci->tel = CODEC;
9057 		dbug(1, dprintf("S/SCOM codec"));
9058 		/* first time we use the scom-s codec we must shut down the internal   */
9059 		/* handset application of the card. This can be done by an assign with */
9060 		/* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9061 		if (!a->scom_appl_disable) {
9062 			if ((j = get_plci(a))) {
9063 				splci = &a->plci[j - 1];
9064 				add_p(splci, CAI, "\x01\x80");
9065 				add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9066 				sig_req(splci, ASSIGN, 0xC0);  /* 0xc0 is the TEL_ID */
9067 				send_req(splci);
9068 				a->scom_appl_disable = true;
9069 			}
9070 			else{
9071 				return 0x2001; /* wrong state, no more plcis */
9072 			}
9073 		}
9074 	}
9075 	else return 0x300B;               /* Facility not supported */
9076 
9077 	return 0;
9078 }
9079 
9080 
CodecIdCheck(DIVA_CAPI_ADAPTER * a,PLCI * plci)9081 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9082 {
9083 
9084 	dbug(1, dprintf("CodecIdCheck"));
9085 
9086 	if (a->AdvSignalPLCI == plci)
9087 	{
9088 		dbug(1, dprintf("PLCI owns codec"));
9089 		VoiceChannelOff(a->AdvCodecPLCI);
9090 		if (a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9091 		{
9092 			dbug(1, dprintf("remove temp codec PLCI"));
9093 			plci_remove(a->AdvCodecPLCI);
9094 			a->AdvCodecFLAG  = 0;
9095 			a->AdvCodecPLCI  = NULL;
9096 			a->AdvSignalAppl = NULL;
9097 		}
9098 		a->AdvSignalPLCI = NULL;
9099 	}
9100 }
9101 
9102 /* -------------------------------------------------------------------
9103    Ask for physical address of card on PCI bus
9104    ------------------------------------------------------------------- */
diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER * a,IDI_SYNC_REQ * preq)9105 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *a,
9106 				       IDI_SYNC_REQ *preq) {
9107 	a->sdram_bar = 0;
9108 	if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9109 		ENTITY *e = (ENTITY *)preq;
9110 
9111 		e->user[0] = a->Id - 1;
9112 		preq->xdi_sdram_bar.info.bar    = 0;
9113 		preq->xdi_sdram_bar.Req         = 0;
9114 		preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9115 
9116 		(*(a->request))(e);
9117 
9118 		a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9119 		dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9120 	}
9121 }
9122 
9123 /* -------------------------------------------------------------------
9124    Ask XDI about extended features
9125    ------------------------------------------------------------------- */
diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER * a)9126 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a) {
9127 	IDI_SYNC_REQ *preq;
9128 	char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
9129 
9130 	char features[4];
9131 	preq = (IDI_SYNC_REQ *)&buffer[0];
9132 
9133 	if (!diva_xdi_extended_features) {
9134 		ENTITY *e = (ENTITY *)preq;
9135 		diva_xdi_extended_features |= 0x80000000;
9136 
9137 		e->user[0] = a->Id - 1;
9138 		preq->xdi_extended_features.Req = 0;
9139 		preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9140 		preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9141 		preq->xdi_extended_features.info.features = &features[0];
9142 
9143 		(*(a->request))(e);
9144 
9145 		if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9146 			/*
9147 			  Check features located in the byte '0'
9148 			*/
9149 			if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9150 				diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9151 			}
9152 			if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9153 				diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9154 				dbug(1, dprintf("XDI provides RxDMA"));
9155 			}
9156 			if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9157 				diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9158 			}
9159 			if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9160 				diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9161 				dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9162 			}
9163 
9164 		}
9165 	}
9166 
9167 	diva_ask_for_xdi_sdram_bar(a, preq);
9168 }
9169 
9170 /*------------------------------------------------------------------*/
9171 /* automatic law                                                    */
9172 /*------------------------------------------------------------------*/
9173 /* called from OS specific part after init time to get the Law              */
9174 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
AutomaticLaw(DIVA_CAPI_ADAPTER * a)9175 void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9176 {
9177 	word j;
9178 	PLCI *splci;
9179 
9180 	if (a->automatic_law) {
9181 		return;
9182 	}
9183 	if ((j = get_plci(a))) {
9184 		diva_get_extended_adapter_features(a);
9185 		splci = &a->plci[j - 1];
9186 		a->automatic_lawPLCI = splci;
9187 		a->automatic_law = 1;
9188 		add_p(splci, CAI, "\x01\x80");
9189 		add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9190 		splci->internal_command = USELAW_REQ;
9191 		splci->command = 0;
9192 		splci->number = 0;
9193 		sig_req(splci, ASSIGN, DSIG_ID);
9194 		send_req(splci);
9195 	}
9196 }
9197 
9198 /* called from OS specific part if an application sends an Capi20Release */
CapiRelease(word Id)9199 word CapiRelease(word Id)
9200 {
9201 	word i, j, appls_found;
9202 	PLCI *plci;
9203 	APPL   *this;
9204 	DIVA_CAPI_ADAPTER *a;
9205 
9206 	if (!Id)
9207 	{
9208 		dbug(0, dprintf("A: CapiRelease(Id==0)"));
9209 		return (_WRONG_APPL_ID);
9210 	}
9211 
9212 	this = &application[Id - 1];               /* get application pointer */
9213 
9214 	for (i = 0, appls_found = 0; i < max_appl; i++)
9215 	{
9216 		if (application[i].Id)       /* an application has been found        */
9217 		{
9218 			appls_found++;
9219 		}
9220 	}
9221 
9222 	for (i = 0; i < max_adapter; i++)             /* scan all adapters...    */
9223 	{
9224 		a = &adapter[i];
9225 		if (a->request)
9226 		{
9227 			a->Info_Mask[Id - 1] = 0;
9228 			a->CIP_Mask[Id - 1] = 0;
9229 			a->Notification_Mask[Id - 1] = 0;
9230 			a->codec_listen[Id - 1] = NULL;
9231 			a->requested_options_table[Id - 1] = 0;
9232 			for (j = 0; j < a->max_plci; j++)           /* and all PLCIs connected */
9233 			{                                      /* with this application   */
9234 				plci = &a->plci[j];
9235 				if (plci->Id)                         /* if plci owns no application */
9236 				{                                    /* it may be not jet connected */
9237 					if (plci->State == INC_CON_PENDING
9238 					    || plci->State == INC_CON_ALERT)
9239 					{
9240 						if (test_bit(Id - 1, plci->c_ind_mask_table))
9241 						{
9242 							__clear_bit(Id - 1, plci->c_ind_mask_table);
9243 							if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9244 							{
9245 								sig_req(plci, HANGUP, 0);
9246 								send_req(plci);
9247 								plci->State = OUTG_DIS_PENDING;
9248 							}
9249 						}
9250 					}
9251 					if (test_bit(Id - 1, plci->c_ind_mask_table))
9252 					{
9253 						__clear_bit(Id - 1, plci->c_ind_mask_table);
9254 						if (bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9255 						{
9256 							if (!plci->appl)
9257 							{
9258 								plci_remove(plci);
9259 								plci->State = IDLE;
9260 							}
9261 						}
9262 					}
9263 					if (plci->appl == this)
9264 					{
9265 						plci->appl = NULL;
9266 						plci_remove(plci);
9267 						plci->State = IDLE;
9268 					}
9269 				}
9270 			}
9271 			listen_check(a);
9272 
9273 			if (a->flag_dynamic_l1_down)
9274 			{
9275 				if (appls_found == 1)            /* last application does a capi release */
9276 				{
9277 					if ((j = get_plci(a)))
9278 					{
9279 						plci = &a->plci[j - 1];
9280 						plci->command = 0;
9281 						add_p(plci, OAD, "\x01\xfd");
9282 						add_p(plci, CAI, "\x01\x80");
9283 						add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9284 						add_p(plci, SHIFT | 6, NULL);
9285 						add_p(plci, SIN, "\x02\x00\x00");
9286 						plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9287 						sig_req(plci, ASSIGN, DSIG_ID);
9288 						add_p(plci, FTY, "\x02\xff\x06"); /* l1 down */
9289 						sig_req(plci, SIG_CTRL, 0);
9290 						send_req(plci);
9291 					}
9292 				}
9293 			}
9294 			if (a->AdvSignalAppl == this)
9295 			{
9296 				this->NullCREnable = false;
9297 				if (a->AdvCodecPLCI)
9298 				{
9299 					plci_remove(a->AdvCodecPLCI);
9300 					a->AdvCodecPLCI->tel = 0;
9301 					a->AdvCodecPLCI->adv_nl = 0;
9302 				}
9303 				a->AdvSignalAppl = NULL;
9304 				a->AdvSignalPLCI = NULL;
9305 				a->AdvCodecFLAG = 0;
9306 				a->AdvCodecPLCI = NULL;
9307 			}
9308 		}
9309 	}
9310 
9311 	this->Id = 0;
9312 
9313 	return GOOD;
9314 }
9315 
plci_remove_check(PLCI * plci)9316 static word plci_remove_check(PLCI *plci)
9317 {
9318 	if (!plci) return true;
9319 	if (!plci->NL.Id && bitmap_empty(plci->c_ind_mask_table, MAX_APPL))
9320 	{
9321 		if (plci->Sig.Id == 0xff)
9322 			plci->Sig.Id = 0;
9323 		if (!plci->Sig.Id)
9324 		{
9325 			dbug(1, dprintf("plci_remove_complete(%x)", plci->Id));
9326 			dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci->tel, plci->Sig.Id));
9327 			if (plci->Id)
9328 			{
9329 				CodecIdCheck(plci->adapter, plci);
9330 				clear_b1_config(plci);
9331 				ncci_remove(plci, 0, false);
9332 				plci_free_msg_in_queue(plci);
9333 				channel_flow_control_remove(plci);
9334 				plci->Id = 0;
9335 				plci->State = IDLE;
9336 				plci->channels = 0;
9337 				plci->appl = NULL;
9338 				plci->notifiedcall = 0;
9339 			}
9340 			listen_check(plci->adapter);
9341 			return true;
9342 		}
9343 	}
9344 	return false;
9345 }
9346 
9347 
9348 /*------------------------------------------------------------------*/
9349 
plci_nl_busy(PLCI * plci)9350 static byte plci_nl_busy(PLCI *plci)
9351 {
9352 	/* only applicable for non-multiplexed protocols */
9353 	return (plci->nl_req
9354 		|| (plci->ncci_ring_list
9355 		    && plci->adapter->ncci_ch[plci->ncci_ring_list]
9356 		    && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9357 }
9358 
9359 
9360 /*------------------------------------------------------------------*/
9361 /* DTMF facilities                                                  */
9362 /*------------------------------------------------------------------*/
9363 
9364 
9365 static struct
9366 {
9367 	byte send_mask;
9368 	byte listen_mask;
9369 	byte character;
9370 	byte code;
9371 } dtmf_digit_map[] =
9372 {
9373 	{ 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9374 	{ 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9375 	{ 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9376 	{ 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9377 	{ 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9378 	{ 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9379 	{ 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9380 	{ 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9381 	{ 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9382 	{ 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9383 	{ 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9384 	{ 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9385 	{ 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9386 	{ 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9387 	{ 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9388 	{ 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9389 	{ 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9390 	{ 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9391 	{ 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9392 	{ 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9393 
9394 	{ 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9395 	{ 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9396 	{ 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9397 	{ 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9398 	{ 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9399 	{ 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9400 	{ 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9401 	{ 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9402 	{ 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9403 	{ 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9404 	{ 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9405 	{ 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9406 	{ 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9407 	{ 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9408 	{ 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9409 	{ 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9410 	{ 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9411 	{ 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9412 	{ 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9413 	{ 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9414 	{ 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9415 	{ 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9416 	{ 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9417 	{ 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9418 	{ 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9419 	{ 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9420 	{ 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9421 	{ 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9422 	{ 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9423 	{ 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9424 	{ 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9425 	{ 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9426 	{ 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9427 	{ 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9428 	{ 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9429 	{ 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9430 	{ 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9431 	{ 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9432 	{ 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9433 	{ 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9434 	{ 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9435 	{ 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9436 	{ 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9437 	{ 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9438 	{ 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9439 	{ 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9440 	{ 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9441 	{ 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9442 	{ 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9443 	{ 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9444 	{ 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9445 	{ 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9446 
9447 };
9448 
9449 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9450 
9451 
dtmf_enable_receiver(PLCI * plci,byte enable_mask)9452 static void dtmf_enable_receiver(PLCI *plci, byte enable_mask)
9453 {
9454 	word min_digit_duration, min_gap_duration;
9455 
9456 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9457 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9458 			(char *)(FILE_), __LINE__, enable_mask));
9459 
9460 	if (enable_mask != 0)
9461 	{
9462 		min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9463 		min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9464 		plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9465 		PUT_WORD(&plci->internal_req_buffer[1], min_digit_duration);
9466 		PUT_WORD(&plci->internal_req_buffer[3], min_gap_duration);
9467 		plci->NData[0].PLength = 5;
9468 
9469 		PUT_WORD(&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9470 		plci->NData[0].PLength += 2;
9471 		capidtmf_recv_enable(&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9472 
9473 	}
9474 	else
9475 	{
9476 		plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9477 		plci->NData[0].PLength = 1;
9478 
9479 		capidtmf_recv_disable(&(plci->capidtmf_state));
9480 
9481 	}
9482 	plci->NData[0].P = plci->internal_req_buffer;
9483 	plci->NL.X = plci->NData;
9484 	plci->NL.ReqCh = 0;
9485 	plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9486 	plci->adapter->request(&plci->NL);
9487 }
9488 
9489 
dtmf_send_digits(PLCI * plci,byte * digit_buffer,word digit_count)9490 static void dtmf_send_digits(PLCI *plci, byte *digit_buffer, word digit_count)
9491 {
9492 	word w, i;
9493 
9494 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9495 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9496 			(char *)(FILE_), __LINE__, digit_count));
9497 
9498 	plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9499 	w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9500 	PUT_WORD(&plci->internal_req_buffer[1], w);
9501 	w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9502 	PUT_WORD(&plci->internal_req_buffer[3], w);
9503 	for (i = 0; i < digit_count; i++)
9504 	{
9505 		w = 0;
9506 		while ((w < DTMF_DIGIT_MAP_ENTRIES)
9507 		       && (digit_buffer[i] != dtmf_digit_map[w].character))
9508 		{
9509 			w++;
9510 		}
9511 		plci->internal_req_buffer[5 + i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9512 			dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9513 	}
9514 	plci->NData[0].PLength = 5 + digit_count;
9515 	plci->NData[0].P = plci->internal_req_buffer;
9516 	plci->NL.X = plci->NData;
9517 	plci->NL.ReqCh = 0;
9518 	plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9519 	plci->adapter->request(&plci->NL);
9520 }
9521 
9522 
dtmf_rec_clear_config(PLCI * plci)9523 static void dtmf_rec_clear_config(PLCI *plci)
9524 {
9525 
9526 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9527 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9528 			(char *)(FILE_), __LINE__));
9529 
9530 	plci->dtmf_rec_active = 0;
9531 	plci->dtmf_rec_pulse_ms = 0;
9532 	plci->dtmf_rec_pause_ms = 0;
9533 
9534 	capidtmf_init(&(plci->capidtmf_state), plci->adapter->u_law);
9535 
9536 }
9537 
9538 
dtmf_send_clear_config(PLCI * plci)9539 static void dtmf_send_clear_config(PLCI *plci)
9540 {
9541 
9542 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9543 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9544 			(char *)(FILE_), __LINE__));
9545 
9546 	plci->dtmf_send_requests = 0;
9547 	plci->dtmf_send_pulse_ms = 0;
9548 	plci->dtmf_send_pause_ms = 0;
9549 }
9550 
9551 
dtmf_prepare_switch(dword Id,PLCI * plci)9552 static void dtmf_prepare_switch(dword Id, PLCI *plci)
9553 {
9554 
9555 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9556 			UnMapId(Id), (char *)(FILE_), __LINE__));
9557 
9558 	while (plci->dtmf_send_requests != 0)
9559 		dtmf_confirmation(Id, plci);
9560 }
9561 
9562 
dtmf_save_config(dword Id,PLCI * plci,byte Rc)9563 static word dtmf_save_config(dword Id, PLCI *plci, byte Rc)
9564 {
9565 
9566 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9567 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9568 
9569 	return (GOOD);
9570 }
9571 
9572 
dtmf_restore_config(dword Id,PLCI * plci,byte Rc)9573 static word dtmf_restore_config(dword Id, PLCI *plci, byte Rc)
9574 {
9575 	word Info;
9576 
9577 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9578 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9579 
9580 	Info = GOOD;
9581 	if (plci->B1_facilities & B1_FACILITY_DTMFR)
9582 	{
9583 		switch (plci->adjust_b_state)
9584 		{
9585 		case ADJUST_B_RESTORE_DTMF_1:
9586 			plci->internal_command = plci->adjust_b_command;
9587 			if (plci_nl_busy(plci))
9588 			{
9589 				plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9590 				break;
9591 			}
9592 			dtmf_enable_receiver(plci, plci->dtmf_rec_active);
9593 			plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9594 			break;
9595 		case ADJUST_B_RESTORE_DTMF_2:
9596 			if ((Rc != OK) && (Rc != OK_FC))
9597 			{
9598 				dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9599 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9600 				Info = _WRONG_STATE;
9601 				break;
9602 			}
9603 			break;
9604 		}
9605 	}
9606 	return (Info);
9607 }
9608 
9609 
dtmf_command(dword Id,PLCI * plci,byte Rc)9610 static void dtmf_command(dword Id, PLCI *plci, byte Rc)
9611 {
9612 	word internal_command, Info;
9613 	byte mask;
9614 	byte result[4];
9615 
9616 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9617 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9618 			plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9619 			plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9620 
9621 	Info = GOOD;
9622 	result[0] = 2;
9623 	PUT_WORD(&result[1], DTMF_SUCCESS);
9624 	internal_command = plci->internal_command;
9625 	plci->internal_command = 0;
9626 	mask = 0x01;
9627 	switch (plci->dtmf_cmd)
9628 	{
9629 
9630 	case DTMF_LISTEN_TONE_START:
9631 		mask <<= 1; /* fall through */
9632 	case DTMF_LISTEN_MF_START:
9633 		mask <<= 1; /* fall through */
9634 
9635 	case DTMF_LISTEN_START:
9636 		switch (internal_command)
9637 		{
9638 		default:
9639 			adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9640 								  B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9641 			/* fall through */
9642 		case DTMF_COMMAND_1:
9643 			if (adjust_b_process(Id, plci, Rc) != GOOD)
9644 			{
9645 				dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9646 						UnMapId(Id), (char *)(FILE_), __LINE__));
9647 				Info = _FACILITY_NOT_SUPPORTED;
9648 				break;
9649 			}
9650 			if (plci->internal_command)
9651 				return;
9652 			/* fall through */
9653 		case DTMF_COMMAND_2:
9654 			if (plci_nl_busy(plci))
9655 			{
9656 				plci->internal_command = DTMF_COMMAND_2;
9657 				return;
9658 			}
9659 			plci->internal_command = DTMF_COMMAND_3;
9660 			dtmf_enable_receiver(plci, (byte)(plci->dtmf_rec_active | mask));
9661 			return;
9662 		case DTMF_COMMAND_3:
9663 			if ((Rc != OK) && (Rc != OK_FC))
9664 			{
9665 				dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9666 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9667 				Info = _FACILITY_NOT_SUPPORTED;
9668 				break;
9669 			}
9670 
9671 			plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9672 
9673 			plci->dtmf_rec_active |= mask;
9674 			break;
9675 		}
9676 		break;
9677 
9678 
9679 	case DTMF_LISTEN_TONE_STOP:
9680 		mask <<= 1; /* fall through */
9681 	case DTMF_LISTEN_MF_STOP:
9682 		mask <<= 1; /* fall through */
9683 
9684 	case DTMF_LISTEN_STOP:
9685 		switch (internal_command)
9686 		{
9687 		default:
9688 			plci->dtmf_rec_active &= ~mask;
9689 			if (plci->dtmf_rec_active)
9690 				break;
9691 /*
9692   case DTMF_COMMAND_1:
9693   if (plci->dtmf_rec_active)
9694   {
9695   if (plci_nl_busy (plci))
9696   {
9697   plci->internal_command = DTMF_COMMAND_1;
9698   return;
9699   }
9700   plci->dtmf_rec_active &= ~mask;
9701   plci->internal_command = DTMF_COMMAND_2;
9702   dtmf_enable_receiver (plci, false);
9703   return;
9704   }
9705   Rc = OK;
9706   case DTMF_COMMAND_2:
9707   if ((Rc != OK) && (Rc != OK_FC))
9708   {
9709   dbug (1, dprintf("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9710   UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9711   Info = _FACILITY_NOT_SUPPORTED;
9712   break;
9713   }
9714 */
9715 			adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
9716 								  ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9717 			/* fall through */
9718 		case DTMF_COMMAND_3:
9719 			if (adjust_b_process(Id, plci, Rc) != GOOD)
9720 			{
9721 				dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9722 						UnMapId(Id), (char *)(FILE_), __LINE__));
9723 				Info = _FACILITY_NOT_SUPPORTED;
9724 				break;
9725 			}
9726 			if (plci->internal_command)
9727 				return;
9728 			break;
9729 		}
9730 		break;
9731 
9732 
9733 	case DTMF_SEND_TONE:
9734 		mask <<= 1; /* fall through */
9735 	case DTMF_SEND_MF:
9736 		mask <<= 1; /* fall through */
9737 
9738 	case DTMF_DIGITS_SEND:
9739 		switch (internal_command)
9740 		{
9741 		default:
9742 			adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9743 								  ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9744 					   DTMF_COMMAND_1);
9745 			/* fall through */
9746 		case DTMF_COMMAND_1:
9747 			if (adjust_b_process(Id, plci, Rc) != GOOD)
9748 			{
9749 				dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9750 						UnMapId(Id), (char *)(FILE_), __LINE__));
9751 				Info = _FACILITY_NOT_SUPPORTED;
9752 				break;
9753 			}
9754 			if (plci->internal_command)
9755 				return;
9756 			/* fall through */
9757 		case DTMF_COMMAND_2:
9758 			if (plci_nl_busy(plci))
9759 			{
9760 				plci->internal_command = DTMF_COMMAND_2;
9761 				return;
9762 			}
9763 			plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9764 			plci->internal_command = DTMF_COMMAND_3;
9765 			dtmf_send_digits(plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9766 			return;
9767 		case DTMF_COMMAND_3:
9768 			if ((Rc != OK) && (Rc != OK_FC))
9769 			{
9770 				dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9771 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9772 				if (plci->dtmf_send_requests != 0)
9773 					(plci->dtmf_send_requests)--;
9774 				Info = _FACILITY_NOT_SUPPORTED;
9775 				break;
9776 			}
9777 			return;
9778 		}
9779 		break;
9780 	}
9781 	sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9782 	      "wws", Info, SELECTOR_DTMF, result);
9783 }
9784 
9785 
dtmf_request(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)9786 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
9787 {
9788 	word Info;
9789 	word i, j;
9790 	byte mask;
9791 	API_PARSE dtmf_parms[5];
9792 	byte result[40];
9793 
9794 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9795 			UnMapId(Id), (char *)(FILE_), __LINE__));
9796 
9797 	Info = GOOD;
9798 	result[0] = 2;
9799 	PUT_WORD(&result[1], DTMF_SUCCESS);
9800 	if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9801 	{
9802 		dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9803 				UnMapId(Id), (char *)(FILE_), __LINE__));
9804 		Info = _FACILITY_NOT_SUPPORTED;
9805 	}
9806 	else if (api_parse(&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9807 	{
9808 		dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9809 				UnMapId(Id), (char *)(FILE_), __LINE__));
9810 		Info = _WRONG_MESSAGE_FORMAT;
9811 	}
9812 
9813 	else if ((GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9814 		 || (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9815 	{
9816 		if (!((a->requested_options_table[appl->Id - 1])
9817 		      & (1L << PRIVATE_DTMF_TONE)))
9818 		{
9819 			dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9820 					UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9821 			PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9822 		}
9823 		else
9824 		{
9825 			for (i = 0; i < 32; i++)
9826 				result[4 + i] = 0;
9827 			if (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9828 			{
9829 				for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9830 				{
9831 					if (dtmf_digit_map[i].listen_mask != 0)
9832 						result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9833 				}
9834 			}
9835 			else
9836 			{
9837 				for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9838 				{
9839 					if (dtmf_digit_map[i].send_mask != 0)
9840 						result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9841 				}
9842 			}
9843 			result[0] = 3 + 32;
9844 			result[3] = 32;
9845 		}
9846 	}
9847 
9848 	else if (plci == NULL)
9849 	{
9850 		dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9851 				UnMapId(Id), (char *)(FILE_), __LINE__));
9852 		Info = _WRONG_IDENTIFIER;
9853 	}
9854 	else
9855 	{
9856 		if (!plci->State
9857 		    || !plci->NL.Id || plci->nl_remove_id)
9858 		{
9859 			dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9860 					UnMapId(Id), (char *)(FILE_), __LINE__));
9861 			Info = _WRONG_STATE;
9862 		}
9863 		else
9864 		{
9865 			plci->command = 0;
9866 			plci->dtmf_cmd = GET_WORD(dtmf_parms[0].info);
9867 			mask = 0x01;
9868 			switch (plci->dtmf_cmd)
9869 			{
9870 
9871 			case DTMF_LISTEN_TONE_START:
9872 			case DTMF_LISTEN_TONE_STOP:
9873 				mask <<= 1; /* fall through */
9874 			case DTMF_LISTEN_MF_START:
9875 			case DTMF_LISTEN_MF_STOP:
9876 				mask <<= 1;
9877 				if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
9878 				      & (1L << PRIVATE_DTMF_TONE)))
9879 				{
9880 					dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9881 							UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9882 					PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9883 					break;
9884 				}
9885 				/* fall through */
9886 
9887 			case DTMF_LISTEN_START:
9888 			case DTMF_LISTEN_STOP:
9889 				if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
9890 				    && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
9891 				{
9892 					dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9893 							UnMapId(Id), (char *)(FILE_), __LINE__));
9894 					Info = _FACILITY_NOT_SUPPORTED;
9895 					break;
9896 				}
9897 				if (mask & DTMF_LISTEN_ACTIVE_FLAG)
9898 				{
9899 					if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
9900 					{
9901 						plci->dtmf_rec_pulse_ms = 0;
9902 						plci->dtmf_rec_pause_ms = 0;
9903 					}
9904 					else
9905 					{
9906 						plci->dtmf_rec_pulse_ms = GET_WORD(dtmf_parms[1].info);
9907 						plci->dtmf_rec_pause_ms = GET_WORD(dtmf_parms[2].info);
9908 					}
9909 				}
9910 				start_internal_command(Id, plci, dtmf_command);
9911 				return (false);
9912 
9913 
9914 			case DTMF_SEND_TONE:
9915 				mask <<= 1; /* fall through */
9916 			case DTMF_SEND_MF:
9917 				mask <<= 1;
9918 				if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
9919 				      & (1L << PRIVATE_DTMF_TONE)))
9920 				{
9921 					dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9922 							UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9923 					PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9924 					break;
9925 				}
9926 				/* fall through */
9927 
9928 			case DTMF_DIGITS_SEND:
9929 				if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
9930 				{
9931 					dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9932 							UnMapId(Id), (char *)(FILE_), __LINE__));
9933 					Info = _WRONG_MESSAGE_FORMAT;
9934 					break;
9935 				}
9936 				if (mask & DTMF_LISTEN_ACTIVE_FLAG)
9937 				{
9938 					plci->dtmf_send_pulse_ms = GET_WORD(dtmf_parms[1].info);
9939 					plci->dtmf_send_pause_ms = GET_WORD(dtmf_parms[2].info);
9940 				}
9941 				i = 0;
9942 				j = 0;
9943 				while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
9944 				{
9945 					j = 0;
9946 					while ((j < DTMF_DIGIT_MAP_ENTRIES)
9947 					       && ((dtmf_parms[3].info[i + 1] != dtmf_digit_map[j].character)
9948 						   || ((dtmf_digit_map[j].send_mask & mask) == 0)))
9949 					{
9950 						j++;
9951 					}
9952 					i++;
9953 				}
9954 				if (j == DTMF_DIGIT_MAP_ENTRIES)
9955 				{
9956 					dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
9957 							UnMapId(Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
9958 					PUT_WORD(&result[1], DTMF_INCORRECT_DIGIT);
9959 					break;
9960 				}
9961 				if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
9962 				{
9963 					dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
9964 							UnMapId(Id), (char *)(FILE_), __LINE__));
9965 					Info = _WRONG_STATE;
9966 					break;
9967 				}
9968 				api_save_msg(dtmf_parms, "wwws", &plci->saved_msg);
9969 				start_internal_command(Id, plci, dtmf_command);
9970 				return (false);
9971 
9972 			default:
9973 				dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9974 						UnMapId(Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
9975 				PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9976 			}
9977 		}
9978 	}
9979 	sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
9980 	      "wws", Info, SELECTOR_DTMF, result);
9981 	return (false);
9982 }
9983 
9984 
dtmf_confirmation(dword Id,PLCI * plci)9985 static void dtmf_confirmation(dword Id, PLCI *plci)
9986 {
9987 	word i;
9988 	byte result[4];
9989 
9990 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
9991 			UnMapId(Id), (char *)(FILE_), __LINE__));
9992 
9993 	result[0] = 2;
9994 	PUT_WORD(&result[1], DTMF_SUCCESS);
9995 	if (plci->dtmf_send_requests != 0)
9996 	{
9997 		sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
9998 		      "wws", GOOD, SELECTOR_DTMF, result);
9999 		(plci->dtmf_send_requests)--;
10000 		for (i = 0; i < plci->dtmf_send_requests; i++)
10001 			plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i + 1];
10002 	}
10003 }
10004 
10005 
dtmf_indication(dword Id,PLCI * plci,byte * msg,word length)10006 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length)
10007 {
10008 	word i, j, n;
10009 
10010 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10011 			UnMapId(Id), (char *)(FILE_), __LINE__));
10012 
10013 	n = 0;
10014 	for (i = 1; i < length; i++)
10015 	{
10016 		j = 0;
10017 		while ((j < DTMF_DIGIT_MAP_ENTRIES)
10018 		       && ((msg[i] != dtmf_digit_map[j].code)
10019 			   || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10020 		{
10021 			j++;
10022 		}
10023 		if (j < DTMF_DIGIT_MAP_ENTRIES)
10024 		{
10025 
10026 			if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10027 			    && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10028 			    && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10029 			{
10030 				if (n + 1 == i)
10031 				{
10032 					for (i = length; i > n + 1; i--)
10033 						msg[i] = msg[i - 1];
10034 					length++;
10035 					i++;
10036 				}
10037 				msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10038 			}
10039 			plci->tone_last_indication_code = dtmf_digit_map[j].character;
10040 
10041 			msg[++n] = dtmf_digit_map[j].character;
10042 		}
10043 	}
10044 	if (n != 0)
10045 	{
10046 		msg[0] = (byte) n;
10047 		sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10048 	}
10049 }
10050 
10051 
10052 /*------------------------------------------------------------------*/
10053 /* DTMF parameters                                                  */
10054 /*------------------------------------------------------------------*/
10055 
dtmf_parameter_write(PLCI * plci)10056 static void dtmf_parameter_write(PLCI *plci)
10057 {
10058 	word i;
10059 	byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10060 
10061 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10062 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10063 			(char *)(FILE_), __LINE__));
10064 
10065 	parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10066 	parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10067 	for (i = 0; i < plci->dtmf_parameter_length; i++)
10068 		parameter_buffer[2 + i] = plci->dtmf_parameter_buffer[i];
10069 	add_p(plci, FTY, parameter_buffer);
10070 	sig_req(plci, TEL_CTRL, 0);
10071 	send_req(plci);
10072 }
10073 
10074 
dtmf_parameter_clear_config(PLCI * plci)10075 static void dtmf_parameter_clear_config(PLCI *plci)
10076 {
10077 
10078 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10079 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10080 			(char *)(FILE_), __LINE__));
10081 
10082 	plci->dtmf_parameter_length = 0;
10083 }
10084 
10085 
dtmf_parameter_prepare_switch(dword Id,PLCI * plci)10086 static void dtmf_parameter_prepare_switch(dword Id, PLCI *plci)
10087 {
10088 
10089 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10090 			UnMapId(Id), (char *)(FILE_), __LINE__));
10091 
10092 }
10093 
10094 
dtmf_parameter_save_config(dword Id,PLCI * plci,byte Rc)10095 static word dtmf_parameter_save_config(dword Id, PLCI *plci, byte Rc)
10096 {
10097 
10098 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10099 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10100 
10101 	return (GOOD);
10102 }
10103 
10104 
dtmf_parameter_restore_config(dword Id,PLCI * plci,byte Rc)10105 static word dtmf_parameter_restore_config(dword Id, PLCI *plci, byte Rc)
10106 {
10107 	word Info;
10108 
10109 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10110 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10111 
10112 	Info = GOOD;
10113 	if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10114 	    && (plci->dtmf_parameter_length != 0))
10115 	{
10116 		switch (plci->adjust_b_state)
10117 		{
10118 		case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10119 			plci->internal_command = plci->adjust_b_command;
10120 			if (plci->sig_req)
10121 			{
10122 				plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10123 				break;
10124 			}
10125 			dtmf_parameter_write(plci);
10126 			plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10127 			break;
10128 		case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10129 			if ((Rc != OK) && (Rc != OK_FC))
10130 			{
10131 				dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10132 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10133 				Info = _WRONG_STATE;
10134 				break;
10135 			}
10136 			break;
10137 		}
10138 	}
10139 	return (Info);
10140 }
10141 
10142 
10143 /*------------------------------------------------------------------*/
10144 /* Line interconnect facilities                                     */
10145 /*------------------------------------------------------------------*/
10146 
10147 
10148 LI_CONFIG   *li_config_table;
10149 word li_total_channels;
10150 
10151 
10152 /*------------------------------------------------------------------*/
10153 /* translate a CHI information element to a channel number          */
10154 /* returns 0xff - any channel                                       */
10155 /*         0xfe - chi wrong coding                                  */
10156 /*         0xfd - D-channel                                         */
10157 /*         0x00 - no channel                                        */
10158 /*         else channel number / PRI: timeslot                      */
10159 /* if channels is provided we accept more than one channel.         */
10160 /*------------------------------------------------------------------*/
10161 
chi_to_channel(byte * chi,dword * pchannelmap)10162 static byte chi_to_channel(byte *chi, dword *pchannelmap)
10163 {
10164 	int p;
10165 	int i;
10166 	dword map;
10167 	byte excl;
10168 	byte ofs;
10169 	byte ch;
10170 
10171 	if (pchannelmap) *pchannelmap = 0;
10172 	if (!chi[0]) return 0xff;
10173 	excl = 0;
10174 
10175 	if (chi[1] & 0x20) {
10176 		if (chi[0] == 1 && chi[1] == 0xac) return 0xfd; /* exclusive d-channel */
10177 		for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10178 		if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10179 		if ((chi[1] | 0xc8) != 0xe9) return 0xfe;
10180 		if (chi[1] & 0x08) excl = 0x40;
10181 
10182 		/* int. id present */
10183 		if (chi[1] & 0x40) {
10184 			p = i + 1;
10185 			for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10186 			if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10187 		}
10188 
10189 		/* coding standard, Number/Map, Channel Type */
10190 		p = i + 1;
10191 		for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10192 		if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10193 		if ((chi[p] | 0xd0) != 0xd3) return 0xfe;
10194 
10195 		/* Number/Map */
10196 		if (chi[p] & 0x10) {
10197 
10198 			/* map */
10199 			if ((chi[0] - p) == 4) ofs = 0;
10200 			else if ((chi[0] - p) == 3) ofs = 1;
10201 			else return 0xfe;
10202 			ch = 0;
10203 			map = 0;
10204 			for (i = 0; i < 4 && p < chi[0]; i++) {
10205 				p++;
10206 				ch += 8;
10207 				map <<= 8;
10208 				if (chi[p]) {
10209 					for (ch = 0; !(chi[p] & (1 << ch)); ch++);
10210 					map |= chi[p];
10211 				}
10212 			}
10213 			ch += ofs;
10214 			map <<= ofs;
10215 		}
10216 		else {
10217 
10218 			/* number */
10219 			p = i + 1;
10220 			ch = chi[p] & 0x3f;
10221 			if (pchannelmap) {
10222 				if ((byte)(chi[0] - p) > 30) return 0xfe;
10223 				map = 0;
10224 				for (i = p; i <= chi[0]; i++) {
10225 					if ((chi[i] & 0x7f) > 31) return 0xfe;
10226 					map |= (1L << (chi[i] & 0x7f));
10227 				}
10228 			}
10229 			else {
10230 				if (p != chi[0]) return 0xfe;
10231 				if (ch > 31) return 0xfe;
10232 				map = (1L << ch);
10233 			}
10234 			if (chi[p] & 0x40) return 0xfe;
10235 		}
10236 		if (pchannelmap) *pchannelmap = map;
10237 		else if (map != ((dword)(1L << ch))) return 0xfe;
10238 		return (byte)(excl | ch);
10239 	}
10240 	else {  /* not PRI */
10241 		for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10242 		if (i != chi[0] || !(chi[i] & 0x80)) return 0xfe;
10243 		if (chi[1] & 0x08) excl = 0x40;
10244 
10245 		switch (chi[1] | 0x98) {
10246 		case 0x98: return 0;
10247 		case 0x99:
10248 			if (pchannelmap) *pchannelmap = 2;
10249 			return excl | 1;
10250 		case 0x9a:
10251 			if (pchannelmap) *pchannelmap = 4;
10252 			return excl | 2;
10253 		case 0x9b: return 0xff;
10254 		case 0x9c: return 0xfd; /* d-ch */
10255 		default: return 0xfe;
10256 		}
10257 	}
10258 }
10259 
10260 
mixer_set_bchannel_id_esc(PLCI * plci,byte bchannel_id)10261 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id)
10262 {
10263 	DIVA_CAPI_ADAPTER *a;
10264 	PLCI *splci;
10265 	byte old_id;
10266 
10267 	a = plci->adapter;
10268 	old_id = plci->li_bchannel_id;
10269 	if (a->li_pri)
10270 	{
10271 		if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10272 			li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10273 		plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10274 		if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10275 			li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10276 	}
10277 	else
10278 	{
10279 		if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10280 		{
10281 			if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10282 				li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10283 			plci->li_bchannel_id = bchannel_id & 0x03;
10284 			if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10285 			{
10286 				splci = a->AdvSignalPLCI;
10287 				if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10288 				{
10289 					if ((splci->li_bchannel_id != 0)
10290 					    && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10291 					{
10292 						li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10293 					}
10294 					splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10295 					li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10296 					dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10297 							(dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10298 							(char *)(FILE_), __LINE__, splci->li_bchannel_id));
10299 				}
10300 			}
10301 			if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10302 				li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10303 		}
10304 	}
10305 	if ((old_id == 0) && (plci->li_bchannel_id != 0)
10306 	    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10307 	{
10308 		mixer_clear_config(plci);
10309 	}
10310 	dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10311 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10312 			(char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10313 }
10314 
10315 
mixer_set_bchannel_id(PLCI * plci,byte * chi)10316 static void mixer_set_bchannel_id(PLCI *plci, byte *chi)
10317 {
10318 	DIVA_CAPI_ADAPTER *a;
10319 	PLCI *splci;
10320 	byte ch, old_id;
10321 
10322 	a = plci->adapter;
10323 	old_id = plci->li_bchannel_id;
10324 	ch = chi_to_channel(chi, NULL);
10325 	if (!(ch & 0x80))
10326 	{
10327 		if (a->li_pri)
10328 		{
10329 			if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10330 				li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10331 			plci->li_bchannel_id = (ch & 0x1f) + 1;
10332 			if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10333 				li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10334 		}
10335 		else
10336 		{
10337 			if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10338 			{
10339 				if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10340 					li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10341 				plci->li_bchannel_id = ch & 0x1f;
10342 				if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10343 				{
10344 					splci = a->AdvSignalPLCI;
10345 					if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10346 					{
10347 						if ((splci->li_bchannel_id != 0)
10348 						    && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10349 						{
10350 							li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10351 						}
10352 						splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10353 						li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10354 						dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10355 								(dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10356 								(char *)(FILE_), __LINE__, splci->li_bchannel_id));
10357 					}
10358 				}
10359 				if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10360 					li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10361 			}
10362 		}
10363 	}
10364 	if ((old_id == 0) && (plci->li_bchannel_id != 0)
10365 	    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10366 	{
10367 		mixer_clear_config(plci);
10368 	}
10369 	dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10370 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10371 			(char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10372 }
10373 
10374 
10375 #define MIXER_MAX_DUMP_CHANNELS 34
10376 
mixer_calculate_coefs(DIVA_CAPI_ADAPTER * a)10377 static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER *a)
10378 {
10379 	word n, i, j;
10380 	char *p;
10381 	char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10382 
10383 	dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10384 			(dword)(UnMapController(a->Id)), (char *)(FILE_), __LINE__));
10385 
10386 	for (i = 0; i < li_total_channels; i++)
10387 	{
10388 		li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10389 		if (li_config_table[i].chflags != 0)
10390 			li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10391 		else
10392 		{
10393 			for (j = 0; j < li_total_channels; j++)
10394 			{
10395 				if (((li_config_table[i].flag_table[j]) != 0)
10396 				    || ((li_config_table[j].flag_table[i]) != 0))
10397 				{
10398 					li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10399 				}
10400 				if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10401 				    || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10402 				{
10403 					li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10404 				}
10405 			}
10406 		}
10407 	}
10408 	for (i = 0; i < li_total_channels; i++)
10409 	{
10410 		for (j = 0; j < li_total_channels; j++)
10411 		{
10412 			li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10413 			if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10414 				li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10415 		}
10416 	}
10417 	for (n = 0; n < li_total_channels; n++)
10418 	{
10419 		if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10420 		{
10421 			for (i = 0; i < li_total_channels; i++)
10422 			{
10423 				if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10424 				{
10425 					for (j = 0; j < li_total_channels; j++)
10426 					{
10427 						li_config_table[i].coef_table[j] |=
10428 							li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10429 					}
10430 				}
10431 			}
10432 		}
10433 	}
10434 	for (i = 0; i < li_total_channels; i++)
10435 	{
10436 		if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10437 		{
10438 			li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10439 			for (j = 0; j < li_total_channels; j++)
10440 			{
10441 				if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10442 					li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10443 			}
10444 			if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10445 				li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10446 		}
10447 	}
10448 	for (i = 0; i < li_total_channels; i++)
10449 	{
10450 		if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10451 		{
10452 			for (j = 0; j < li_total_channels; j++)
10453 			{
10454 				if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10455 					li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10456 				if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10457 					li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10458 				if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10459 					li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10460 				if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10461 					li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10462 			}
10463 			if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10464 			{
10465 				for (j = 0; j < li_total_channels; j++)
10466 				{
10467 					if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10468 					{
10469 						li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10470 						if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10471 							li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10472 					}
10473 				}
10474 			}
10475 			if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10476 			{
10477 				for (j = 0; j < li_total_channels; j++)
10478 				{
10479 					if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10480 						li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10481 				}
10482 			}
10483 			if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10484 			{
10485 				for (j = 0; j < li_total_channels; j++)
10486 				{
10487 					if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10488 					{
10489 						for (n = 0; n < li_total_channels; n++)
10490 						{
10491 							if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10492 							{
10493 								li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10494 								if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10495 								{
10496 									li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10497 									if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10498 										li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10499 								}
10500 								else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10501 									li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10502 							}
10503 						}
10504 					}
10505 				}
10506 			}
10507 		}
10508 	}
10509 	for (i = 0; i < li_total_channels; i++)
10510 	{
10511 		if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10512 		{
10513 			if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10514 				li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10515 			if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10516 				li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10517 			if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10518 				li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10519 			for (j = 0; j < li_total_channels; j++)
10520 			{
10521 				if ((li_config_table[i].flag_table[j] &
10522 				     (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10523 				    || (li_config_table[j].flag_table[i] &
10524 					(LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10525 				{
10526 					li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10527 				}
10528 				if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10529 					li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10530 				if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10531 					li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10532 			}
10533 			if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10534 			{
10535 				li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10536 				li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10537 			}
10538 		}
10539 	}
10540 	for (i = 0; i < li_total_channels; i++)
10541 	{
10542 		if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10543 		{
10544 			j = 0;
10545 			while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10546 				j++;
10547 			if (j < li_total_channels)
10548 			{
10549 				for (j = 0; j < li_total_channels; j++)
10550 				{
10551 					li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10552 					if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10553 						li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10554 				}
10555 			}
10556 		}
10557 	}
10558 	n = li_total_channels;
10559 	if (n > MIXER_MAX_DUMP_CHANNELS)
10560 		n = MIXER_MAX_DUMP_CHANNELS;
10561 
10562 	p = hex_line;
10563 	for (j = 0; j < n; j++)
10564 	{
10565 		if ((j & 0x7) == 0)
10566 			*(p++) = ' ';
10567 		p = hex_byte_pack(p, li_config_table[j].curchnl);
10568 	}
10569 	*p = '\0';
10570 	dbug(1, dprintf("[%06lx] CURRENT %s",
10571 			(dword)(UnMapController(a->Id)), (char *)hex_line));
10572 	p = hex_line;
10573 	for (j = 0; j < n; j++)
10574 	{
10575 		if ((j & 0x7) == 0)
10576 			*(p++) = ' ';
10577 		p = hex_byte_pack(p, li_config_table[j].channel);
10578 	}
10579 	*p = '\0';
10580 	dbug(1, dprintf("[%06lx] CHANNEL %s",
10581 			(dword)(UnMapController(a->Id)), (char *)hex_line));
10582 	p = hex_line;
10583 	for (j = 0; j < n; j++)
10584 	{
10585 		if ((j & 0x7) == 0)
10586 			*(p++) = ' ';
10587 		p = hex_byte_pack(p, li_config_table[j].chflags);
10588 	}
10589 	*p = '\0';
10590 	dbug(1, dprintf("[%06lx] CHFLAG  %s",
10591 			(dword)(UnMapController(a->Id)), (char *)hex_line));
10592 	for (i = 0; i < n; i++)
10593 	{
10594 		p = hex_line;
10595 		for (j = 0; j < n; j++)
10596 		{
10597 			if ((j & 0x7) == 0)
10598 				*(p++) = ' ';
10599 			p = hex_byte_pack(p, li_config_table[i].flag_table[j]);
10600 		}
10601 		*p = '\0';
10602 		dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10603 				(dword)(UnMapController(a->Id)), i, (char *)hex_line));
10604 	}
10605 	for (i = 0; i < n; i++)
10606 	{
10607 		p = hex_line;
10608 		for (j = 0; j < n; j++)
10609 		{
10610 			if ((j & 0x7) == 0)
10611 				*(p++) = ' ';
10612 			p = hex_byte_pack(p, li_config_table[i].coef_table[j]);
10613 		}
10614 		*p = '\0';
10615 		dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10616 				(dword)(UnMapController(a->Id)), i, (char *)hex_line));
10617 	}
10618 }
10619 
10620 
10621 static struct
10622 {
10623 	byte mask;
10624 	byte line_flags;
10625 } mixer_write_prog_pri[] =
10626 {
10627 	{ LI_COEF_CH_CH, 0 },
10628 	{ LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10629 	{ LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10630 	{ LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10631 };
10632 
10633 static struct
10634 {
10635 	byte from_ch;
10636 	byte to_ch;
10637 	byte mask;
10638 	byte xconnect_override;
10639 } mixer_write_prog_bri[] =
10640 {
10641 	{ 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10642 	{ 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10643 	{ 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10644 	{ 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10645 	{ 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10646 	{ 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10647 	{ 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10648 	{ 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10649 	{ 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10650 	{ 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10651 	{ 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10652 	{ 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10653 	{ 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10654 	{ 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10655 	{ 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10656 	{ 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10657 	{ 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10658 	{ 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10659 	{ 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10660 	{ 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10661 	{ 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10662 	{ 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10663 	{ 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10664 	{ 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10665 	{ 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10666 	{ 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10667 	{ 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10668 	{ 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10669 	{ 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10670 	{ 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10671 	{ 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10672 	{ 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10673 	{ 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10674 	{ 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10675 	{ 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10676 	{ 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10677 };
10678 
10679 static byte mixer_swapped_index_bri[] =
10680 {
10681 	18,  /* B      to B      */
10682 	19,  /* Alt B  to B      */
10683 	20,  /* PC     to B      */
10684 	21,  /* Alt PC to B      */
10685 	22,  /* IC     to B      */
10686 	23,  /* Alt IC to B      */
10687 	24,  /* B      to PC     */
10688 	25,  /* Alt B  to PC     */
10689 	26,  /* PC     to PC     */
10690 	27,  /* Alt PC to PC     */
10691 	28,  /* IC     to PC     */
10692 	29,  /* Alt IC to PC     */
10693 	30,  /* B      to IC     */
10694 	31,  /* Alt B  to IC     */
10695 	32,  /* PC     to IC     */
10696 	33,  /* Alt PC to IC     */
10697 	34,  /* IC     to IC     */
10698 	35,  /* Alt IC to IC     */
10699 	0,   /* Alt B  to Alt B  */
10700 	1,   /* B      to Alt B  */
10701 	2,   /* Alt PC to Alt B  */
10702 	3,   /* PC     to Alt B  */
10703 	4,   /* Alt IC to Alt B  */
10704 	5,   /* IC     to Alt B  */
10705 	6,   /* Alt B  to Alt PC */
10706 	7,   /* B      to Alt PC */
10707 	8,   /* Alt PC to Alt PC */
10708 	9,   /* PC     to Alt PC */
10709 	10,  /* Alt IC to Alt PC */
10710 	11,  /* IC     to Alt PC */
10711 	12,  /* Alt B  to Alt IC */
10712 	13,  /* B      to Alt IC */
10713 	14,  /* Alt PC to Alt IC */
10714 	15,  /* PC     to Alt IC */
10715 	16,  /* Alt IC to Alt IC */
10716 	17   /* IC     to Alt IC */
10717 };
10718 
10719 static struct
10720 {
10721 	byte mask;
10722 	byte from_pc;
10723 	byte to_pc;
10724 } xconnect_write_prog[] =
10725 {
10726 	{ LI_COEF_CH_CH, false, false },
10727 	{ LI_COEF_CH_PC, false, true },
10728 	{ LI_COEF_PC_CH, true, false },
10729 	{ LI_COEF_PC_PC, true, true }
10730 };
10731 
10732 
xconnect_query_addresses(PLCI * plci)10733 static void xconnect_query_addresses(PLCI *plci)
10734 {
10735 	DIVA_CAPI_ADAPTER *a;
10736 	word w, ch;
10737 	byte *p;
10738 
10739 	dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10740 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10741 			(char *)(FILE_), __LINE__));
10742 
10743 	a = plci->adapter;
10744 	if (a->li_pri && ((plci->li_bchannel_id == 0)
10745 			  || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10746 	{
10747 		dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10748 				(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10749 				(char *)(FILE_), __LINE__));
10750 		return;
10751 	}
10752 	p = plci->internal_req_buffer;
10753 	ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10754 	*(p++) = UDATA_REQUEST_XCONNECT_FROM;
10755 	w = ch;
10756 	*(p++) = (byte) w;
10757 	*(p++) = (byte)(w >> 8);
10758 	w = ch | XCONNECT_CHANNEL_PORT_PC;
10759 	*(p++) = (byte) w;
10760 	*(p++) = (byte)(w >> 8);
10761 	plci->NData[0].P = plci->internal_req_buffer;
10762 	plci->NData[0].PLength = p - plci->internal_req_buffer;
10763 	plci->NL.X = plci->NData;
10764 	plci->NL.ReqCh = 0;
10765 	plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10766 	plci->adapter->request(&plci->NL);
10767 }
10768 
10769 
xconnect_write_coefs(PLCI * plci,word internal_command)10770 static void xconnect_write_coefs(PLCI *plci, word internal_command)
10771 {
10772 
10773 	dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10774 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10775 			(char *)(FILE_), __LINE__, internal_command));
10776 
10777 	plci->li_write_command = internal_command;
10778 	plci->li_write_channel = 0;
10779 }
10780 
10781 
xconnect_write_coefs_process(dword Id,PLCI * plci,byte Rc)10782 static byte xconnect_write_coefs_process(dword Id, PLCI *plci, byte Rc)
10783 {
10784 	DIVA_CAPI_ADAPTER *a;
10785 	word w, n, i, j, r, s, to_ch;
10786 	dword d;
10787 	byte *p;
10788 	struct xconnect_transfer_address_s   *transfer_address;
10789 	byte ch_map[MIXER_CHANNELS_BRI];
10790 
10791 	dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10792 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10793 
10794 	a = plci->adapter;
10795 	if ((plci->li_bchannel_id == 0)
10796 	    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10797 	{
10798 		dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10799 				UnMapId(Id), (char *)(FILE_), __LINE__));
10800 		return (true);
10801 	}
10802 	i = a->li_base + (plci->li_bchannel_id - 1);
10803 	j = plci->li_write_channel;
10804 	p = plci->internal_req_buffer;
10805 	if (j != 0)
10806 	{
10807 		if ((Rc != OK) && (Rc != OK_FC))
10808 		{
10809 			dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10810 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10811 			return (false);
10812 		}
10813 	}
10814 	if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10815 	{
10816 		r = 0;
10817 		s = 0;
10818 		if (j < li_total_channels)
10819 		{
10820 			if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10821 			{
10822 				s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10823 				     (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10824 					((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10825 					 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10826 			}
10827 			r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10828 			while ((j < li_total_channels)
10829 			       && ((r == 0)
10830 				   || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10831 				   || (!li_config_table[j].adapter->li_pri
10832 				       && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10833 				   || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10834 					|| (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10835 				       && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10836 					   || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10837 				   || ((li_config_table[j].adapter->li_base != a->li_base)
10838 				       && !(r & s &
10839 					    ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10840 					     (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10841 					    ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10842 					     (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10843 			{
10844 				j++;
10845 				if (j < li_total_channels)
10846 					r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10847 			}
10848 		}
10849 		if (j < li_total_channels)
10850 		{
10851 			plci->internal_command = plci->li_write_command;
10852 			if (plci_nl_busy(plci))
10853 				return (true);
10854 			to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10855 			*(p++) = UDATA_REQUEST_XCONNECT_TO;
10856 			do
10857 			{
10858 				if (li_config_table[j].adapter->li_base != a->li_base)
10859 				{
10860 					r &= s &
10861 						((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10862 						 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10863 						((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10864 						 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10865 				}
10866 				n = 0;
10867 				do
10868 				{
10869 					if (r & xconnect_write_prog[n].mask)
10870 					{
10871 						if (xconnect_write_prog[n].from_pc)
10872 							transfer_address = &(li_config_table[j].send_pc);
10873 						else
10874 							transfer_address = &(li_config_table[j].send_b);
10875 						d = transfer_address->card_address.low;
10876 						*(p++) = (byte) d;
10877 						*(p++) = (byte)(d >> 8);
10878 						*(p++) = (byte)(d >> 16);
10879 						*(p++) = (byte)(d >> 24);
10880 						d = transfer_address->card_address.high;
10881 						*(p++) = (byte) d;
10882 						*(p++) = (byte)(d >> 8);
10883 						*(p++) = (byte)(d >> 16);
10884 						*(p++) = (byte)(d >> 24);
10885 						d = transfer_address->offset;
10886 						*(p++) = (byte) d;
10887 						*(p++) = (byte)(d >> 8);
10888 						*(p++) = (byte)(d >> 16);
10889 						*(p++) = (byte)(d >> 24);
10890 						w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
10891 						*(p++) = (byte) w;
10892 						*(p++) = (byte)(w >> 8);
10893 						w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
10894 							(li_config_table[i].adapter->u_law ?
10895 							 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
10896 							 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
10897 						*(p++) = (byte) w;
10898 						*(p++) = (byte) 0;
10899 						li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
10900 					}
10901 					n++;
10902 				} while ((n < ARRAY_SIZE(xconnect_write_prog))
10903 					 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
10904 				if (n == ARRAY_SIZE(xconnect_write_prog))
10905 				{
10906 					do
10907 					{
10908 						j++;
10909 						if (j < li_total_channels)
10910 							r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10911 					} while ((j < li_total_channels)
10912 						 && ((r == 0)
10913 						     || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10914 						     || (!li_config_table[j].adapter->li_pri
10915 							 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10916 						     || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10917 							  || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10918 							 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10919 							     || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10920 						     || ((li_config_table[j].adapter->li_base != a->li_base)
10921 							 && !(r & s &
10922 							      ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10923 							       (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10924 							      ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10925 							       (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
10926 				}
10927 			} while ((j < li_total_channels)
10928 				 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
10929 		}
10930 		else if (j == li_total_channels)
10931 		{
10932 			plci->internal_command = plci->li_write_command;
10933 			if (plci_nl_busy(plci))
10934 				return (true);
10935 			if (a->li_pri)
10936 			{
10937 				*(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
10938 				w = 0;
10939 				if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
10940 					w |= MIXER_FEATURE_ENABLE_TX_DATA;
10941 				if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
10942 					w |= MIXER_FEATURE_ENABLE_RX_DATA;
10943 				*(p++) = (byte) w;
10944 				*(p++) = (byte)(w >> 8);
10945 			}
10946 			else
10947 			{
10948 				*(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
10949 				w = 0;
10950 				if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
10951 				    && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
10952 				{
10953 					w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
10954 				}
10955 				if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
10956 					w |= MIXER_FEATURE_ENABLE_TX_DATA;
10957 				if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
10958 					w |= MIXER_FEATURE_ENABLE_RX_DATA;
10959 				*(p++) = (byte) w;
10960 				*(p++) = (byte)(w >> 8);
10961 				for (j = 0; j < sizeof(ch_map); j += 2)
10962 				{
10963 					if (plci->li_bchannel_id == 2)
10964 					{
10965 						ch_map[j] = (byte)(j + 1);
10966 						ch_map[j + 1] = (byte) j;
10967 					}
10968 					else
10969 					{
10970 						ch_map[j] = (byte) j;
10971 						ch_map[j + 1] = (byte)(j + 1);
10972 					}
10973 				}
10974 				for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
10975 				{
10976 					i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
10977 					j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
10978 					if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
10979 					{
10980 						*p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
10981 							mixer_write_prog_bri[n].xconnect_override :
10982 							((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
10983 						if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
10984 						{
10985 							w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10986 							li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
10987 						}
10988 					}
10989 					else
10990 					{
10991 						*p = 0x00;
10992 						if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10993 						{
10994 							w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
10995 							if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
10996 								*p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
10997 						}
10998 					}
10999 					p++;
11000 				}
11001 			}
11002 			j = li_total_channels + 1;
11003 		}
11004 	}
11005 	else
11006 	{
11007 		if (j <= li_total_channels)
11008 		{
11009 			plci->internal_command = plci->li_write_command;
11010 			if (plci_nl_busy(plci))
11011 				return (true);
11012 			if (j < a->li_base)
11013 				j = a->li_base;
11014 			if (a->li_pri)
11015 			{
11016 				*(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11017 				w = 0;
11018 				if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11019 					w |= MIXER_FEATURE_ENABLE_TX_DATA;
11020 				if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11021 					w |= MIXER_FEATURE_ENABLE_RX_DATA;
11022 				*(p++) = (byte) w;
11023 				*(p++) = (byte)(w >> 8);
11024 				for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11025 				{
11026 					*(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11027 					for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11028 					{
11029 						w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11030 						if (w & mixer_write_prog_pri[n].mask)
11031 						{
11032 							*(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11033 							li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11034 						}
11035 						else
11036 							*(p++) = 0x00;
11037 					}
11038 					*(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11039 					for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11040 					{
11041 						w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11042 						if (w & mixer_write_prog_pri[n].mask)
11043 						{
11044 							*(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11045 							li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11046 						}
11047 						else
11048 							*(p++) = 0x00;
11049 					}
11050 				}
11051 			}
11052 			else
11053 			{
11054 				*(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11055 				w = 0;
11056 				if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11057 				    && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11058 				{
11059 					w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11060 				}
11061 				if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11062 					w |= MIXER_FEATURE_ENABLE_TX_DATA;
11063 				if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11064 					w |= MIXER_FEATURE_ENABLE_RX_DATA;
11065 				*(p++) = (byte) w;
11066 				*(p++) = (byte)(w >> 8);
11067 				for (j = 0; j < sizeof(ch_map); j += 2)
11068 				{
11069 					if (plci->li_bchannel_id == 2)
11070 					{
11071 						ch_map[j] = (byte)(j + 1);
11072 						ch_map[j + 1] = (byte) j;
11073 					}
11074 					else
11075 					{
11076 						ch_map[j] = (byte) j;
11077 						ch_map[j + 1] = (byte)(j + 1);
11078 					}
11079 				}
11080 				for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11081 				{
11082 					i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11083 					j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11084 					if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11085 					{
11086 						*p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11087 						w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11088 						li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11089 					}
11090 					else
11091 					{
11092 						*p = 0x00;
11093 						if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11094 						{
11095 							w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11096 							if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11097 								*p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11098 						}
11099 					}
11100 					p++;
11101 				}
11102 			}
11103 			j = li_total_channels + 1;
11104 		}
11105 	}
11106 	plci->li_write_channel = j;
11107 	if (p != plci->internal_req_buffer)
11108 	{
11109 		plci->NData[0].P = plci->internal_req_buffer;
11110 		plci->NData[0].PLength = p - plci->internal_req_buffer;
11111 		plci->NL.X = plci->NData;
11112 		plci->NL.ReqCh = 0;
11113 		plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11114 		plci->adapter->request(&plci->NL);
11115 	}
11116 	return (true);
11117 }
11118 
11119 
mixer_notify_update(PLCI * plci,byte others)11120 static void mixer_notify_update(PLCI *plci, byte others)
11121 {
11122 	DIVA_CAPI_ADAPTER *a;
11123 	word i, w;
11124 	PLCI *notify_plci;
11125 	byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11126 
11127 	dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11128 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11129 			(char *)(FILE_), __LINE__, others));
11130 
11131 	a = plci->adapter;
11132 	if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11133 	{
11134 		if (others)
11135 			plci->li_notify_update = true;
11136 		i = 0;
11137 		do
11138 		{
11139 			notify_plci = NULL;
11140 			if (others)
11141 			{
11142 				while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11143 					i++;
11144 				if (i < li_total_channels)
11145 					notify_plci = li_config_table[i++].plci;
11146 			}
11147 			else
11148 			{
11149 				if ((plci->li_bchannel_id != 0)
11150 				    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11151 				{
11152 					notify_plci = plci;
11153 				}
11154 			}
11155 			if ((notify_plci != NULL)
11156 			    && !notify_plci->li_notify_update
11157 			    && (notify_plci->appl != NULL)
11158 			    && (notify_plci->State)
11159 			    && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11160 			{
11161 				notify_plci->li_notify_update = true;
11162 				((CAPI_MSG *) msg)->header.length = 18;
11163 				((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11164 				((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11165 				((CAPI_MSG *) msg)->header.number = 0;
11166 				((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11167 				((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11168 				((CAPI_MSG *) msg)->header.ncci = 0;
11169 				((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11170 				((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11171 				((CAPI_MSG *) msg)->info.facility_req.structs[1] = LI_REQ_SILENT_UPDATE & 0xff;
11172 				((CAPI_MSG *) msg)->info.facility_req.structs[2] = LI_REQ_SILENT_UPDATE >> 8;
11173 				((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11174 				w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11175 				if (w != _QUEUE_FULL)
11176 				{
11177 					if (w != 0)
11178 					{
11179 						dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11180 								(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11181 								(char *)(FILE_), __LINE__,
11182 								(dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11183 					}
11184 					notify_plci->li_notify_update = false;
11185 				}
11186 			}
11187 		} while (others && (notify_plci != NULL));
11188 		if (others)
11189 			plci->li_notify_update = false;
11190 	}
11191 }
11192 
11193 
mixer_clear_config(PLCI * plci)11194 static void mixer_clear_config(PLCI *plci)
11195 {
11196 	DIVA_CAPI_ADAPTER *a;
11197 	word i, j;
11198 
11199 	dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11200 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11201 			(char *)(FILE_), __LINE__));
11202 
11203 	plci->li_notify_update = false;
11204 	plci->li_plci_b_write_pos = 0;
11205 	plci->li_plci_b_read_pos = 0;
11206 	plci->li_plci_b_req_pos = 0;
11207 	a = plci->adapter;
11208 	if ((plci->li_bchannel_id != 0)
11209 	    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11210 	{
11211 		i = a->li_base + (plci->li_bchannel_id - 1);
11212 		li_config_table[i].curchnl = 0;
11213 		li_config_table[i].channel = 0;
11214 		li_config_table[i].chflags = 0;
11215 		for (j = 0; j < li_total_channels; j++)
11216 		{
11217 			li_config_table[j].flag_table[i] = 0;
11218 			li_config_table[i].flag_table[j] = 0;
11219 			li_config_table[i].coef_table[j] = 0;
11220 			li_config_table[j].coef_table[i] = 0;
11221 		}
11222 		if (!a->li_pri)
11223 		{
11224 			li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11225 			if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11226 			{
11227 				i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11228 				li_config_table[i].curchnl = 0;
11229 				li_config_table[i].channel = 0;
11230 				li_config_table[i].chflags = 0;
11231 				for (j = 0; j < li_total_channels; j++)
11232 				{
11233 					li_config_table[i].flag_table[j] = 0;
11234 					li_config_table[j].flag_table[i] = 0;
11235 					li_config_table[i].coef_table[j] = 0;
11236 					li_config_table[j].coef_table[i] = 0;
11237 				}
11238 				if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11239 				{
11240 					i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11241 					li_config_table[i].curchnl = 0;
11242 					li_config_table[i].channel = 0;
11243 					li_config_table[i].chflags = 0;
11244 					for (j = 0; j < li_total_channels; j++)
11245 					{
11246 						li_config_table[i].flag_table[j] = 0;
11247 						li_config_table[j].flag_table[i] = 0;
11248 						li_config_table[i].coef_table[j] = 0;
11249 						li_config_table[j].coef_table[i] = 0;
11250 					}
11251 				}
11252 			}
11253 		}
11254 	}
11255 }
11256 
11257 
mixer_prepare_switch(dword Id,PLCI * plci)11258 static void mixer_prepare_switch(dword Id, PLCI *plci)
11259 {
11260 
11261 	dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11262 			UnMapId(Id), (char *)(FILE_), __LINE__));
11263 
11264 	do
11265 	{
11266 		mixer_indication_coefs_set(Id, plci);
11267 	} while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11268 }
11269 
11270 
mixer_save_config(dword Id,PLCI * plci,byte Rc)11271 static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11272 {
11273 	DIVA_CAPI_ADAPTER *a;
11274 	word i, j;
11275 
11276 	dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11277 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11278 
11279 	a = plci->adapter;
11280 	if ((plci->li_bchannel_id != 0)
11281 	    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11282 	{
11283 		i = a->li_base + (plci->li_bchannel_id - 1);
11284 		for (j = 0; j < li_total_channels; j++)
11285 		{
11286 			li_config_table[i].coef_table[j] &= 0xf;
11287 			li_config_table[j].coef_table[i] &= 0xf;
11288 		}
11289 		if (!a->li_pri)
11290 			li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11291 	}
11292 	return (GOOD);
11293 }
11294 
11295 
mixer_restore_config(dword Id,PLCI * plci,byte Rc)11296 static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11297 {
11298 	DIVA_CAPI_ADAPTER *a;
11299 	word Info;
11300 
11301 	dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11302 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11303 
11304 	Info = GOOD;
11305 	a = plci->adapter;
11306 	if ((plci->B1_facilities & B1_FACILITY_MIXER)
11307 	    && (plci->li_bchannel_id != 0)
11308 	    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11309 	{
11310 		switch (plci->adjust_b_state)
11311 		{
11312 		case ADJUST_B_RESTORE_MIXER_1:
11313 			if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11314 			{
11315 				plci->internal_command = plci->adjust_b_command;
11316 				if (plci_nl_busy(plci))
11317 				{
11318 					plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11319 					break;
11320 				}
11321 				xconnect_query_addresses(plci);
11322 				plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11323 				break;
11324 			}
11325 			plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11326 			Rc = OK;
11327 			/* fall through */
11328 		case ADJUST_B_RESTORE_MIXER_2:
11329 		case ADJUST_B_RESTORE_MIXER_3:
11330 		case ADJUST_B_RESTORE_MIXER_4:
11331 			if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11332 			{
11333 				dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11334 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11335 				Info = _WRONG_STATE;
11336 				break;
11337 			}
11338 			if (Rc == OK)
11339 			{
11340 				if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11341 					plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11342 				else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11343 					plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11344 			}
11345 			else if (Rc == 0)
11346 			{
11347 				if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11348 					plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11349 				else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11350 					plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11351 			}
11352 			if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11353 			{
11354 				plci->internal_command = plci->adjust_b_command;
11355 				break;
11356 			}
11357 			/* fall through */
11358 		case ADJUST_B_RESTORE_MIXER_5:
11359 			xconnect_write_coefs(plci, plci->adjust_b_command);
11360 			plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11361 			Rc = OK;
11362 			/* fall through */
11363 		case ADJUST_B_RESTORE_MIXER_6:
11364 			if (!xconnect_write_coefs_process(Id, plci, Rc))
11365 			{
11366 				dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11367 						UnMapId(Id), (char *)(FILE_), __LINE__));
11368 				Info = _FACILITY_NOT_SUPPORTED;
11369 				break;
11370 			}
11371 			if (plci->internal_command)
11372 				break;
11373 			plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11374 		case ADJUST_B_RESTORE_MIXER_7:
11375 			break;
11376 		}
11377 	}
11378 	return (Info);
11379 }
11380 
11381 
mixer_command(dword Id,PLCI * plci,byte Rc)11382 static void mixer_command(dword Id, PLCI *plci, byte Rc)
11383 {
11384 	DIVA_CAPI_ADAPTER *a;
11385 	word i, internal_command;
11386 
11387 	dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11388 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11389 			plci->li_cmd));
11390 
11391 	a = plci->adapter;
11392 	internal_command = plci->internal_command;
11393 	plci->internal_command = 0;
11394 	switch (plci->li_cmd)
11395 	{
11396 	case LI_REQ_CONNECT:
11397 	case LI_REQ_DISCONNECT:
11398 	case LI_REQ_SILENT_UPDATE:
11399 		switch (internal_command)
11400 		{
11401 		default:
11402 			if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11403 			{
11404 				adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11405 									  B1_FACILITY_MIXER), MIXER_COMMAND_1);
11406 			}
11407 			/* fall through */
11408 		case MIXER_COMMAND_1:
11409 			if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11410 			{
11411 				if (adjust_b_process(Id, plci, Rc) != GOOD)
11412 				{
11413 					dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11414 							UnMapId(Id), (char *)(FILE_), __LINE__));
11415 					break;
11416 				}
11417 				if (plci->internal_command)
11418 					return;
11419 			}
11420 			plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11421 			if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11422 			    || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11423 				&& (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11424 										      ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11425 			{
11426 				xconnect_write_coefs(plci, MIXER_COMMAND_2);
11427 			}
11428 			else
11429 			{
11430 				do
11431 				{
11432 					mixer_indication_coefs_set(Id, plci);
11433 				} while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11434 			}
11435 			/* fall through */
11436 		case MIXER_COMMAND_2:
11437 			if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11438 			    || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11439 				&& (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11440 										      ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11441 			{
11442 				if (!xconnect_write_coefs_process(Id, plci, Rc))
11443 				{
11444 					dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11445 							UnMapId(Id), (char *)(FILE_), __LINE__));
11446 					if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11447 					{
11448 						do
11449 						{
11450 							plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11451 								LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11452 							i = (plci->li_plci_b_write_pos == 0) ?
11453 								LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11454 						} while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11455 							 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11456 					}
11457 					break;
11458 				}
11459 				if (plci->internal_command)
11460 					return;
11461 			}
11462 			if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11463 			{
11464 				adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11465 									  ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11466 			}
11467 			/* fall through */
11468 		case MIXER_COMMAND_3:
11469 			if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11470 			{
11471 				if (adjust_b_process(Id, plci, Rc) != GOOD)
11472 				{
11473 					dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11474 							UnMapId(Id), (char *)(FILE_), __LINE__));
11475 					break;
11476 				}
11477 				if (plci->internal_command)
11478 					return;
11479 			}
11480 			break;
11481 		}
11482 		break;
11483 	}
11484 	if ((plci->li_bchannel_id == 0)
11485 	    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11486 	{
11487 		dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11488 				UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11489 	}
11490 	else
11491 	{
11492 		i = a->li_base + (plci->li_bchannel_id - 1);
11493 		li_config_table[i].curchnl = plci->li_channel_bits;
11494 		if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11495 		{
11496 			i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11497 			li_config_table[i].curchnl = plci->li_channel_bits;
11498 			if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11499 			{
11500 				i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11501 				li_config_table[i].curchnl = plci->li_channel_bits;
11502 			}
11503 		}
11504 	}
11505 }
11506 
11507 
li_update_connect(dword Id,DIVA_CAPI_ADAPTER * a,PLCI * plci,dword plci_b_id,byte connect,dword li_flags)11508 static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11509 			      dword plci_b_id, byte connect, dword li_flags)
11510 {
11511 	word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11512 	PLCI *plci_b;
11513 	DIVA_CAPI_ADAPTER *a_b;
11514 
11515 	a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11516 	plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11517 	ch_a = a->li_base + (plci->li_bchannel_id - 1);
11518 	if (!a->li_pri && (plci->tel == ADV_VOICE)
11519 	    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11520 	{
11521 		ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11522 		ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11523 			a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11524 	}
11525 	else
11526 	{
11527 		ch_a_v = ch_a;
11528 		ch_a_s = ch_a;
11529 	}
11530 	ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11531 	if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11532 	    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11533 	{
11534 		ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11535 		ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11536 			a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11537 	}
11538 	else
11539 	{
11540 		ch_b_v = ch_b;
11541 		ch_b_s = ch_b;
11542 	}
11543 	if (connect)
11544 	{
11545 		li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11546 		li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11547 		li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11548 		li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11549 	}
11550 	li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11551 	li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11552 	li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11553 	li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11554 	if (ch_a_v == ch_b_v)
11555 	{
11556 		li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11557 		li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11558 	}
11559 	else
11560 	{
11561 		if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11562 		{
11563 			for (i = 0; i < li_total_channels; i++)
11564 			{
11565 				if (i != ch_a_v)
11566 					li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11567 			}
11568 		}
11569 		if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11570 		{
11571 			for (i = 0; i < li_total_channels; i++)
11572 			{
11573 				if (i != ch_a_s)
11574 					li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11575 			}
11576 		}
11577 		if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11578 		{
11579 			for (i = 0; i < li_total_channels; i++)
11580 			{
11581 				if (i != ch_a_v)
11582 					li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11583 			}
11584 		}
11585 		if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11586 		{
11587 			for (i = 0; i < li_total_channels; i++)
11588 			{
11589 				if (i != ch_a_s)
11590 					li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11591 			}
11592 		}
11593 	}
11594 	if (li_flags & LI_FLAG_CONFERENCE_A_B)
11595 	{
11596 		li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11597 		li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11598 		li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11599 		li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11600 	}
11601 	if (li_flags & LI_FLAG_CONFERENCE_B_A)
11602 	{
11603 		li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11604 		li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11605 		li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11606 		li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11607 	}
11608 	if (li_flags & LI_FLAG_MONITOR_A)
11609 	{
11610 		li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11611 		li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11612 	}
11613 	if (li_flags & LI_FLAG_MONITOR_B)
11614 	{
11615 		li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11616 		li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11617 	}
11618 	if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11619 	{
11620 		li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11621 		li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11622 	}
11623 	if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11624 	{
11625 		li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11626 		li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11627 	}
11628 	if (li_flags & LI_FLAG_MIX_A)
11629 	{
11630 		li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11631 		li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11632 	}
11633 	if (li_flags & LI_FLAG_MIX_B)
11634 	{
11635 		li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11636 		li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11637 	}
11638 	if (ch_a_v != ch_a_s)
11639 	{
11640 		li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11641 		li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11642 	}
11643 	if (ch_b_v != ch_b_s)
11644 	{
11645 		li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11646 		li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11647 	}
11648 }
11649 
11650 
li2_update_connect(dword Id,DIVA_CAPI_ADAPTER * a,PLCI * plci,dword plci_b_id,byte connect,dword li_flags)11651 static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11652 			       dword plci_b_id, byte connect, dword li_flags)
11653 {
11654 	word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11655 	PLCI *plci_b;
11656 	DIVA_CAPI_ADAPTER *a_b;
11657 
11658 	a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11659 	plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11660 	ch_a = a->li_base + (plci->li_bchannel_id - 1);
11661 	if (!a->li_pri && (plci->tel == ADV_VOICE)
11662 	    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11663 	{
11664 		ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11665 		ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11666 			a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11667 	}
11668 	else
11669 	{
11670 		ch_a_v = ch_a;
11671 		ch_a_s = ch_a;
11672 	}
11673 	ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11674 	if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11675 	    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11676 	{
11677 		ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11678 		ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11679 			a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11680 	}
11681 	else
11682 	{
11683 		ch_b_v = ch_b;
11684 		ch_b_s = ch_b;
11685 	}
11686 	if (connect)
11687 	{
11688 		li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11689 		li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11690 		li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11691 		li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11692 		li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11693 		li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11694 	}
11695 	li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11696 	li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11697 	li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11698 	li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11699 	li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11700 	li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11701 	li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11702 	li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11703 	if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11704 	{
11705 		li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11706 		li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11707 		li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11708 		li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11709 	}
11710 	if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11711 	{
11712 		li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11713 		li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11714 		li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11715 		li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11716 	}
11717 	if (li_flags & LI2_FLAG_MONITOR_B)
11718 	{
11719 		li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11720 		li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11721 	}
11722 	if (li_flags & LI2_FLAG_MIX_B)
11723 	{
11724 		li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11725 		li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11726 	}
11727 	if (li_flags & LI2_FLAG_MONITOR_X)
11728 		li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11729 	if (li_flags & LI2_FLAG_MIX_X)
11730 		li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11731 	if (li_flags & LI2_FLAG_LOOP_B)
11732 	{
11733 		li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11734 		li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11735 		li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11736 		li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11737 	}
11738 	if (li_flags & LI2_FLAG_LOOP_PC)
11739 		li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11740 	if (li_flags & LI2_FLAG_LOOP_X)
11741 		li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11742 	if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11743 		li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11744 	if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11745 		li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11746 	if (ch_a_v != ch_a_s)
11747 	{
11748 		li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11749 		li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11750 	}
11751 	if (ch_b_v != ch_b_s)
11752 	{
11753 		li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11754 		li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11755 	}
11756 }
11757 
11758 
li_check_main_plci(dword Id,PLCI * plci)11759 static word li_check_main_plci(dword Id, PLCI *plci)
11760 {
11761 	if (plci == NULL)
11762 	{
11763 		dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11764 				UnMapId(Id), (char *)(FILE_), __LINE__));
11765 		return (_WRONG_IDENTIFIER);
11766 	}
11767 	if (!plci->State
11768 	    || !plci->NL.Id || plci->nl_remove_id
11769 	    || (plci->li_bchannel_id == 0))
11770 	{
11771 		dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11772 				UnMapId(Id), (char *)(FILE_), __LINE__));
11773 		return (_WRONG_STATE);
11774 	}
11775 	li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11776 	return (GOOD);
11777 }
11778 
11779 
li_check_plci_b(dword Id,PLCI * plci,dword plci_b_id,word plci_b_write_pos,byte * p_result)11780 static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11781 			     dword plci_b_id, word plci_b_write_pos, byte *p_result)
11782 {
11783 	byte ctlr_b;
11784 	PLCI *plci_b;
11785 
11786 	if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11787 	     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11788 	{
11789 		dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11790 				UnMapId(Id), (char *)(FILE_), __LINE__));
11791 		PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11792 		return (NULL);
11793 	}
11794 	ctlr_b = 0;
11795 	if ((plci_b_id & 0x7f) != 0)
11796 	{
11797 		ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11798 		if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11799 			ctlr_b = 0;
11800 	}
11801 	if ((ctlr_b == 0)
11802 	    || (((plci_b_id >> 8) & 0xff) == 0)
11803 	    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11804 	{
11805 		dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11806 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11807 		PUT_WORD(p_result, _WRONG_IDENTIFIER);
11808 		return (NULL);
11809 	}
11810 	plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11811 	if (!plci_b->State
11812 	    || !plci_b->NL.Id || plci_b->nl_remove_id
11813 	    || (plci_b->li_bchannel_id == 0))
11814 	{
11815 		dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11816 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11817 		PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11818 		return (NULL);
11819 	}
11820 	li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11821 	if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11822 	    ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11823 	    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11824 		|| !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11825 	{
11826 		dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11827 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11828 		PUT_WORD(p_result, _WRONG_IDENTIFIER);
11829 		return (NULL);
11830 	}
11831 	if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11832 							  (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11833 	{
11834 		dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11835 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11836 		PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11837 		return (NULL);
11838 	}
11839 	return (plci_b);
11840 }
11841 
11842 
li2_check_plci_b(dword Id,PLCI * plci,dword plci_b_id,word plci_b_write_pos,byte * p_result)11843 static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11844 			      dword plci_b_id, word plci_b_write_pos, byte *p_result)
11845 {
11846 	byte ctlr_b;
11847 	PLCI *plci_b;
11848 
11849 	if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11850 	     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11851 	{
11852 		dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11853 				UnMapId(Id), (char *)(FILE_), __LINE__));
11854 		PUT_WORD(p_result, _WRONG_STATE);
11855 		return (NULL);
11856 	}
11857 	ctlr_b = 0;
11858 	if ((plci_b_id & 0x7f) != 0)
11859 	{
11860 		ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11861 		if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11862 			ctlr_b = 0;
11863 	}
11864 	if ((ctlr_b == 0)
11865 	    || (((plci_b_id >> 8) & 0xff) == 0)
11866 	    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11867 	{
11868 		dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11869 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11870 		PUT_WORD(p_result, _WRONG_IDENTIFIER);
11871 		return (NULL);
11872 	}
11873 	plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11874 	if (!plci_b->State
11875 	    || !plci_b->NL.Id || plci_b->nl_remove_id
11876 	    || (plci_b->li_bchannel_id == 0)
11877 	    || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11878 	{
11879 		dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11880 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11881 		PUT_WORD(p_result, _WRONG_STATE);
11882 		return (NULL);
11883 	}
11884 	if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11885 	    ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11886 	    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11887 		|| !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11888 	{
11889 		dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11890 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11891 		PUT_WORD(p_result, _WRONG_IDENTIFIER);
11892 		return (NULL);
11893 	}
11894 	if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11895 							  (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11896 	{
11897 		dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11898 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11899 		PUT_WORD(p_result, _WRONG_STATE);
11900 		return (NULL);
11901 	}
11902 	return (plci_b);
11903 }
11904 
11905 
mixer_request(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)11906 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
11907 {
11908 	word Info;
11909 	word i;
11910 	dword d, li_flags, plci_b_id;
11911 	PLCI *plci_b;
11912 	API_PARSE li_parms[3];
11913 	API_PARSE li_req_parms[3];
11914 	API_PARSE li_participant_struct[2];
11915 	API_PARSE li_participant_parms[3];
11916 	word participant_parms_pos;
11917 	byte result_buffer[32];
11918 	byte *result;
11919 	word result_pos;
11920 	word plci_b_write_pos;
11921 
11922 	dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
11923 			UnMapId(Id), (char *)(FILE_), __LINE__));
11924 
11925 	Info = GOOD;
11926 	result = result_buffer;
11927 	result_buffer[0] = 0;
11928 	if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
11929 	{
11930 		dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
11931 				UnMapId(Id), (char *)(FILE_), __LINE__));
11932 		Info = _FACILITY_NOT_SUPPORTED;
11933 	}
11934 	else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
11935 	{
11936 		dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
11937 				UnMapId(Id), (char *)(FILE_), __LINE__));
11938 		Info = _WRONG_MESSAGE_FORMAT;
11939 	}
11940 	else
11941 	{
11942 		result_buffer[0] = 3;
11943 		PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
11944 		result_buffer[3] = 0;
11945 		switch (GET_WORD(li_parms[0].info))
11946 		{
11947 		case LI_GET_SUPPORTED_SERVICES:
11948 			if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
11949 			{
11950 				result_buffer[0] = 17;
11951 				result_buffer[3] = 14;
11952 				PUT_WORD(&result_buffer[4], GOOD);
11953 				d = 0;
11954 				if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
11955 					d |= LI_CONFERENCING_SUPPORTED;
11956 				if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
11957 					d |= LI_MONITORING_SUPPORTED;
11958 				if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
11959 					d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
11960 				if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11961 					d |= LI_CROSS_CONTROLLER_SUPPORTED;
11962 				PUT_DWORD(&result_buffer[6], d);
11963 				if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11964 				{
11965 					d = 0;
11966 					for (i = 0; i < li_total_channels; i++)
11967 					{
11968 						if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11969 						    && (li_config_table[i].adapter->li_pri
11970 							|| (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
11971 						{
11972 							d++;
11973 						}
11974 					}
11975 				}
11976 				else
11977 				{
11978 					d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
11979 				}
11980 				PUT_DWORD(&result_buffer[10], d / 2);
11981 				PUT_DWORD(&result_buffer[14], d);
11982 			}
11983 			else
11984 			{
11985 				result_buffer[0] = 25;
11986 				result_buffer[3] = 22;
11987 				PUT_WORD(&result_buffer[4], GOOD);
11988 				d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
11989 				if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
11990 					d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
11991 				if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
11992 					d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
11993 				if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
11994 					d |= LI2_PC_LOOPING_SUPPORTED;
11995 				if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11996 					d |= LI2_CROSS_CONTROLLER_SUPPORTED;
11997 				PUT_DWORD(&result_buffer[6], d);
11998 				d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
11999 				PUT_DWORD(&result_buffer[10], d / 2);
12000 				PUT_DWORD(&result_buffer[14], d - 1);
12001 				if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12002 				{
12003 					d = 0;
12004 					for (i = 0; i < li_total_channels; i++)
12005 					{
12006 						if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12007 						    && (li_config_table[i].adapter->li_pri
12008 							|| (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12009 						{
12010 							d++;
12011 						}
12012 					}
12013 				}
12014 				PUT_DWORD(&result_buffer[18], d / 2);
12015 				PUT_DWORD(&result_buffer[22], d - 1);
12016 			}
12017 			break;
12018 
12019 		case LI_REQ_CONNECT:
12020 			if (li_parms[1].length == 8)
12021 			{
12022 				appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12023 				if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12024 				{
12025 					dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12026 							UnMapId(Id), (char *)(FILE_), __LINE__));
12027 					Info = _WRONG_MESSAGE_FORMAT;
12028 					break;
12029 				}
12030 				plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12031 				li_flags = GET_DWORD(li_req_parms[1].info);
12032 				Info = li_check_main_plci(Id, plci);
12033 				result_buffer[0] = 9;
12034 				result_buffer[3] = 6;
12035 				PUT_DWORD(&result_buffer[4], plci_b_id);
12036 				PUT_WORD(&result_buffer[8], GOOD);
12037 				if (Info != GOOD)
12038 					break;
12039 				result = plci->saved_msg.info;
12040 				for (i = 0; i <= result_buffer[0]; i++)
12041 					result[i] = result_buffer[i];
12042 				plci_b_write_pos = plci->li_plci_b_write_pos;
12043 				plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12044 				if (plci_b == NULL)
12045 					break;
12046 				li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12047 				plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12048 				plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12049 				plci->li_plci_b_write_pos = plci_b_write_pos;
12050 			}
12051 			else
12052 			{
12053 				appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12054 				if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12055 				{
12056 					dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12057 							UnMapId(Id), (char *)(FILE_), __LINE__));
12058 					Info = _WRONG_MESSAGE_FORMAT;
12059 					break;
12060 				}
12061 				li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12062 				Info = li_check_main_plci(Id, plci);
12063 				result_buffer[0] = 7;
12064 				result_buffer[3] = 4;
12065 				PUT_WORD(&result_buffer[4], Info);
12066 				result_buffer[6] = 0;
12067 				if (Info != GOOD)
12068 					break;
12069 				result = plci->saved_msg.info;
12070 				for (i = 0; i <= result_buffer[0]; i++)
12071 					result[i] = result_buffer[i];
12072 				plci_b_write_pos = plci->li_plci_b_write_pos;
12073 				participant_parms_pos = 0;
12074 				result_pos = 7;
12075 				li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12076 				while (participant_parms_pos < li_req_parms[1].length)
12077 				{
12078 					result[result_pos] = 6;
12079 					result_pos += 7;
12080 					PUT_DWORD(&result[result_pos - 6], 0);
12081 					PUT_WORD(&result[result_pos - 2], GOOD);
12082 					if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12083 						      (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12084 					{
12085 						dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12086 								UnMapId(Id), (char *)(FILE_), __LINE__));
12087 						PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12088 						break;
12089 					}
12090 					if (api_parse(&li_participant_struct[0].info[1],
12091 						      li_participant_struct[0].length, "dd", li_participant_parms))
12092 					{
12093 						dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12094 								UnMapId(Id), (char *)(FILE_), __LINE__));
12095 						PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12096 						break;
12097 					}
12098 					plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12099 					li_flags = GET_DWORD(li_participant_parms[1].info);
12100 					PUT_DWORD(&result[result_pos - 6], plci_b_id);
12101 					if (sizeof(result) - result_pos < 7)
12102 					{
12103 						dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12104 								UnMapId(Id), (char *)(FILE_), __LINE__));
12105 						PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12106 						break;
12107 					}
12108 					plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12109 					if (plci_b != NULL)
12110 					{
12111 						li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12112 						plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12113 							((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12114 								      LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12115 						plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12116 					}
12117 					participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12118 								       (&li_req_parms[1].info[1]));
12119 				}
12120 				result[0] = (byte)(result_pos - 1);
12121 				result[3] = (byte)(result_pos - 4);
12122 				result[6] = (byte)(result_pos - 7);
12123 				i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12124 				if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12125 				    || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12126 				{
12127 					plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12128 					plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12129 				}
12130 				else
12131 					plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12132 				plci->li_plci_b_write_pos = plci_b_write_pos;
12133 			}
12134 			mixer_calculate_coefs(a);
12135 			plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12136 			mixer_notify_update(plci, true);
12137 			sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12138 			      "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12139 			plci->command = 0;
12140 			plci->li_cmd = GET_WORD(li_parms[0].info);
12141 			start_internal_command(Id, plci, mixer_command);
12142 			return (false);
12143 
12144 		case LI_REQ_DISCONNECT:
12145 			if (li_parms[1].length == 4)
12146 			{
12147 				appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12148 				if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12149 				{
12150 					dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12151 							UnMapId(Id), (char *)(FILE_), __LINE__));
12152 					Info = _WRONG_MESSAGE_FORMAT;
12153 					break;
12154 				}
12155 				plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12156 				Info = li_check_main_plci(Id, plci);
12157 				result_buffer[0] = 9;
12158 				result_buffer[3] = 6;
12159 				PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12160 				PUT_WORD(&result_buffer[8], GOOD);
12161 				if (Info != GOOD)
12162 					break;
12163 				result = plci->saved_msg.info;
12164 				for (i = 0; i <= result_buffer[0]; i++)
12165 					result[i] = result_buffer[i];
12166 				plci_b_write_pos = plci->li_plci_b_write_pos;
12167 				plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12168 				if (plci_b == NULL)
12169 					break;
12170 				li_update_connect(Id, a, plci, plci_b_id, false, 0);
12171 				plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12172 				plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12173 				plci->li_plci_b_write_pos = plci_b_write_pos;
12174 			}
12175 			else
12176 			{
12177 				appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12178 				if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12179 				{
12180 					dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12181 							UnMapId(Id), (char *)(FILE_), __LINE__));
12182 					Info = _WRONG_MESSAGE_FORMAT;
12183 					break;
12184 				}
12185 				Info = li_check_main_plci(Id, plci);
12186 				result_buffer[0] = 7;
12187 				result_buffer[3] = 4;
12188 				PUT_WORD(&result_buffer[4], Info);
12189 				result_buffer[6] = 0;
12190 				if (Info != GOOD)
12191 					break;
12192 				result = plci->saved_msg.info;
12193 				for (i = 0; i <= result_buffer[0]; i++)
12194 					result[i] = result_buffer[i];
12195 				plci_b_write_pos = plci->li_plci_b_write_pos;
12196 				participant_parms_pos = 0;
12197 				result_pos = 7;
12198 				while (participant_parms_pos < li_req_parms[0].length)
12199 				{
12200 					result[result_pos] = 6;
12201 					result_pos += 7;
12202 					PUT_DWORD(&result[result_pos - 6], 0);
12203 					PUT_WORD(&result[result_pos - 2], GOOD);
12204 					if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12205 						      (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12206 					{
12207 						dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12208 								UnMapId(Id), (char *)(FILE_), __LINE__));
12209 						PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12210 						break;
12211 					}
12212 					if (api_parse(&li_participant_struct[0].info[1],
12213 						      li_participant_struct[0].length, "d", li_participant_parms))
12214 					{
12215 						dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12216 								UnMapId(Id), (char *)(FILE_), __LINE__));
12217 						PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12218 						break;
12219 					}
12220 					plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12221 					PUT_DWORD(&result[result_pos - 6], plci_b_id);
12222 					if (sizeof(result) - result_pos < 7)
12223 					{
12224 						dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12225 								UnMapId(Id), (char *)(FILE_), __LINE__));
12226 						PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12227 						break;
12228 					}
12229 					plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12230 					if (plci_b != NULL)
12231 					{
12232 						li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12233 						plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12234 						plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12235 					}
12236 					participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12237 								       (&li_req_parms[0].info[1]));
12238 				}
12239 				result[0] = (byte)(result_pos - 1);
12240 				result[3] = (byte)(result_pos - 4);
12241 				result[6] = (byte)(result_pos - 7);
12242 				i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12243 				if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12244 				    || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12245 				{
12246 					plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12247 					plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12248 				}
12249 				else
12250 					plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12251 				plci->li_plci_b_write_pos = plci_b_write_pos;
12252 			}
12253 			mixer_calculate_coefs(a);
12254 			plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12255 			mixer_notify_update(plci, true);
12256 			sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12257 			      "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12258 			plci->command = 0;
12259 			plci->li_cmd = GET_WORD(li_parms[0].info);
12260 			start_internal_command(Id, plci, mixer_command);
12261 			return (false);
12262 
12263 		case LI_REQ_SILENT_UPDATE:
12264 			if (!plci || !plci->State
12265 			    || !plci->NL.Id || plci->nl_remove_id
12266 			    || (plci->li_bchannel_id == 0)
12267 			    || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12268 			{
12269 				dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12270 						UnMapId(Id), (char *)(FILE_), __LINE__));
12271 				return (false);
12272 			}
12273 			plci_b_write_pos = plci->li_plci_b_write_pos;
12274 			if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12275 			     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12276 			{
12277 				dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12278 						UnMapId(Id), (char *)(FILE_), __LINE__));
12279 				return (false);
12280 			}
12281 			i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12282 			if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12283 			    || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12284 			{
12285 				plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12286 				plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12287 			}
12288 			else
12289 				plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12290 			plci->li_plci_b_write_pos = plci_b_write_pos;
12291 			plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12292 			plci->command = 0;
12293 			plci->li_cmd = GET_WORD(li_parms[0].info);
12294 			start_internal_command(Id, plci, mixer_command);
12295 			return (false);
12296 
12297 		default:
12298 			dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12299 					UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12300 			Info = _FACILITY_NOT_SUPPORTED;
12301 		}
12302 	}
12303 	sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12304 	      "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12305 	return (false);
12306 }
12307 
12308 
mixer_indication_coefs_set(dword Id,PLCI * plci)12309 static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12310 {
12311 	dword d;
12312 	byte result[12];
12313 
12314 	dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12315 			UnMapId(Id), (char *)(FILE_), __LINE__));
12316 
12317 	if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12318 	{
12319 		do
12320 		{
12321 			d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12322 			if (!(d & LI_PLCI_B_SKIP_FLAG))
12323 			{
12324 				if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12325 				{
12326 					if (d & LI_PLCI_B_DISC_FLAG)
12327 					{
12328 						result[0] = 5;
12329 						PUT_WORD(&result[1], LI_IND_DISCONNECT);
12330 						result[3] = 2;
12331 						PUT_WORD(&result[4], _LI_USER_INITIATED);
12332 					}
12333 					else
12334 					{
12335 						result[0] = 7;
12336 						PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12337 						result[3] = 4;
12338 						PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12339 					}
12340 				}
12341 				else
12342 				{
12343 					if (d & LI_PLCI_B_DISC_FLAG)
12344 					{
12345 						result[0] = 9;
12346 						PUT_WORD(&result[1], LI_IND_DISCONNECT);
12347 						result[3] = 6;
12348 						PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12349 						PUT_WORD(&result[8], _LI_USER_INITIATED);
12350 					}
12351 					else
12352 					{
12353 						result[0] = 7;
12354 						PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12355 						result[3] = 4;
12356 						PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12357 					}
12358 				}
12359 				sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12360 				      "ws", SELECTOR_LINE_INTERCONNECT, result);
12361 			}
12362 			plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12363 				0 : plci->li_plci_b_read_pos + 1;
12364 		} while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12365 	}
12366 }
12367 
12368 
mixer_indication_xconnect_from(dword Id,PLCI * plci,byte * msg,word length)12369 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12370 {
12371 	word i, j, ch;
12372 	struct xconnect_transfer_address_s s,   *p;
12373 	DIVA_CAPI_ADAPTER *a;
12374 
12375 	dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12376 			UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12377 
12378 	a = plci->adapter;
12379 	i = 1;
12380 	for (i = 1; i < length; i += 16)
12381 	{
12382 		s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12383 		s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12384 		s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12385 		ch = msg[i + 12] | (msg[i + 13] << 8);
12386 		j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12387 		if (!a->li_pri && (plci->li_bchannel_id == 2))
12388 			j = 1 - j;
12389 		j += a->li_base;
12390 		if (ch & XCONNECT_CHANNEL_PORT_PC)
12391 			p = &(li_config_table[j].send_pc);
12392 		else
12393 			p = &(li_config_table[j].send_b);
12394 		p->card_address.low = s.card_address.low;
12395 		p->card_address.high = s.card_address.high;
12396 		p->offset = s.offset;
12397 		li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12398 	}
12399 	if (plci->internal_command_queue[0]
12400 	    && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12401 		|| (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12402 		|| (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12403 	{
12404 		(*(plci->internal_command_queue[0]))(Id, plci, 0);
12405 		if (!plci->internal_command)
12406 			next_internal_command(Id, plci);
12407 	}
12408 	mixer_notify_update(plci, true);
12409 }
12410 
12411 
mixer_indication_xconnect_to(dword Id,PLCI * plci,byte * msg,word length)12412 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12413 {
12414 
12415 	dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12416 			UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12417 
12418 }
12419 
12420 
mixer_notify_source_removed(PLCI * plci,dword plci_b_id)12421 static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12422 {
12423 	word plci_b_write_pos;
12424 
12425 	plci_b_write_pos = plci->li_plci_b_write_pos;
12426 	if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12427 	     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12428 	{
12429 		dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12430 				(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12431 				(char *)(FILE_), __LINE__));
12432 		return (false);
12433 	}
12434 	plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12435 	plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12436 	plci->li_plci_b_write_pos = plci_b_write_pos;
12437 	return (true);
12438 }
12439 
12440 
mixer_remove(PLCI * plci)12441 static void mixer_remove(PLCI *plci)
12442 {
12443 	DIVA_CAPI_ADAPTER *a;
12444 	PLCI *notify_plci;
12445 	dword plci_b_id;
12446 	word i, j;
12447 
12448 	dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12449 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12450 			(char *)(FILE_), __LINE__));
12451 
12452 	a = plci->adapter;
12453 	plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12454 	if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12455 	{
12456 		if ((plci->li_bchannel_id != 0)
12457 		    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12458 		{
12459 			i = a->li_base + (plci->li_bchannel_id - 1);
12460 			if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12461 			{
12462 				for (j = 0; j < li_total_channels; j++)
12463 				{
12464 					if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12465 					    || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12466 					{
12467 						notify_plci = li_config_table[j].plci;
12468 						if ((notify_plci != NULL)
12469 						    && (notify_plci != plci)
12470 						    && (notify_plci->appl != NULL)
12471 						    && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12472 						    && (notify_plci->State)
12473 						    && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12474 						{
12475 							mixer_notify_source_removed(notify_plci, plci_b_id);
12476 						}
12477 					}
12478 				}
12479 				mixer_clear_config(plci);
12480 				mixer_calculate_coefs(a);
12481 				mixer_notify_update(plci, true);
12482 			}
12483 			li_config_table[i].plci = NULL;
12484 			plci->li_bchannel_id = 0;
12485 		}
12486 	}
12487 }
12488 
12489 
12490 /*------------------------------------------------------------------*/
12491 /* Echo canceller facilities                                        */
12492 /*------------------------------------------------------------------*/
12493 
12494 
ec_write_parameters(PLCI * plci)12495 static void ec_write_parameters(PLCI *plci)
12496 {
12497 	word w;
12498 	byte parameter_buffer[6];
12499 
12500 	dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12501 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12502 			(char *)(FILE_), __LINE__));
12503 
12504 	parameter_buffer[0] = 5;
12505 	parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12506 	PUT_WORD(&parameter_buffer[2], plci->ec_idi_options);
12507 	plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12508 	w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12509 	PUT_WORD(&parameter_buffer[4], w);
12510 	add_p(plci, FTY, parameter_buffer);
12511 	sig_req(plci, TEL_CTRL, 0);
12512 	send_req(plci);
12513 }
12514 
12515 
ec_clear_config(PLCI * plci)12516 static void ec_clear_config(PLCI *plci)
12517 {
12518 
12519 	dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12520 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12521 			(char *)(FILE_), __LINE__));
12522 
12523 	plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12524 		LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12525 	plci->ec_tail_length = 0;
12526 }
12527 
12528 
ec_prepare_switch(dword Id,PLCI * plci)12529 static void ec_prepare_switch(dword Id, PLCI *plci)
12530 {
12531 
12532 	dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12533 			UnMapId(Id), (char *)(FILE_), __LINE__));
12534 
12535 }
12536 
12537 
ec_save_config(dword Id,PLCI * plci,byte Rc)12538 static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12539 {
12540 
12541 	dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12542 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12543 
12544 	return (GOOD);
12545 }
12546 
12547 
ec_restore_config(dword Id,PLCI * plci,byte Rc)12548 static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12549 {
12550 	word Info;
12551 
12552 	dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12553 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12554 
12555 	Info = GOOD;
12556 	if (plci->B1_facilities & B1_FACILITY_EC)
12557 	{
12558 		switch (plci->adjust_b_state)
12559 		{
12560 		case ADJUST_B_RESTORE_EC_1:
12561 			plci->internal_command = plci->adjust_b_command;
12562 			if (plci->sig_req)
12563 			{
12564 				plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12565 				break;
12566 			}
12567 			ec_write_parameters(plci);
12568 			plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12569 			break;
12570 		case ADJUST_B_RESTORE_EC_2:
12571 			if ((Rc != OK) && (Rc != OK_FC))
12572 			{
12573 				dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12574 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12575 				Info = _WRONG_STATE;
12576 				break;
12577 			}
12578 			break;
12579 		}
12580 	}
12581 	return (Info);
12582 }
12583 
12584 
ec_command(dword Id,PLCI * plci,byte Rc)12585 static void ec_command(dword Id, PLCI *plci, byte Rc)
12586 {
12587 	word internal_command, Info;
12588 	byte result[8];
12589 
12590 	dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12591 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12592 			plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12593 
12594 	Info = GOOD;
12595 	if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12596 	{
12597 		result[0] = 2;
12598 		PUT_WORD(&result[1], EC_SUCCESS);
12599 	}
12600 	else
12601 	{
12602 		result[0] = 5;
12603 		PUT_WORD(&result[1], plci->ec_cmd);
12604 		result[3] = 2;
12605 		PUT_WORD(&result[4], GOOD);
12606 	}
12607 	internal_command = plci->internal_command;
12608 	plci->internal_command = 0;
12609 	switch (plci->ec_cmd)
12610 	{
12611 	case EC_ENABLE_OPERATION:
12612 	case EC_FREEZE_COEFFICIENTS:
12613 	case EC_RESUME_COEFFICIENT_UPDATE:
12614 	case EC_RESET_COEFFICIENTS:
12615 		switch (internal_command)
12616 		{
12617 		default:
12618 			adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12619 								  B1_FACILITY_EC), EC_COMMAND_1);
12620 			/* fall through */
12621 		case EC_COMMAND_1:
12622 			if (adjust_b_process(Id, plci, Rc) != GOOD)
12623 			{
12624 				dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12625 						UnMapId(Id), (char *)(FILE_), __LINE__));
12626 				Info = _FACILITY_NOT_SUPPORTED;
12627 				break;
12628 			}
12629 			if (plci->internal_command)
12630 				return;
12631 			/* fall through */
12632 		case EC_COMMAND_2:
12633 			if (plci->sig_req)
12634 			{
12635 				plci->internal_command = EC_COMMAND_2;
12636 				return;
12637 			}
12638 			plci->internal_command = EC_COMMAND_3;
12639 			ec_write_parameters(plci);
12640 			return;
12641 		case EC_COMMAND_3:
12642 			if ((Rc != OK) && (Rc != OK_FC))
12643 			{
12644 				dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12645 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12646 				Info = _FACILITY_NOT_SUPPORTED;
12647 				break;
12648 			}
12649 			break;
12650 		}
12651 		break;
12652 
12653 	case EC_DISABLE_OPERATION:
12654 		switch (internal_command)
12655 		{
12656 		default:
12657 		case EC_COMMAND_1:
12658 			if (plci->B1_facilities & B1_FACILITY_EC)
12659 			{
12660 				if (plci->sig_req)
12661 				{
12662 					plci->internal_command = EC_COMMAND_1;
12663 					return;
12664 				}
12665 				plci->internal_command = EC_COMMAND_2;
12666 				ec_write_parameters(plci);
12667 				return;
12668 			}
12669 			Rc = OK;
12670 			/* fall through */
12671 		case EC_COMMAND_2:
12672 			if ((Rc != OK) && (Rc != OK_FC))
12673 			{
12674 				dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12675 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12676 				Info = _FACILITY_NOT_SUPPORTED;
12677 				break;
12678 			}
12679 			adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12680 								  ~B1_FACILITY_EC), EC_COMMAND_3);
12681 			/* fall through */
12682 		case EC_COMMAND_3:
12683 			if (adjust_b_process(Id, plci, Rc) != GOOD)
12684 			{
12685 				dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12686 						UnMapId(Id), (char *)(FILE_), __LINE__));
12687 				Info = _FACILITY_NOT_SUPPORTED;
12688 				break;
12689 			}
12690 			if (plci->internal_command)
12691 				return;
12692 			break;
12693 		}
12694 		break;
12695 	}
12696 	sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12697 	      "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12698 	      PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12699 }
12700 
12701 
ec_request(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)12702 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
12703 {
12704 	word Info;
12705 	word opt;
12706 	API_PARSE ec_parms[3];
12707 	byte result[16];
12708 
12709 	dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12710 			UnMapId(Id), (char *)(FILE_), __LINE__));
12711 
12712 	Info = GOOD;
12713 	result[0] = 0;
12714 	if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12715 	{
12716 		dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12717 				UnMapId(Id), (char *)(FILE_), __LINE__));
12718 		Info = _FACILITY_NOT_SUPPORTED;
12719 	}
12720 	else
12721 	{
12722 		if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12723 		{
12724 			if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12725 			{
12726 				dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12727 						UnMapId(Id), (char *)(FILE_), __LINE__));
12728 				Info = _WRONG_MESSAGE_FORMAT;
12729 			}
12730 			else
12731 			{
12732 				if (plci == NULL)
12733 				{
12734 					dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12735 							UnMapId(Id), (char *)(FILE_), __LINE__));
12736 					Info = _WRONG_IDENTIFIER;
12737 				}
12738 				else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12739 				{
12740 					dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12741 							UnMapId(Id), (char *)(FILE_), __LINE__));
12742 					Info = _WRONG_STATE;
12743 				}
12744 				else
12745 				{
12746 					plci->command = 0;
12747 					plci->ec_cmd = GET_WORD(ec_parms[0].info);
12748 					plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12749 					result[0] = 2;
12750 					PUT_WORD(&result[1], EC_SUCCESS);
12751 					if (msg[1].length >= 4)
12752 					{
12753 						opt = GET_WORD(&ec_parms[0].info[2]);
12754 						plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12755 									  LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12756 						if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12757 							plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12758 						if (opt & EC_DETECT_DISABLE_TONE)
12759 							plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12760 						if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12761 							plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12762 						if (msg[1].length >= 6)
12763 						{
12764 							plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12765 						}
12766 					}
12767 					switch (plci->ec_cmd)
12768 					{
12769 					case EC_ENABLE_OPERATION:
12770 						plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12771 						start_internal_command(Id, plci, ec_command);
12772 						return (false);
12773 
12774 					case EC_DISABLE_OPERATION:
12775 						plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12776 							LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12777 							LEC_RESET_COEFFICIENTS;
12778 						start_internal_command(Id, plci, ec_command);
12779 						return (false);
12780 
12781 					case EC_FREEZE_COEFFICIENTS:
12782 						plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12783 						start_internal_command(Id, plci, ec_command);
12784 						return (false);
12785 
12786 					case EC_RESUME_COEFFICIENT_UPDATE:
12787 						plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12788 						start_internal_command(Id, plci, ec_command);
12789 						return (false);
12790 
12791 					case EC_RESET_COEFFICIENTS:
12792 						plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12793 						start_internal_command(Id, plci, ec_command);
12794 						return (false);
12795 
12796 					default:
12797 						dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12798 								UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12799 						PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12800 					}
12801 				}
12802 			}
12803 		}
12804 		else
12805 		{
12806 			if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12807 			{
12808 				dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12809 						UnMapId(Id), (char *)(FILE_), __LINE__));
12810 				Info = _WRONG_MESSAGE_FORMAT;
12811 			}
12812 			else
12813 			{
12814 				if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12815 				{
12816 					result[0] = 11;
12817 					PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12818 					result[3] = 8;
12819 					PUT_WORD(&result[4], GOOD);
12820 					PUT_WORD(&result[6], 0x0007);
12821 					PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12822 					PUT_WORD(&result[10], 0);
12823 				}
12824 				else if (plci == NULL)
12825 				{
12826 					dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12827 							UnMapId(Id), (char *)(FILE_), __LINE__));
12828 					Info = _WRONG_IDENTIFIER;
12829 				}
12830 				else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12831 				{
12832 					dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12833 							UnMapId(Id), (char *)(FILE_), __LINE__));
12834 					Info = _WRONG_STATE;
12835 				}
12836 				else
12837 				{
12838 					plci->command = 0;
12839 					plci->ec_cmd = GET_WORD(ec_parms[0].info);
12840 					plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12841 					result[0] = 5;
12842 					PUT_WORD(&result[1], plci->ec_cmd);
12843 					result[3] = 2;
12844 					PUT_WORD(&result[4], GOOD);
12845 					plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12846 								  LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12847 					plci->ec_tail_length = 0;
12848 					if (ec_parms[1].length >= 2)
12849 					{
12850 						opt = GET_WORD(&ec_parms[1].info[1]);
12851 						if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12852 							plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12853 						if (opt & EC_DETECT_DISABLE_TONE)
12854 							plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12855 						if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12856 							plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12857 						if (ec_parms[1].length >= 4)
12858 						{
12859 							plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12860 						}
12861 					}
12862 					switch (plci->ec_cmd)
12863 					{
12864 					case EC_ENABLE_OPERATION:
12865 						plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12866 						start_internal_command(Id, plci, ec_command);
12867 						return (false);
12868 
12869 					case EC_DISABLE_OPERATION:
12870 						plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12871 							LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12872 							LEC_RESET_COEFFICIENTS;
12873 						start_internal_command(Id, plci, ec_command);
12874 						return (false);
12875 
12876 					default:
12877 						dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12878 								UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12879 						PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12880 					}
12881 				}
12882 			}
12883 		}
12884 	}
12885 	sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12886 	      "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12887 	      PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12888 	return (false);
12889 }
12890 
12891 
ec_indication(dword Id,PLCI * plci,byte * msg,word length)12892 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
12893 {
12894 	byte result[8];
12895 
12896 	dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
12897 			UnMapId(Id), (char *)(FILE_), __LINE__));
12898 
12899 	if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
12900 	{
12901 		if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12902 		{
12903 			result[0] = 2;
12904 			PUT_WORD(&result[1], 0);
12905 			switch (msg[1])
12906 			{
12907 			case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
12908 				PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
12909 				break;
12910 			case LEC_DISABLE_TYPE_REVERSED_2100HZ:
12911 				PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
12912 				break;
12913 			case LEC_DISABLE_RELEASED:
12914 				PUT_WORD(&result[1], EC_BYPASS_RELEASED);
12915 				break;
12916 			}
12917 		}
12918 		else
12919 		{
12920 			result[0] = 5;
12921 			PUT_WORD(&result[1], EC_BYPASS_INDICATION);
12922 			result[3] = 2;
12923 			PUT_WORD(&result[4], 0);
12924 			switch (msg[1])
12925 			{
12926 			case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
12927 				PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
12928 				break;
12929 			case LEC_DISABLE_TYPE_REVERSED_2100HZ:
12930 				PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
12931 				break;
12932 			case LEC_DISABLE_RELEASED:
12933 				PUT_WORD(&result[4], EC_BYPASS_RELEASED);
12934 				break;
12935 			}
12936 		}
12937 		sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12938 		      PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12939 	}
12940 }
12941 
12942 
12943 
12944 /*------------------------------------------------------------------*/
12945 /* Advanced voice                                                   */
12946 /*------------------------------------------------------------------*/
12947 
adv_voice_write_coefs(PLCI * plci,word write_command)12948 static void adv_voice_write_coefs(PLCI *plci, word write_command)
12949 {
12950 	DIVA_CAPI_ADAPTER *a;
12951 	word i;
12952 	byte *p;
12953 
12954 	word w, n, j, k;
12955 	byte ch_map[MIXER_CHANNELS_BRI];
12956 
12957 	byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
12958 
12959 	dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
12960 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12961 			(char *)(FILE_), __LINE__, write_command));
12962 
12963 	a = plci->adapter;
12964 	p = coef_buffer + 1;
12965 	*(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
12966 	i = 0;
12967 	while (i + sizeof(word) <= a->adv_voice_coef_length)
12968 	{
12969 		PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
12970 		p += 2;
12971 		i += 2;
12972 	}
12973 	while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
12974 	{
12975 		PUT_WORD(p, 0x8000);
12976 		p += 2;
12977 		i += 2;
12978 	}
12979 
12980 	if (!a->li_pri && (plci->li_bchannel_id == 0))
12981 	{
12982 		if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
12983 		{
12984 			plci->li_bchannel_id = 1;
12985 			li_config_table[a->li_base].plci = plci;
12986 			dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
12987 					(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12988 					(char *)(FILE_), __LINE__, plci->li_bchannel_id));
12989 		}
12990 		else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
12991 		{
12992 			plci->li_bchannel_id = 2;
12993 			li_config_table[a->li_base + 1].plci = plci;
12994 			dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
12995 					(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12996 					(char *)(FILE_), __LINE__, plci->li_bchannel_id));
12997 		}
12998 	}
12999 	if (!a->li_pri && (plci->li_bchannel_id != 0)
13000 	    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13001 	{
13002 		i = a->li_base + (plci->li_bchannel_id - 1);
13003 		switch (write_command)
13004 		{
13005 		case ADV_VOICE_WRITE_ACTIVATION:
13006 			j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13007 			k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13008 			if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13009 			{
13010 				li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13011 				li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13012 			}
13013 			if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13014 			{
13015 				li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13016 				li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13017 				li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13018 				li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13019 			}
13020 			mixer_calculate_coefs(a);
13021 			li_config_table[i].curchnl = li_config_table[i].channel;
13022 			li_config_table[j].curchnl = li_config_table[j].channel;
13023 			if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13024 				li_config_table[k].curchnl = li_config_table[k].channel;
13025 			break;
13026 
13027 		case ADV_VOICE_WRITE_DEACTIVATION:
13028 			for (j = 0; j < li_total_channels; j++)
13029 			{
13030 				li_config_table[i].flag_table[j] = 0;
13031 				li_config_table[j].flag_table[i] = 0;
13032 			}
13033 			k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13034 			for (j = 0; j < li_total_channels; j++)
13035 			{
13036 				li_config_table[k].flag_table[j] = 0;
13037 				li_config_table[j].flag_table[k] = 0;
13038 			}
13039 			if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13040 			{
13041 				k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13042 				for (j = 0; j < li_total_channels; j++)
13043 				{
13044 					li_config_table[k].flag_table[j] = 0;
13045 					li_config_table[j].flag_table[k] = 0;
13046 				}
13047 			}
13048 			mixer_calculate_coefs(a);
13049 			break;
13050 		}
13051 		if (plci->B1_facilities & B1_FACILITY_MIXER)
13052 		{
13053 			w = 0;
13054 			if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13055 				w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13056 			if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13057 				w |= MIXER_FEATURE_ENABLE_TX_DATA;
13058 			if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13059 				w |= MIXER_FEATURE_ENABLE_RX_DATA;
13060 			*(p++) = (byte) w;
13061 			*(p++) = (byte)(w >> 8);
13062 			for (j = 0; j < sizeof(ch_map); j += 2)
13063 			{
13064 				ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13065 				ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13066 			}
13067 			for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13068 			{
13069 				i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13070 				j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13071 				if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13072 				{
13073 					*(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13074 					w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13075 					li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13076 				}
13077 				else
13078 				{
13079 					*(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13080 						a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13081 				}
13082 			}
13083 		}
13084 		else
13085 		{
13086 			for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13087 				*(p++) = a->adv_voice_coef_buffer[i];
13088 		}
13089 	}
13090 	else
13091 
13092 	{
13093 		for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13094 			*(p++) = a->adv_voice_coef_buffer[i];
13095 	}
13096 	coef_buffer[0] = (p - coef_buffer) - 1;
13097 	add_p(plci, FTY, coef_buffer);
13098 	sig_req(plci, TEL_CTRL, 0);
13099 	send_req(plci);
13100 }
13101 
13102 
adv_voice_clear_config(PLCI * plci)13103 static void adv_voice_clear_config(PLCI *plci)
13104 {
13105 	DIVA_CAPI_ADAPTER *a;
13106 
13107 	word i, j;
13108 
13109 
13110 	dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13111 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13112 			(char *)(FILE_), __LINE__));
13113 
13114 	a = plci->adapter;
13115 	if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13116 	{
13117 		a->adv_voice_coef_length = 0;
13118 
13119 		if (!a->li_pri && (plci->li_bchannel_id != 0)
13120 		    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13121 		{
13122 			i = a->li_base + (plci->li_bchannel_id - 1);
13123 			li_config_table[i].curchnl = 0;
13124 			li_config_table[i].channel = 0;
13125 			li_config_table[i].chflags = 0;
13126 			for (j = 0; j < li_total_channels; j++)
13127 			{
13128 				li_config_table[i].flag_table[j] = 0;
13129 				li_config_table[j].flag_table[i] = 0;
13130 				li_config_table[i].coef_table[j] = 0;
13131 				li_config_table[j].coef_table[i] = 0;
13132 			}
13133 			li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13134 			i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13135 			li_config_table[i].curchnl = 0;
13136 			li_config_table[i].channel = 0;
13137 			li_config_table[i].chflags = 0;
13138 			for (j = 0; j < li_total_channels; j++)
13139 			{
13140 				li_config_table[i].flag_table[j] = 0;
13141 				li_config_table[j].flag_table[i] = 0;
13142 				li_config_table[i].coef_table[j] = 0;
13143 				li_config_table[j].coef_table[i] = 0;
13144 			}
13145 			if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13146 			{
13147 				i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13148 				li_config_table[i].curchnl = 0;
13149 				li_config_table[i].channel = 0;
13150 				li_config_table[i].chflags = 0;
13151 				for (j = 0; j < li_total_channels; j++)
13152 				{
13153 					li_config_table[i].flag_table[j] = 0;
13154 					li_config_table[j].flag_table[i] = 0;
13155 					li_config_table[i].coef_table[j] = 0;
13156 					li_config_table[j].coef_table[i] = 0;
13157 				}
13158 			}
13159 		}
13160 
13161 	}
13162 }
13163 
13164 
adv_voice_prepare_switch(dword Id,PLCI * plci)13165 static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13166 {
13167 
13168 	dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13169 			UnMapId(Id), (char *)(FILE_), __LINE__));
13170 
13171 }
13172 
13173 
adv_voice_save_config(dword Id,PLCI * plci,byte Rc)13174 static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13175 {
13176 
13177 	dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13178 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13179 
13180 	return (GOOD);
13181 }
13182 
13183 
adv_voice_restore_config(dword Id,PLCI * plci,byte Rc)13184 static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13185 {
13186 	DIVA_CAPI_ADAPTER *a;
13187 	word Info;
13188 
13189 	dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13190 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13191 
13192 	Info = GOOD;
13193 	a = plci->adapter;
13194 	if ((plci->B1_facilities & B1_FACILITY_VOICE)
13195 	    && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13196 	{
13197 		switch (plci->adjust_b_state)
13198 		{
13199 		case ADJUST_B_RESTORE_VOICE_1:
13200 			plci->internal_command = plci->adjust_b_command;
13201 			if (plci->sig_req)
13202 			{
13203 				plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13204 				break;
13205 			}
13206 			adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13207 			plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13208 			break;
13209 		case ADJUST_B_RESTORE_VOICE_2:
13210 			if ((Rc != OK) && (Rc != OK_FC))
13211 			{
13212 				dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13213 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13214 				Info = _WRONG_STATE;
13215 				break;
13216 			}
13217 			break;
13218 		}
13219 	}
13220 	return (Info);
13221 }
13222 
13223 
13224 
13225 
13226 /*------------------------------------------------------------------*/
13227 /* B1 resource switching                                            */
13228 /*------------------------------------------------------------------*/
13229 
13230 static byte b1_facilities_table[] =
13231 {
13232 	0x00,  /* 0  No bchannel resources      */
13233 	0x00,  /* 1  Codec (automatic law)      */
13234 	0x00,  /* 2  Codec (A-law)              */
13235 	0x00,  /* 3  Codec (y-law)              */
13236 	0x00,  /* 4  HDLC for X.21              */
13237 	0x00,  /* 5  HDLC                       */
13238 	0x00,  /* 6  External Device 0          */
13239 	0x00,  /* 7  External Device 1          */
13240 	0x00,  /* 8  HDLC 56k                   */
13241 	0x00,  /* 9  Transparent                */
13242 	0x00,  /* 10 Loopback to network        */
13243 	0x00,  /* 11 Test pattern to net        */
13244 	0x00,  /* 12 Rate adaptation sync       */
13245 	0x00,  /* 13 Rate adaptation async      */
13246 	0x00,  /* 14 R-Interface                */
13247 	0x00,  /* 15 HDLC 128k leased line      */
13248 	0x00,  /* 16 FAX                        */
13249 	0x00,  /* 17 Modem async                */
13250 	0x00,  /* 18 Modem sync HDLC            */
13251 	0x00,  /* 19 V.110 async HDLC           */
13252 	0x12,  /* 20 Adv voice (Trans,mixer)    */
13253 	0x00,  /* 21 Codec connected to IC      */
13254 	0x0c,  /* 22 Trans,DTMF                 */
13255 	0x1e,  /* 23 Trans,DTMF+mixer           */
13256 	0x1f,  /* 24 Trans,DTMF+mixer+local     */
13257 	0x13,  /* 25 Trans,mixer+local          */
13258 	0x12,  /* 26 HDLC,mixer                 */
13259 	0x12,  /* 27 HDLC 56k,mixer             */
13260 	0x2c,  /* 28 Trans,LEC+DTMF             */
13261 	0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13262 	0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13263 	0x2c,  /* 31 RTP,LEC+DTMF               */
13264 	0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13265 	0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13266 	0x00,  /* 34 Signaling task             */
13267 	0x00,  /* 35 PIAFS                      */
13268 	0x0c,  /* 36 Trans,DTMF+TONE            */
13269 	0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13270 	0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13271 };
13272 
13273 
get_b1_facilities(PLCI * plci,byte b1_resource)13274 static word get_b1_facilities(PLCI *plci, byte b1_resource)
13275 {
13276 	word b1_facilities;
13277 
13278 	b1_facilities = b1_facilities_table[b1_resource];
13279 	if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13280 	{
13281 
13282 		if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13283 		      || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13284 
13285 		{
13286 			if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13287 				b1_facilities |= B1_FACILITY_DTMFX;
13288 			if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13289 				b1_facilities |= B1_FACILITY_DTMFR;
13290 		}
13291 	}
13292 	if ((b1_resource == 17) || (b1_resource == 18))
13293 	{
13294 		if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13295 			b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13296 	}
13297 /*
13298   dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13299   (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13300   (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13301 */
13302 	return (b1_facilities);
13303 }
13304 
13305 
add_b1_facilities(PLCI * plci,byte b1_resource,word b1_facilities)13306 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13307 {
13308 	byte b;
13309 
13310 	switch (b1_resource)
13311 	{
13312 	case 5:
13313 	case 26:
13314 		if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13315 			b = 26;
13316 		else
13317 			b = 5;
13318 		break;
13319 
13320 	case 8:
13321 	case 27:
13322 		if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13323 			b = 27;
13324 		else
13325 			b = 8;
13326 		break;
13327 
13328 	case 9:
13329 	case 20:
13330 	case 22:
13331 	case 23:
13332 	case 24:
13333 	case 25:
13334 	case 28:
13335 	case 29:
13336 	case 30:
13337 	case 36:
13338 	case 37:
13339 	case 38:
13340 		if (b1_facilities & B1_FACILITY_EC)
13341 		{
13342 			if (b1_facilities & B1_FACILITY_LOCAL)
13343 				b = 30;
13344 			else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13345 				b = 29;
13346 			else
13347 				b = 28;
13348 		}
13349 
13350 		else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13351 			 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13352 			     || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13353 		{
13354 			if (b1_facilities & B1_FACILITY_LOCAL)
13355 				b = 38;
13356 			else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13357 				b = 37;
13358 			else
13359 				b = 36;
13360 		}
13361 
13362 		else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13363 			  && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13364 			 || ((b1_facilities & B1_FACILITY_DTMFR)
13365 			     && ((b1_facilities & B1_FACILITY_MIXER)
13366 				 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13367 			 || ((b1_facilities & B1_FACILITY_DTMFX)
13368 			     && ((b1_facilities & B1_FACILITY_MIXER)
13369 				 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13370 		{
13371 			if (b1_facilities & B1_FACILITY_LOCAL)
13372 				b = 24;
13373 			else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13374 				b = 23;
13375 			else
13376 				b = 22;
13377 		}
13378 		else
13379 		{
13380 			if (b1_facilities & B1_FACILITY_LOCAL)
13381 				b = 25;
13382 			else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13383 				b = 20;
13384 			else
13385 				b = 9;
13386 		}
13387 		break;
13388 
13389 	case 31:
13390 	case 32:
13391 	case 33:
13392 		if (b1_facilities & B1_FACILITY_LOCAL)
13393 			b = 33;
13394 		else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13395 			b = 32;
13396 		else
13397 			b = 31;
13398 		break;
13399 
13400 	default:
13401 		b = b1_resource;
13402 	}
13403 	dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13404 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13405 			(char *)(FILE_), __LINE__,
13406 			b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13407 	return (b);
13408 }
13409 
13410 
adjust_b1_facilities(PLCI * plci,byte new_b1_resource,word new_b1_facilities)13411 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13412 {
13413 	word removed_facilities;
13414 
13415 	dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13416 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13417 			(char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13418 			new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13419 
13420 	new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13421 	removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13422 
13423 	if (removed_facilities & B1_FACILITY_EC)
13424 		ec_clear_config(plci);
13425 
13426 
13427 	if (removed_facilities & B1_FACILITY_DTMFR)
13428 	{
13429 		dtmf_rec_clear_config(plci);
13430 		dtmf_parameter_clear_config(plci);
13431 	}
13432 	if (removed_facilities & B1_FACILITY_DTMFX)
13433 		dtmf_send_clear_config(plci);
13434 
13435 
13436 	if (removed_facilities & B1_FACILITY_MIXER)
13437 		mixer_clear_config(plci);
13438 
13439 	if (removed_facilities & B1_FACILITY_VOICE)
13440 		adv_voice_clear_config(plci);
13441 	plci->B1_facilities = new_b1_facilities;
13442 }
13443 
13444 
adjust_b_clear(PLCI * plci)13445 static void adjust_b_clear(PLCI *plci)
13446 {
13447 
13448 	dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13449 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13450 			(char *)(FILE_), __LINE__));
13451 
13452 	plci->adjust_b_restore = false;
13453 }
13454 
13455 
adjust_b_process(dword Id,PLCI * plci,byte Rc)13456 static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13457 {
13458 	word Info;
13459 	byte b1_resource;
13460 	NCCI *ncci_ptr;
13461 	API_PARSE bp[2];
13462 
13463 	dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13464 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13465 
13466 	Info = GOOD;
13467 	switch (plci->adjust_b_state)
13468 	{
13469 	case ADJUST_B_START:
13470 		if ((plci->adjust_b_parms_msg == NULL)
13471 		    && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13472 		    && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13473 						 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13474 		{
13475 			b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13476 				0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13477 			if (b1_resource == plci->B1_resource)
13478 			{
13479 				adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13480 				break;
13481 			}
13482 			if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13483 			{
13484 				dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13485 						UnMapId(Id), (char *)(FILE_), __LINE__,
13486 						plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13487 				Info = _WRONG_STATE;
13488 				break;
13489 			}
13490 		}
13491 		if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13492 		{
13493 
13494 			mixer_prepare_switch(Id, plci);
13495 
13496 
13497 			dtmf_prepare_switch(Id, plci);
13498 			dtmf_parameter_prepare_switch(Id, plci);
13499 
13500 
13501 			ec_prepare_switch(Id, plci);
13502 
13503 			adv_voice_prepare_switch(Id, plci);
13504 		}
13505 		plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13506 		Rc = OK;
13507 		/* fall through */
13508 	case ADJUST_B_SAVE_MIXER_1:
13509 		if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13510 		{
13511 
13512 			Info = mixer_save_config(Id, plci, Rc);
13513 			if ((Info != GOOD) || plci->internal_command)
13514 				break;
13515 
13516 		}
13517 		plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13518 		Rc = OK;
13519 		/* fall through */
13520 	case ADJUST_B_SAVE_DTMF_1:
13521 		if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13522 		{
13523 
13524 			Info = dtmf_save_config(Id, plci, Rc);
13525 			if ((Info != GOOD) || plci->internal_command)
13526 				break;
13527 
13528 		}
13529 		plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13530 		/* fall through */
13531 	case ADJUST_B_REMOVE_L23_1:
13532 		if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13533 		    && plci->NL.Id && !plci->nl_remove_id)
13534 		{
13535 			plci->internal_command = plci->adjust_b_command;
13536 			if (plci->adjust_b_ncci != 0)
13537 			{
13538 				ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13539 				while (ncci_ptr->data_pending)
13540 				{
13541 					plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13542 					data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13543 				}
13544 				while (ncci_ptr->data_ack_pending)
13545 					data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13546 			}
13547 			nl_req_ncci(plci, REMOVE,
13548 				    (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13549 			send_req(plci);
13550 			plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13551 			break;
13552 		}
13553 		plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13554 		Rc = OK;
13555 		/* fall through */
13556 	case ADJUST_B_REMOVE_L23_2:
13557 		if ((Rc != OK) && (Rc != OK_FC))
13558 		{
13559 			dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13560 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13561 			Info = _WRONG_STATE;
13562 			break;
13563 		}
13564 		if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13565 		{
13566 			if (plci_nl_busy(plci))
13567 			{
13568 				plci->internal_command = plci->adjust_b_command;
13569 				break;
13570 			}
13571 		}
13572 		plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13573 		Rc = OK;
13574 		/* fall through */
13575 	case ADJUST_B_SAVE_EC_1:
13576 		if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13577 		{
13578 
13579 			Info = ec_save_config(Id, plci, Rc);
13580 			if ((Info != GOOD) || plci->internal_command)
13581 				break;
13582 
13583 		}
13584 		plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13585 		Rc = OK;
13586 		/* fall through */
13587 	case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13588 		if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13589 		{
13590 
13591 			Info = dtmf_parameter_save_config(Id, plci, Rc);
13592 			if ((Info != GOOD) || plci->internal_command)
13593 				break;
13594 
13595 		}
13596 		plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13597 		Rc = OK;
13598 		/* fall through */
13599 	case ADJUST_B_SAVE_VOICE_1:
13600 		if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13601 		{
13602 			Info = adv_voice_save_config(Id, plci, Rc);
13603 			if ((Info != GOOD) || plci->internal_command)
13604 				break;
13605 		}
13606 		plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13607 		/* fall through */
13608 	case ADJUST_B_SWITCH_L1_1:
13609 		if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13610 		{
13611 			if (plci->sig_req)
13612 			{
13613 				plci->internal_command = plci->adjust_b_command;
13614 				break;
13615 			}
13616 			if (plci->adjust_b_parms_msg != NULL)
13617 				api_load_msg(plci->adjust_b_parms_msg, bp);
13618 			else
13619 				api_load_msg(&plci->B_protocol, bp);
13620 			Info = add_b1(plci, bp,
13621 				      (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13622 				      plci->adjust_b_facilities);
13623 			if (Info != GOOD)
13624 			{
13625 				dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13626 						UnMapId(Id), (char *)(FILE_), __LINE__,
13627 						plci->B1_resource, plci->adjust_b_facilities));
13628 				break;
13629 			}
13630 			plci->internal_command = plci->adjust_b_command;
13631 			sig_req(plci, RESOURCES, 0);
13632 			send_req(plci);
13633 			plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13634 			break;
13635 		}
13636 		plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13637 		Rc = OK;
13638 		/* fall through */
13639 	case ADJUST_B_SWITCH_L1_2:
13640 		if ((Rc != OK) && (Rc != OK_FC))
13641 		{
13642 			dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13643 					UnMapId(Id), (char *)(FILE_), __LINE__,
13644 					Rc, plci->B1_resource, plci->adjust_b_facilities));
13645 			Info = _WRONG_STATE;
13646 			break;
13647 		}
13648 		plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13649 		Rc = OK;
13650 		/* fall through */
13651 	case ADJUST_B_RESTORE_VOICE_1:
13652 	case ADJUST_B_RESTORE_VOICE_2:
13653 		if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13654 		{
13655 			Info = adv_voice_restore_config(Id, plci, Rc);
13656 			if ((Info != GOOD) || plci->internal_command)
13657 				break;
13658 		}
13659 		plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13660 		Rc = OK;
13661 		/* fall through */
13662 	case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13663 	case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13664 		if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13665 		{
13666 
13667 			Info = dtmf_parameter_restore_config(Id, plci, Rc);
13668 			if ((Info != GOOD) || plci->internal_command)
13669 				break;
13670 
13671 		}
13672 		plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13673 		Rc = OK;
13674 		/* fall through */
13675 	case ADJUST_B_RESTORE_EC_1:
13676 	case ADJUST_B_RESTORE_EC_2:
13677 		if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13678 		{
13679 
13680 			Info = ec_restore_config(Id, plci, Rc);
13681 			if ((Info != GOOD) || plci->internal_command)
13682 				break;
13683 
13684 		}
13685 		plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13686 		/* fall through */
13687 	case ADJUST_B_ASSIGN_L23_1:
13688 		if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13689 		{
13690 			if (plci_nl_busy(plci))
13691 			{
13692 				plci->internal_command = plci->adjust_b_command;
13693 				break;
13694 			}
13695 			if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13696 				plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13697 			if (plci->adjust_b_parms_msg != NULL)
13698 				api_load_msg(plci->adjust_b_parms_msg, bp);
13699 			else
13700 				api_load_msg(&plci->B_protocol, bp);
13701 			Info = add_b23(plci, bp);
13702 			if (Info != GOOD)
13703 			{
13704 				dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13705 						UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13706 				break;
13707 			}
13708 			plci->internal_command = plci->adjust_b_command;
13709 			nl_req_ncci(plci, ASSIGN, 0);
13710 			send_req(plci);
13711 			plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13712 			break;
13713 		}
13714 		plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13715 		Rc = ASSIGN_OK;
13716 		/* fall through */
13717 	case ADJUST_B_ASSIGN_L23_2:
13718 		if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13719 		{
13720 			dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13721 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13722 			Info = _WRONG_STATE;
13723 			break;
13724 		}
13725 		if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13726 		{
13727 			if (Rc != ASSIGN_OK)
13728 			{
13729 				plci->internal_command = plci->adjust_b_command;
13730 				break;
13731 			}
13732 		}
13733 		if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13734 		{
13735 			plci->adjust_b_restore = true;
13736 			break;
13737 		}
13738 		plci->adjust_b_state = ADJUST_B_CONNECT_1;
13739 		/* fall through */
13740 	case ADJUST_B_CONNECT_1:
13741 		if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13742 		{
13743 			plci->internal_command = plci->adjust_b_command;
13744 			if (plci_nl_busy(plci))
13745 				break;
13746 			nl_req_ncci(plci, N_CONNECT, 0);
13747 			send_req(plci);
13748 			plci->adjust_b_state = ADJUST_B_CONNECT_2;
13749 			break;
13750 		}
13751 		plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13752 		Rc = OK;
13753 		/* fall through */
13754 	case ADJUST_B_CONNECT_2:
13755 	case ADJUST_B_CONNECT_3:
13756 	case ADJUST_B_CONNECT_4:
13757 		if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13758 		{
13759 			dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13760 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13761 			Info = _WRONG_STATE;
13762 			break;
13763 		}
13764 		if (Rc == OK)
13765 		{
13766 			if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13767 			{
13768 				get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13769 				Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13770 			}
13771 			if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13772 				plci->adjust_b_state = ADJUST_B_CONNECT_3;
13773 			else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13774 				plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13775 		}
13776 		else if (Rc == 0)
13777 		{
13778 			if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13779 				plci->adjust_b_state = ADJUST_B_CONNECT_4;
13780 			else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13781 				plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13782 		}
13783 		if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13784 		{
13785 			plci->internal_command = plci->adjust_b_command;
13786 			break;
13787 		}
13788 		Rc = OK;
13789 		/* fall through */
13790 	case ADJUST_B_RESTORE_DTMF_1:
13791 	case ADJUST_B_RESTORE_DTMF_2:
13792 		if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13793 		{
13794 
13795 			Info = dtmf_restore_config(Id, plci, Rc);
13796 			if ((Info != GOOD) || plci->internal_command)
13797 				break;
13798 
13799 		}
13800 		plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13801 		Rc = OK;
13802 		/* fall through */
13803 	case ADJUST_B_RESTORE_MIXER_1:
13804 	case ADJUST_B_RESTORE_MIXER_2:
13805 	case ADJUST_B_RESTORE_MIXER_3:
13806 	case ADJUST_B_RESTORE_MIXER_4:
13807 	case ADJUST_B_RESTORE_MIXER_5:
13808 	case ADJUST_B_RESTORE_MIXER_6:
13809 	case ADJUST_B_RESTORE_MIXER_7:
13810 		if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13811 		{
13812 
13813 			Info = mixer_restore_config(Id, plci, Rc);
13814 			if ((Info != GOOD) || plci->internal_command)
13815 				break;
13816 
13817 		}
13818 		plci->adjust_b_state = ADJUST_B_END;
13819 	case ADJUST_B_END:
13820 		break;
13821 	}
13822 	return (Info);
13823 }
13824 
13825 
adjust_b1_resource(dword Id,PLCI * plci,API_SAVE * bp_msg,word b1_facilities,word internal_command)13826 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13827 {
13828 
13829 	dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13830 			UnMapId(Id), (char *)(FILE_), __LINE__,
13831 			plci->B1_resource, b1_facilities));
13832 
13833 	plci->adjust_b_parms_msg = bp_msg;
13834 	plci->adjust_b_facilities = b1_facilities;
13835 	plci->adjust_b_command = internal_command;
13836 	plci->adjust_b_ncci = (word)(Id >> 16);
13837 	if ((bp_msg == NULL) && (plci->B1_resource == 0))
13838 		plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13839 	else
13840 		plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13841 	plci->adjust_b_state = ADJUST_B_START;
13842 	dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13843 			UnMapId(Id), (char *)(FILE_), __LINE__,
13844 			plci->B1_resource, b1_facilities));
13845 }
13846 
13847 
adjust_b_restore(dword Id,PLCI * plci,byte Rc)13848 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13849 {
13850 	word internal_command;
13851 
13852 	dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13853 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13854 
13855 	internal_command = plci->internal_command;
13856 	plci->internal_command = 0;
13857 	switch (internal_command)
13858 	{
13859 	default:
13860 		plci->command = 0;
13861 		if (plci->req_in != 0)
13862 		{
13863 			plci->internal_command = ADJUST_B_RESTORE_1;
13864 			break;
13865 		}
13866 		Rc = OK;
13867 		/* fall through */
13868 	case ADJUST_B_RESTORE_1:
13869 		if ((Rc != OK) && (Rc != OK_FC))
13870 		{
13871 			dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13872 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13873 		}
13874 		plci->adjust_b_parms_msg = NULL;
13875 		plci->adjust_b_facilities = plci->B1_facilities;
13876 		plci->adjust_b_command = ADJUST_B_RESTORE_2;
13877 		plci->adjust_b_ncci = (word)(Id >> 16);
13878 		plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13879 		plci->adjust_b_state = ADJUST_B_START;
13880 		dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13881 				UnMapId(Id), (char *)(FILE_), __LINE__));
13882 		/* fall through */
13883 	case ADJUST_B_RESTORE_2:
13884 		if (adjust_b_process(Id, plci, Rc) != GOOD)
13885 		{
13886 			dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13887 					UnMapId(Id), (char *)(FILE_), __LINE__));
13888 		}
13889 		if (plci->internal_command)
13890 			break;
13891 		break;
13892 	}
13893 }
13894 
13895 
reset_b3_command(dword Id,PLCI * plci,byte Rc)13896 static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
13897 {
13898 	word Info;
13899 	word internal_command;
13900 
13901 	dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
13902 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13903 
13904 	Info = GOOD;
13905 	internal_command = plci->internal_command;
13906 	plci->internal_command = 0;
13907 	switch (internal_command)
13908 	{
13909 	default:
13910 		plci->command = 0;
13911 		plci->adjust_b_parms_msg = NULL;
13912 		plci->adjust_b_facilities = plci->B1_facilities;
13913 		plci->adjust_b_command = RESET_B3_COMMAND_1;
13914 		plci->adjust_b_ncci = (word)(Id >> 16);
13915 		plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
13916 		plci->adjust_b_state = ADJUST_B_START;
13917 		dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
13918 				UnMapId(Id), (char *)(FILE_), __LINE__));
13919 		/* fall through */
13920 	case RESET_B3_COMMAND_1:
13921 		Info = adjust_b_process(Id, plci, Rc);
13922 		if (Info != GOOD)
13923 		{
13924 			dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
13925 					UnMapId(Id), (char *)(FILE_), __LINE__));
13926 			break;
13927 		}
13928 		if (plci->internal_command)
13929 			return;
13930 		break;
13931 	}
13932 /*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
13933 	sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
13934 }
13935 
13936 
select_b_command(dword Id,PLCI * plci,byte Rc)13937 static void select_b_command(dword Id, PLCI *plci, byte Rc)
13938 {
13939 	word Info;
13940 	word internal_command;
13941 	byte esc_chi[3];
13942 
13943 	dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
13944 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13945 
13946 	Info = GOOD;
13947 	internal_command = plci->internal_command;
13948 	plci->internal_command = 0;
13949 	switch (internal_command)
13950 	{
13951 	default:
13952 		plci->command = 0;
13953 		plci->adjust_b_parms_msg = &plci->saved_msg;
13954 		if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
13955 			plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
13956 		else
13957 			plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
13958 		plci->adjust_b_command = SELECT_B_COMMAND_1;
13959 		plci->adjust_b_ncci = (word)(Id >> 16);
13960 		if (plci->saved_msg.parms[0].length == 0)
13961 		{
13962 			plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
13963 				ADJUST_B_MODE_NO_RESOURCE;
13964 		}
13965 		else
13966 		{
13967 			plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
13968 				ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
13969 		}
13970 		plci->adjust_b_state = ADJUST_B_START;
13971 		dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
13972 				UnMapId(Id), (char *)(FILE_), __LINE__));
13973 		/* fall through */
13974 	case SELECT_B_COMMAND_1:
13975 		Info = adjust_b_process(Id, plci, Rc);
13976 		if (Info != GOOD)
13977 		{
13978 			dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
13979 					UnMapId(Id), (char *)(FILE_), __LINE__));
13980 			break;
13981 		}
13982 		if (plci->internal_command)
13983 			return;
13984 		if (plci->tel == ADV_VOICE)
13985 		{
13986 			esc_chi[0] = 0x02;
13987 			esc_chi[1] = 0x18;
13988 			esc_chi[2] = plci->b_channel;
13989 			SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
13990 		}
13991 		break;
13992 	}
13993 	sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
13994 }
13995 
13996 
fax_connect_ack_command(dword Id,PLCI * plci,byte Rc)13997 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
13998 {
13999 	word internal_command;
14000 
14001 	dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14002 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14003 
14004 	internal_command = plci->internal_command;
14005 	plci->internal_command = 0;
14006 	switch (internal_command)
14007 	{
14008 	default:
14009 		plci->command = 0; /* fall through */
14010 	case FAX_CONNECT_ACK_COMMAND_1:
14011 		if (plci_nl_busy(plci))
14012 		{
14013 			plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14014 			return;
14015 		}
14016 		plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14017 		plci->NData[0].P = plci->fax_connect_info_buffer;
14018 		plci->NData[0].PLength = plci->fax_connect_info_length;
14019 		plci->NL.X = plci->NData;
14020 		plci->NL.ReqCh = 0;
14021 		plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14022 		plci->adapter->request(&plci->NL);
14023 		return;
14024 	case FAX_CONNECT_ACK_COMMAND_2:
14025 		if ((Rc != OK) && (Rc != OK_FC))
14026 		{
14027 			dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14028 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14029 			break;
14030 		}
14031 	}
14032 	if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14033 	    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14034 	{
14035 		if (plci->B3_prot == 4)
14036 			sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14037 		else
14038 			sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
14039 		plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14040 	}
14041 }
14042 
14043 
fax_edata_ack_command(dword Id,PLCI * plci,byte Rc)14044 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14045 {
14046 	word internal_command;
14047 
14048 	dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14049 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14050 
14051 	internal_command = plci->internal_command;
14052 	plci->internal_command = 0;
14053 	switch (internal_command)
14054 	{
14055 	default:
14056 		plci->command = 0;
14057 		/* fall through */
14058 	case FAX_EDATA_ACK_COMMAND_1:
14059 		if (plci_nl_busy(plci))
14060 		{
14061 			plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14062 			return;
14063 		}
14064 		plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14065 		plci->NData[0].P = plci->fax_connect_info_buffer;
14066 		plci->NData[0].PLength = plci->fax_edata_ack_length;
14067 		plci->NL.X = plci->NData;
14068 		plci->NL.ReqCh = 0;
14069 		plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14070 		plci->adapter->request(&plci->NL);
14071 		return;
14072 	case FAX_EDATA_ACK_COMMAND_2:
14073 		if ((Rc != OK) && (Rc != OK_FC))
14074 		{
14075 			dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14076 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14077 			break;
14078 		}
14079 	}
14080 }
14081 
14082 
fax_connect_info_command(dword Id,PLCI * plci,byte Rc)14083 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14084 {
14085 	word Info;
14086 	word internal_command;
14087 
14088 	dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14089 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14090 
14091 	Info = GOOD;
14092 	internal_command = plci->internal_command;
14093 	plci->internal_command = 0;
14094 	switch (internal_command)
14095 	{
14096 	default:
14097 		plci->command = 0; /* fall through */
14098 	case FAX_CONNECT_INFO_COMMAND_1:
14099 		if (plci_nl_busy(plci))
14100 		{
14101 			plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14102 			return;
14103 		}
14104 		plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14105 		plci->NData[0].P = plci->fax_connect_info_buffer;
14106 		plci->NData[0].PLength = plci->fax_connect_info_length;
14107 		plci->NL.X = plci->NData;
14108 		plci->NL.ReqCh = 0;
14109 		plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14110 		plci->adapter->request(&plci->NL);
14111 		return;
14112 	case FAX_CONNECT_INFO_COMMAND_2:
14113 		if ((Rc != OK) && (Rc != OK_FC))
14114 		{
14115 			dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14116 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14117 			Info = _WRONG_STATE;
14118 			break;
14119 		}
14120 		if (plci_nl_busy(plci))
14121 		{
14122 			plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14123 			return;
14124 		}
14125 		plci->command = _CONNECT_B3_R;
14126 		nl_req_ncci(plci, N_CONNECT, 0);
14127 		send_req(plci);
14128 		return;
14129 	}
14130 	sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14131 }
14132 
14133 
fax_adjust_b23_command(dword Id,PLCI * plci,byte Rc)14134 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14135 {
14136 	word Info;
14137 	word internal_command;
14138 
14139 	dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14140 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14141 
14142 	Info = GOOD;
14143 	internal_command = plci->internal_command;
14144 	plci->internal_command = 0;
14145 	switch (internal_command)
14146 	{
14147 	default:
14148 		plci->command = 0;
14149 		plci->adjust_b_parms_msg = NULL;
14150 		plci->adjust_b_facilities = plci->B1_facilities;
14151 		plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14152 		plci->adjust_b_ncci = (word)(Id >> 16);
14153 		plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14154 		plci->adjust_b_state = ADJUST_B_START;
14155 		dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14156 				UnMapId(Id), (char *)(FILE_), __LINE__));
14157 		/* fall through */
14158 	case FAX_ADJUST_B23_COMMAND_1:
14159 		Info = adjust_b_process(Id, plci, Rc);
14160 		if (Info != GOOD)
14161 		{
14162 			dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14163 					UnMapId(Id), (char *)(FILE_), __LINE__));
14164 			break;
14165 		}
14166 		if (plci->internal_command)
14167 			return;
14168 		/* fall through */
14169 	case FAX_ADJUST_B23_COMMAND_2:
14170 		if (plci_nl_busy(plci))
14171 		{
14172 			plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14173 			return;
14174 		}
14175 		plci->command = _CONNECT_B3_R;
14176 		nl_req_ncci(plci, N_CONNECT, 0);
14177 		send_req(plci);
14178 		return;
14179 	}
14180 	sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14181 }
14182 
14183 
fax_disconnect_command(dword Id,PLCI * plci,byte Rc)14184 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14185 {
14186 	word internal_command;
14187 
14188 	dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14189 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14190 
14191 	internal_command = plci->internal_command;
14192 	plci->internal_command = 0;
14193 	switch (internal_command)
14194 	{
14195 	default:
14196 		plci->command = 0;
14197 		plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14198 		return;
14199 	case FAX_DISCONNECT_COMMAND_1:
14200 	case FAX_DISCONNECT_COMMAND_2:
14201 	case FAX_DISCONNECT_COMMAND_3:
14202 		if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14203 		{
14204 			dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14205 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14206 			break;
14207 		}
14208 		if (Rc == OK)
14209 		{
14210 			if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14211 			    || (internal_command == FAX_DISCONNECT_COMMAND_2))
14212 			{
14213 				plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14214 			}
14215 		}
14216 		else if (Rc == 0)
14217 		{
14218 			if (internal_command == FAX_DISCONNECT_COMMAND_1)
14219 				plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14220 		}
14221 		return;
14222 	}
14223 }
14224 
14225 
14226 
rtp_connect_b3_req_command(dword Id,PLCI * plci,byte Rc)14227 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14228 {
14229 	word Info;
14230 	word internal_command;
14231 
14232 	dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14233 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14234 
14235 	Info = GOOD;
14236 	internal_command = plci->internal_command;
14237 	plci->internal_command = 0;
14238 	switch (internal_command)
14239 	{
14240 	default:
14241 		plci->command = 0; /* fall through */
14242 	case RTP_CONNECT_B3_REQ_COMMAND_1:
14243 		if (plci_nl_busy(plci))
14244 		{
14245 			plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14246 			return;
14247 		}
14248 		plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14249 		nl_req_ncci(plci, N_CONNECT, 0);
14250 		send_req(plci);
14251 		return;
14252 	case RTP_CONNECT_B3_REQ_COMMAND_2:
14253 		if ((Rc != OK) && (Rc != OK_FC))
14254 		{
14255 			dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14256 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14257 			Info = _WRONG_STATE;
14258 			break;
14259 		}
14260 		if (plci_nl_busy(plci))
14261 		{
14262 			plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14263 			return;
14264 		}
14265 		plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14266 		plci->NData[0].PLength = plci->internal_req_buffer[0];
14267 		plci->NData[0].P = plci->internal_req_buffer + 1;
14268 		plci->NL.X = plci->NData;
14269 		plci->NL.ReqCh = 0;
14270 		plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14271 		plci->adapter->request(&plci->NL);
14272 		break;
14273 	case RTP_CONNECT_B3_REQ_COMMAND_3:
14274 		return;
14275 	}
14276 	sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14277 }
14278 
14279 
rtp_connect_b3_res_command(dword Id,PLCI * plci,byte Rc)14280 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14281 {
14282 	word internal_command;
14283 
14284 	dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14285 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14286 
14287 	internal_command = plci->internal_command;
14288 	plci->internal_command = 0;
14289 	switch (internal_command)
14290 	{
14291 	default:
14292 		plci->command = 0; /* fall through */
14293 	case RTP_CONNECT_B3_RES_COMMAND_1:
14294 		if (plci_nl_busy(plci))
14295 		{
14296 			plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14297 			return;
14298 		}
14299 		plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14300 		nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14301 		send_req(plci);
14302 		return;
14303 	case RTP_CONNECT_B3_RES_COMMAND_2:
14304 		if ((Rc != OK) && (Rc != OK_FC))
14305 		{
14306 			dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14307 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14308 			break;
14309 		}
14310 		if (plci_nl_busy(plci))
14311 		{
14312 			plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14313 			return;
14314 		}
14315 		sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14316 		plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14317 		plci->NData[0].PLength = plci->internal_req_buffer[0];
14318 		plci->NData[0].P = plci->internal_req_buffer + 1;
14319 		plci->NL.X = plci->NData;
14320 		plci->NL.ReqCh = 0;
14321 		plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14322 		plci->adapter->request(&plci->NL);
14323 		return;
14324 	case RTP_CONNECT_B3_RES_COMMAND_3:
14325 		return;
14326 	}
14327 }
14328 
14329 
14330 
hold_save_command(dword Id,PLCI * plci,byte Rc)14331 static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14332 {
14333 	byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14334 	word Info;
14335 	word internal_command;
14336 
14337 	dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14338 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14339 
14340 	Info = GOOD;
14341 	internal_command = plci->internal_command;
14342 	plci->internal_command = 0;
14343 	switch (internal_command)
14344 	{
14345 	default:
14346 		if (!plci->NL.Id)
14347 			break;
14348 		plci->command = 0;
14349 		plci->adjust_b_parms_msg = NULL;
14350 		plci->adjust_b_facilities = plci->B1_facilities;
14351 		plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14352 		plci->adjust_b_ncci = (word)(Id >> 16);
14353 		plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14354 		plci->adjust_b_state = ADJUST_B_START;
14355 		dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14356 				UnMapId(Id), (char *)(FILE_), __LINE__));
14357 		/* fall through */
14358 	case HOLD_SAVE_COMMAND_1:
14359 		Info = adjust_b_process(Id, plci, Rc);
14360 		if (Info != GOOD)
14361 		{
14362 			dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14363 					UnMapId(Id), (char *)(FILE_), __LINE__));
14364 			break;
14365 		}
14366 		if (plci->internal_command)
14367 			return;
14368 	}
14369 	sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14370 }
14371 
14372 
retrieve_restore_command(dword Id,PLCI * plci,byte Rc)14373 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14374 {
14375 	byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14376 	word Info;
14377 	word internal_command;
14378 
14379 	dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14380 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14381 
14382 	Info = GOOD;
14383 	internal_command = plci->internal_command;
14384 	plci->internal_command = 0;
14385 	switch (internal_command)
14386 	{
14387 	default:
14388 		plci->command = 0;
14389 		plci->adjust_b_parms_msg = NULL;
14390 		plci->adjust_b_facilities = plci->B1_facilities;
14391 		plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14392 		plci->adjust_b_ncci = (word)(Id >> 16);
14393 		plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14394 		plci->adjust_b_state = ADJUST_B_START;
14395 		dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14396 				UnMapId(Id), (char *)(FILE_), __LINE__));
14397 		/* fall through */
14398 	case RETRIEVE_RESTORE_COMMAND_1:
14399 		Info = adjust_b_process(Id, plci, Rc);
14400 		if (Info != GOOD)
14401 		{
14402 			dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14403 					UnMapId(Id), (char *)(FILE_), __LINE__));
14404 			break;
14405 		}
14406 		if (plci->internal_command)
14407 			return;
14408 	}
14409 	sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14410 }
14411 
14412 
init_b1_config(PLCI * plci)14413 static void init_b1_config(PLCI *plci)
14414 {
14415 
14416 	dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14417 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14418 			(char *)(FILE_), __LINE__));
14419 
14420 	plci->B1_resource = 0;
14421 	plci->B1_facilities = 0;
14422 
14423 	plci->li_bchannel_id = 0;
14424 	mixer_clear_config(plci);
14425 
14426 
14427 	ec_clear_config(plci);
14428 
14429 
14430 	dtmf_rec_clear_config(plci);
14431 	dtmf_send_clear_config(plci);
14432 	dtmf_parameter_clear_config(plci);
14433 
14434 	adv_voice_clear_config(plci);
14435 	adjust_b_clear(plci);
14436 }
14437 
14438 
clear_b1_config(PLCI * plci)14439 static void clear_b1_config(PLCI *plci)
14440 {
14441 
14442 	dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14443 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14444 			(char *)(FILE_), __LINE__));
14445 
14446 	adv_voice_clear_config(plci);
14447 	adjust_b_clear(plci);
14448 
14449 	ec_clear_config(plci);
14450 
14451 
14452 	dtmf_rec_clear_config(plci);
14453 	dtmf_send_clear_config(plci);
14454 	dtmf_parameter_clear_config(plci);
14455 
14456 
14457 	if ((plci->li_bchannel_id != 0)
14458 	    && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14459 	{
14460 		mixer_clear_config(plci);
14461 		li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14462 		plci->li_bchannel_id = 0;
14463 	}
14464 
14465 	plci->B1_resource = 0;
14466 	plci->B1_facilities = 0;
14467 }
14468 
14469 
14470 /* -----------------------------------------------------------------
14471    XON protocol local helpers
14472    ----------------------------------------------------------------- */
channel_flow_control_remove(PLCI * plci)14473 static void channel_flow_control_remove(PLCI *plci) {
14474 	DIVA_CAPI_ADAPTER *a = plci->adapter;
14475 	word i;
14476 	for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14477 		if (a->ch_flow_plci[i] == plci->Id) {
14478 			a->ch_flow_plci[i] = 0;
14479 			a->ch_flow_control[i] = 0;
14480 		}
14481 	}
14482 }
14483 
channel_x_on(PLCI * plci,byte ch)14484 static void channel_x_on(PLCI *plci, byte ch) {
14485 	DIVA_CAPI_ADAPTER *a = plci->adapter;
14486 	if (a->ch_flow_control[ch] & N_XON_SENT) {
14487 		a->ch_flow_control[ch] &= ~N_XON_SENT;
14488 	}
14489 }
14490 
channel_x_off(PLCI * plci,byte ch,byte flag)14491 static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14492 	DIVA_CAPI_ADAPTER *a = plci->adapter;
14493 	if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14494 		a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14495 		a->ch_flow_plci[ch] = plci->Id;
14496 		a->ch_flow_control_pending++;
14497 	}
14498 }
14499 
channel_request_xon(PLCI * plci,byte ch)14500 static void channel_request_xon(PLCI *plci, byte ch) {
14501 	DIVA_CAPI_ADAPTER *a = plci->adapter;
14502 
14503 	if (a->ch_flow_control[ch] & N_CH_XOFF) {
14504 		a->ch_flow_control[ch] |= N_XON_REQ;
14505 		a->ch_flow_control[ch] &= ~N_CH_XOFF;
14506 		a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14507 	}
14508 }
14509 
channel_xmit_extended_xon(PLCI * plci)14510 static void channel_xmit_extended_xon(PLCI *plci) {
14511 	DIVA_CAPI_ADAPTER *a;
14512 	int max_ch = ARRAY_SIZE(a->ch_flow_control);
14513 	int i, one_requested = 0;
14514 
14515 	if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14516 		return;
14517 	}
14518 
14519 	for (i = 0; i < max_ch; i++) {
14520 		if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14521 		    (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14522 		    (plci->Id == a->ch_flow_plci[i])) {
14523 			channel_request_xon(plci, (byte)i);
14524 			one_requested = 1;
14525 		}
14526 	}
14527 
14528 	if (one_requested) {
14529 		channel_xmit_xon(plci);
14530 	}
14531 }
14532 
14533 /*
14534   Try to xmit next X_ON
14535 */
find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER * a,PLCI * plci)14536 static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14537 	int max_ch = ARRAY_SIZE(a->ch_flow_control);
14538 	int i;
14539 
14540 	if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14541 		return (0);
14542 	}
14543 
14544 	if (a->last_flow_control_ch >= max_ch) {
14545 		a->last_flow_control_ch = 1;
14546 	}
14547 	for (i = a->last_flow_control_ch; i < max_ch; i++) {
14548 		if ((a->ch_flow_control[i] & N_XON_REQ) &&
14549 		    (plci->Id == a->ch_flow_plci[i])) {
14550 			a->last_flow_control_ch = i + 1;
14551 			return (i);
14552 		}
14553 	}
14554 
14555 	for (i = 1; i < a->last_flow_control_ch; i++) {
14556 		if ((a->ch_flow_control[i] & N_XON_REQ) &&
14557 		    (plci->Id == a->ch_flow_plci[i])) {
14558 			a->last_flow_control_ch = i + 1;
14559 			return (i);
14560 		}
14561 	}
14562 
14563 	return (0);
14564 }
14565 
channel_xmit_xon(PLCI * plci)14566 static void channel_xmit_xon(PLCI *plci) {
14567 	DIVA_CAPI_ADAPTER *a = plci->adapter;
14568 	byte ch;
14569 
14570 	if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14571 		return;
14572 	}
14573 	if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14574 		return;
14575 	}
14576 	a->ch_flow_control[ch] &= ~N_XON_REQ;
14577 	a->ch_flow_control[ch] |= N_XON_SENT;
14578 
14579 	plci->NL.Req = plci->nl_req = (byte)N_XON;
14580 	plci->NL.ReqCh         = ch;
14581 	plci->NL.X             = plci->NData;
14582 	plci->NL.XNum          = 1;
14583 	plci->NData[0].P       = &plci->RBuffer[0];
14584 	plci->NData[0].PLength = 0;
14585 
14586 	plci->adapter->request(&plci->NL);
14587 }
14588 
channel_can_xon(PLCI * plci,byte ch)14589 static int channel_can_xon(PLCI *plci, byte ch) {
14590 	APPL *APPLptr;
14591 	DIVA_CAPI_ADAPTER *a;
14592 	word NCCIcode;
14593 	dword count;
14594 	word Num;
14595 	word i;
14596 
14597 	APPLptr = plci->appl;
14598 	a = plci->adapter;
14599 
14600 	if (!APPLptr)
14601 		return (0);
14602 
14603 	NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14604 
14605 	/* count all buffers within the Application pool    */
14606 	/* belonging to the same NCCI. XON if a first is    */
14607 	/* used.                                            */
14608 	count = 0;
14609 	Num = 0xffff;
14610 	for (i = 0; i < APPLptr->MaxBuffer; i++) {
14611 		if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14612 		if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14613 	}
14614 	if ((count > 2) || (Num == 0xffff)) {
14615 		return (0);
14616 	}
14617 	return (1);
14618 }
14619 
14620 
14621 /*------------------------------------------------------------------*/
14622 
CPN_filter_ok(byte * cpn,DIVA_CAPI_ADAPTER * a,word offset)14623 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14624 {
14625 	return 1;
14626 }
14627 
14628 
14629 
14630 /**********************************************************************************/
14631 /* function groups the listening applications according to the CIP mask and the   */
14632 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14633 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14634 /* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14635 /* function must be enabled by setting "a->group_optimization_enabled" from the   */
14636 /* OS specific part (per adapter).                                                */
14637 /**********************************************************************************/
group_optimization(DIVA_CAPI_ADAPTER * a,PLCI * plci)14638 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14639 {
14640 	word i, j, k, busy, group_found;
14641 	dword info_mask_group[MAX_CIP_TYPES];
14642 	dword cip_mask_group[MAX_CIP_TYPES];
14643 	word appl_number_group_type[MAX_APPL];
14644 	PLCI *auxplci;
14645 
14646 	/* all APPLs within this inc. call are allowed to dial in */
14647 	bitmap_fill(plci->group_optimization_mask_table, MAX_APPL);
14648 
14649 	if (!a->group_optimization_enabled)
14650 	{
14651 		dbug(1, dprintf("No group optimization"));
14652 		return;
14653 	}
14654 
14655 	dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14656 
14657 	for (i = 0; i < MAX_CIP_TYPES; i++)
14658 	{
14659 		info_mask_group[i] = 0;
14660 		cip_mask_group[i] = 0;
14661 	}
14662 	for (i = 0; i < MAX_APPL; i++)
14663 	{
14664 		appl_number_group_type[i] = 0;
14665 	}
14666 	for (i = 0; i < max_appl; i++) /* check if any multi instance capable application is present */
14667 	{  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14668 		if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14669 		{
14670 			dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14671 			return; /* allow good application unfiltered access */
14672 		}
14673 	}
14674 	for (i = 0; i < max_appl; i++) /* Build CIP Groups */
14675 	{
14676 		if (application[i].Id && a->CIP_Mask[i])
14677 		{
14678 			for (k = 0, busy = false; k < a->max_plci; k++)
14679 			{
14680 				if (a->plci[k].Id)
14681 				{
14682 					auxplci = &a->plci[k];
14683 					if (auxplci->appl == &application[i]) {
14684 						/* application has a busy PLCI */
14685 						busy = true;
14686 						dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14687 					} else if (test_bit(i, plci->c_ind_mask_table)) {
14688 						/* application has an incoming call pending */
14689 						busy = true;
14690 						dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14691 					}
14692 				}
14693 			}
14694 
14695 			for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++)     /* build groups with free applications only */
14696 			{
14697 				if (j == MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14698 				{                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14699 					appl_number_group_type[i] = MAX_CIP_TYPES;
14700 					group_found = true;
14701 					dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14702 				}
14703 				else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14704 				{                                      /* is group already present ?                  */
14705 					appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14706 					group_found = true;
14707 					dbug(1, dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx", appl_number_group_type[i], i + 1, info_mask_group[j]));
14708 				}
14709 				else if (!info_mask_group[j])
14710 				{                                      /* establish a new group                       */
14711 					appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14712 					info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14713 					cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14714 					group_found = true;
14715 					dbug(1, dprintf("New Group 0x%x established with appl 0x%x, CIP=0x%lx", appl_number_group_type[i], i + 1, info_mask_group[j]));
14716 				}
14717 			}
14718 		}
14719 	}
14720 
14721 	for (i = 0; i < max_appl; i++) /* Build group_optimization_mask_table */
14722 	{
14723 		if (appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14724 		{
14725 			if (appl_number_group_type[i] == MAX_CIP_TYPES)
14726 			{
14727 				dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14728 			}
14729 			else
14730 			{
14731 				dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14732 				for (j = i + 1; j < max_appl; j++)   /* search other group members and mark them as busy        */
14733 				{
14734 					if (appl_number_group_type[i] == appl_number_group_type[j])
14735 					{
14736 						dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14737 						/* disable call on other group members */
14738 						__clear_bit(j, plci->group_optimization_mask_table);
14739 						appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14740 					}
14741 				}
14742 			}
14743 		}
14744 		else                                                 /* application should not get a call */
14745 		{
14746 			__clear_bit(i, plci->group_optimization_mask_table);
14747 		}
14748 	}
14749 
14750 }
14751 
14752 
14753 
14754 /* OS notifies the driver about a application Capi_Register */
CapiRegister(word id)14755 word CapiRegister(word id)
14756 {
14757 	word i, j, appls_found;
14758 
14759 	PLCI *plci;
14760 	DIVA_CAPI_ADAPTER *a;
14761 
14762 	for (i = 0, appls_found = 0; i < max_appl; i++)
14763 	{
14764 		if (application[i].Id && (application[i].Id != id))
14765 		{
14766 			appls_found++;                       /* an application has been found */
14767 		}
14768 	}
14769 
14770 	if (appls_found) return true;
14771 	for (i = 0; i < max_adapter; i++)                   /* scan all adapters...    */
14772 	{
14773 		a = &adapter[i];
14774 		if (a->request)
14775 		{
14776 			if (a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14777 			{
14778 				if (!appls_found)           /* first application does a capi register   */
14779 				{
14780 					if ((j = get_plci(a)))                    /* activate L1 of all adapters */
14781 					{
14782 						plci = &a->plci[j - 1];
14783 						plci->command = 0;
14784 						add_p(plci, OAD, "\x01\xfd");
14785 						add_p(plci, CAI, "\x01\x80");
14786 						add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14787 						add_p(plci, SHIFT | 6, NULL);
14788 						add_p(plci, SIN, "\x02\x00\x00");
14789 						plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14790 						sig_req(plci, ASSIGN, DSIG_ID);
14791 						add_p(plci, FTY, "\x02\xff\x07"); /* l1 start */
14792 						sig_req(plci, SIG_CTRL, 0);
14793 						send_req(plci);
14794 					}
14795 				}
14796 			}
14797 		}
14798 	}
14799 	return false;
14800 }
14801 
14802 /*------------------------------------------------------------------*/
14803 
14804 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14805 
VSwitchReqInd(PLCI * plci,dword Id,byte ** parms)14806 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14807 {
14808 	word i;
14809 	/* Format of vswitch_t:
14810 	   0 byte length
14811 	   1 byte VSWITCHIE
14812 	   2 byte VSWITCH_REQ/VSWITCH_IND
14813 	   3 byte reserved
14814 	   4 word VSwitchcommand
14815 	   6 word returnerror
14816 	   8... Params
14817 	*/
14818 	if (!plci ||
14819 	    !plci->appl ||
14820 	    !plci->State ||
14821 	    plci->Sig.Ind == NCR_FACILITY
14822 		)
14823 		return;
14824 
14825 	for (i = 0; i < MAX_MULTI_IE; i++)
14826 	{
14827 		if (!parms[i][0]) continue;
14828 		if (parms[i][0] < 7)
14829 		{
14830 			parms[i][0] = 0; /* kill it */
14831 			continue;
14832 		}
14833 		dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14834 		switch (parms[i][4])
14835 		{
14836 		case VSJOIN:
14837 			if (!plci->relatedPTYPLCI ||
14838 			    (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14839 			{ /* Error */
14840 				break;
14841 			}
14842 			/* remember all necessary informations */
14843 			if (parms[i][0] != 11 || parms[i][8] != 3) /* Length Test */
14844 			{
14845 				break;
14846 			}
14847 			if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14848 			{   /* first indication after ECT-Request on Consultation Call */
14849 				plci->vswitchstate = parms[i][9];
14850 				parms[i][9] = 2; /* State */
14851 				/* now ask first Call to join */
14852 			}
14853 			else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14854 			{ /* Answer of VSWITCH_REQ from first Call */
14855 				plci->vswitchstate = parms[i][9];
14856 				/* tell consultation call to join
14857 				   and the protocol capabilities of the first call */
14858 			}
14859 			else
14860 			{ /* Error */
14861 				break;
14862 			}
14863 			plci->vsprot = parms[i][10]; /* protocol */
14864 			plci->vsprotdialect = parms[i][11]; /* protocoldialect */
14865 			/* send join request to related PLCI */
14866 			parms[i][1] = VSWITCHIE;
14867 			parms[i][2] = VSWITCH_REQ;
14868 
14869 			plci->relatedPTYPLCI->command = 0;
14870 			plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14871 			add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14872 			sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14873 			send_req(plci->relatedPTYPLCI);
14874 			break;
14875 		case VSTRANSPORT:
14876 		default:
14877 			if (plci->relatedPTYPLCI &&
14878 			    plci->vswitchstate == 3 &&
14879 			    plci->relatedPTYPLCI->vswitchstate == 3)
14880 			{
14881 				add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14882 				sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14883 				send_req(plci->relatedPTYPLCI);
14884 			}
14885 			break;
14886 		}
14887 		parms[i][0] = 0; /* kill it */
14888 	}
14889 }
14890 
14891 
14892 /*------------------------------------------------------------------*/
14893 
diva_get_dma_descriptor(PLCI * plci,dword * dma_magic)14894 static int diva_get_dma_descriptor(PLCI *plci, dword   *dma_magic) {
14895 	ENTITY e;
14896 	IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14897 
14898 	if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14899 		return (-1);
14900 	}
14901 
14902 	pReq->xdi_dma_descriptor_operation.Req = 0;
14903 	pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14904 
14905 	pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14906 	pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
14907 	pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14908 	pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
14909 
14910 	e.user[0] = plci->adapter->Id - 1;
14911 	plci->adapter->request((ENTITY *)pReq);
14912 
14913 	if (!pReq->xdi_dma_descriptor_operation.info.operation &&
14914 	    (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
14915 	    pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
14916 		*dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
14917 		dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
14918 				plci->adapter->Id,
14919 				pReq->xdi_dma_descriptor_operation.info.descriptor_number,
14920 				*dma_magic));
14921 		return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
14922 	} else {
14923 		dbug(1, dprintf("dma_alloc failed"));
14924 		return (-1);
14925 	}
14926 }
14927 
diva_free_dma_descriptor(PLCI * plci,int nr)14928 static void diva_free_dma_descriptor(PLCI *plci, int nr) {
14929 	ENTITY e;
14930 	IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14931 
14932 	if (nr < 0) {
14933 		return;
14934 	}
14935 
14936 	pReq->xdi_dma_descriptor_operation.Req = 0;
14937 	pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14938 
14939 	pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
14940 	pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
14941 	pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
14942 	pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
14943 
14944 	e.user[0] = plci->adapter->Id - 1;
14945 	plci->adapter->request((ENTITY *)pReq);
14946 
14947 	if (!pReq->xdi_dma_descriptor_operation.info.operation) {
14948 		dbug(1, dprintf("dma_free(%d)", nr));
14949 	} else {
14950 		dbug(1, dprintf("dma_free failed (%d)", nr));
14951 	}
14952 }
14953 
14954 /*------------------------------------------------------------------*/
14955