1 /*
2  *
3  Copyright (c) Eicon Networks, 2002.
4  *
5  This source file is supplied for the use with
6  Eicon Networks range of DIVA Server Adapters.
7  *
8  Eicon File Revision :    2.1
9  *
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2, or (at your option)
13  any later version.
14  *
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
17  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18  See the GNU General Public License for more details.
19  *
20  You should have received a copy of the GNU General Public License
21  along with this program; if not, write to the Free Software
22  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25 
26 
27 
28 
29 
30 #include "platform.h"
31 #include "di_defs.h"
32 #include "pc.h"
33 #include "capi20.h"
34 #include "divacapi.h"
35 #include "mdm_msg.h"
36 #include "divasync.h"
37 
38 
39 
40 #define FILE_ "MESSAGE.C"
41 #define dprintf
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 /*------------------------------------------------------------------*/
52 /* This is options supported for all adapters that are server by    */
53 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
54 /* and it is not necessary to save it separate for every adapter    */
55 /* Macrose defined here have only local meaning                     */
56 /*------------------------------------------------------------------*/
57 static dword diva_xdi_extended_features = 0;
58 
59 #define DIVA_CAPI_USE_CMA                 0x00000001
60 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR  0x00000002
61 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL  0x00000004
62 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA     0x00000008
63 
64 /*
65   CAPI can request to process all return codes self only if:
66   protocol code supports this && xdi supports this
67 */
68 #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__)   (((__a__)->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL) && ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) && (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
69 
70 /*------------------------------------------------------------------*/
71 /* local function prototypes                                        */
72 /*------------------------------------------------------------------*/
73 
74 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci);
75 static void set_group_ind_mask(PLCI *plci);
76 static void clear_group_ind_mask_bit(PLCI *plci, word b);
77 static byte test_group_ind_mask_bit(PLCI *plci, word b);
78 void AutomaticLaw(DIVA_CAPI_ADAPTER *);
79 word CapiRelease(word);
80 word CapiRegister(word);
81 word api_put(APPL *, CAPI_MSG *);
82 static word api_parse(byte *, word, byte *, API_PARSE *);
83 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out);
84 static void api_load_msg(API_SAVE *in, API_PARSE *out);
85 
86 word api_remove_start(void);
87 void api_remove_complete(void);
88 
89 static void plci_remove(PLCI *);
90 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a);
91 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *, IDI_SYNC_REQ *);
92 
93 void callback(ENTITY *);
94 
95 static void control_rc(PLCI *, byte, byte, byte, byte, byte);
96 static void data_rc(PLCI *, byte);
97 static void data_ack(PLCI *, byte);
98 static void sig_ind(PLCI *);
99 static void SendInfo(PLCI *, dword, byte **, byte);
100 static void SendSetupInfo(APPL *, PLCI *, dword, byte **, byte);
101 static void SendSSExtInd(APPL *, PLCI *plci, dword Id, byte **parms);
102 
103 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms);
104 
105 static void nl_ind(PLCI *);
106 
107 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
108 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
109 static byte connect_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
110 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
111 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
112 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
113 static byte info_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
114 static byte info_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
115 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
116 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
117 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
118 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
119 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
120 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
121 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
122 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
123 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
124 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
125 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
126 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
127 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
128 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
129 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
130 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
131 
132 static word get_plci(DIVA_CAPI_ADAPTER *);
133 static void add_p(PLCI *, byte, byte *);
134 static void add_s(PLCI *plci, byte code, API_PARSE *p);
135 static void add_ss(PLCI *plci, byte code, API_PARSE *p);
136 static void add_ie(PLCI *plci, byte code, byte *p, word p_length);
137 static void add_d(PLCI *, word, byte *);
138 static void add_ai(PLCI *, API_PARSE *);
139 static word add_b1(PLCI *, API_PARSE *, word, word);
140 static word add_b23(PLCI *, API_PARSE *);
141 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms);
142 static void sig_req(PLCI *, byte, byte);
143 static void nl_req_ncci(PLCI *, byte, byte);
144 static void send_req(PLCI *);
145 static void send_data(PLCI *);
146 static word plci_remove_check(PLCI *);
147 static void listen_check(DIVA_CAPI_ADAPTER *);
148 static byte AddInfo(byte **, byte **, byte *, byte *);
149 static byte getChannel(API_PARSE *);
150 static void IndParse(PLCI *, word *, byte **, byte);
151 static byte ie_compare(byte *, byte *);
152 static word find_cip(DIVA_CAPI_ADAPTER *, byte *, byte *);
153 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *, word);
154 
155 /*
156   XON protocol helpers
157 */
158 static void channel_flow_control_remove(PLCI *plci);
159 static void channel_x_off(PLCI *plci, byte ch, byte flag);
160 static void channel_x_on(PLCI *plci, byte ch);
161 static void channel_request_xon(PLCI *plci, byte ch);
162 static void channel_xmit_xon(PLCI *plci);
163 static int channel_can_xon(PLCI *plci, byte ch);
164 static void channel_xmit_extended_xon(PLCI *plci);
165 
166 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type, dword info_mask, byte setupParse);
167 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *, PLCI *, APPL *, byte);
168 static void CodecIdCheck(DIVA_CAPI_ADAPTER *, PLCI *);
169 static void SetVoiceChannel(PLCI *, byte *, DIVA_CAPI_ADAPTER *);
170 static void VoiceChannelOff(PLCI *plci);
171 static void adv_voice_write_coefs(PLCI *plci, word write_command);
172 static void adv_voice_clear_config(PLCI *plci);
173 
174 static word get_b1_facilities(PLCI *plci, byte b1_resource);
175 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities);
176 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities);
177 static word adjust_b_process(dword Id, PLCI *plci, byte Rc);
178 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE *bp_msg, word b1_facilities, word internal_command);
179 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc);
180 static void reset_b3_command(dword Id, PLCI *plci, byte Rc);
181 static void select_b_command(dword Id, PLCI *plci, byte Rc);
182 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc);
183 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc);
184 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc);
185 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc);
186 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc);
187 static void hold_save_command(dword Id, PLCI *plci, byte Rc);
188 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc);
189 static void init_b1_config(PLCI *plci);
190 static void clear_b1_config(PLCI *plci);
191 
192 static void dtmf_command(dword Id, PLCI *plci, byte Rc);
193 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
194 static void dtmf_confirmation(dword Id, PLCI *plci);
195 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length);
196 static void dtmf_parameter_write(PLCI *plci);
197 
198 
199 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id);
200 static void mixer_set_bchannel_id(PLCI *plci, byte *chi);
201 static void mixer_clear_config(PLCI *plci);
202 static void mixer_notify_update(PLCI *plci, byte others);
203 static void mixer_command(dword Id, PLCI *plci, byte Rc);
204 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
205 static void mixer_indication_coefs_set(dword Id, PLCI *plci);
206 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length);
207 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length);
208 static void mixer_remove(PLCI *plci);
209 
210 
211 static void ec_command(dword Id, PLCI *plci, byte Rc);
212 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl, API_PARSE *msg);
213 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length);
214 
215 
216 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc);
217 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc);
218 
219 
220 static int diva_get_dma_descriptor(PLCI *plci, dword *dma_magic);
221 static void diva_free_dma_descriptor(PLCI *plci, int nr);
222 
223 /*------------------------------------------------------------------*/
224 /* external function prototypes                                     */
225 /*------------------------------------------------------------------*/
226 
227 extern byte MapController(byte);
228 extern byte UnMapController(byte);
229 #define MapId(Id)(((Id) & 0xffffff00L) | MapController((byte)(Id)))
230 #define UnMapId(Id)(((Id) & 0xffffff00L) | UnMapController((byte)(Id)))
231 
232 void sendf(APPL *, word, dword, word, byte *, ...);
233 void *TransmitBufferSet(APPL *appl, dword ref);
234 void *TransmitBufferGet(APPL *appl, void *p);
235 void TransmitBufferFree(APPL *appl, void *p);
236 void *ReceiveBufferGet(APPL *appl, int Num);
237 
238 int fax_head_line_time(char *buffer);
239 
240 
241 /*------------------------------------------------------------------*/
242 /* Global data definitions                                          */
243 /*------------------------------------------------------------------*/
244 extern byte max_adapter;
245 extern byte max_appl;
246 extern DIVA_CAPI_ADAPTER *adapter;
247 extern APPL *application;
248 
249 
250 
251 
252 
253 
254 
255 static byte remove_started = false;
256 static PLCI dummy_plci;
257 
258 
259 static struct _ftable {
260 	word command;
261 	byte *format;
262 	byte (*function)(dword, word, DIVA_CAPI_ADAPTER *, PLCI *, APPL *, API_PARSE *);
263 } ftable[] = {
264 	{_DATA_B3_R,                          "dwww",         data_b3_req},
265 	{_DATA_B3_I | RESPONSE,               "w",            data_b3_res},
266 	{_INFO_R,                             "ss",           info_req},
267 	{_INFO_I | RESPONSE,                  "",             info_res},
268 	{_CONNECT_R,                          "wsssssssss",   connect_req},
269 	{_CONNECT_I | RESPONSE,               "wsssss",       connect_res},
270 	{_CONNECT_ACTIVE_I | RESPONSE,        "",             connect_a_res},
271 	{_DISCONNECT_R,                       "s",            disconnect_req},
272 	{_DISCONNECT_I | RESPONSE,            "",             disconnect_res},
273 	{_LISTEN_R,                           "dddss",        listen_req},
274 	{_ALERT_R,                            "s",            alert_req},
275 	{_FACILITY_R,                         "ws",           facility_req},
276 	{_FACILITY_I | RESPONSE,              "ws",           facility_res},
277 	{_CONNECT_B3_R,                       "s",            connect_b3_req},
278 	{_CONNECT_B3_I | RESPONSE,            "ws",           connect_b3_res},
279 	{_CONNECT_B3_ACTIVE_I | RESPONSE,     "",             connect_b3_a_res},
280 	{_DISCONNECT_B3_R,                    "s",            disconnect_b3_req},
281 	{_DISCONNECT_B3_I | RESPONSE,         "",             disconnect_b3_res},
282 	{_RESET_B3_R,                         "s",            reset_b3_req},
283 	{_RESET_B3_I | RESPONSE,              "",             reset_b3_res},
284 	{_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "ws",           connect_b3_t90_a_res},
285 	{_CONNECT_B3_T90_ACTIVE_I | RESPONSE, "",             connect_b3_t90_a_res},
286 	{_SELECT_B_REQ,                       "s",            select_b_req},
287 	{_MANUFACTURER_R,                     "dws",          manufacturer_req},
288 	{_MANUFACTURER_I | RESPONSE,          "dws",          manufacturer_res},
289 	{_MANUFACTURER_I | RESPONSE,          "",             manufacturer_res}
290 };
291 
292 static byte *cip_bc[29][2] = {
293 	{ "",                     ""                     }, /* 0 */
294 	{ "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 1 */
295 	{ "\x02\x88\x90",         "\x02\x88\x90"         }, /* 2 */
296 	{ "\x02\x89\x90",         "\x02\x89\x90"         }, /* 3 */
297 	{ "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 4 */
298 	{ "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 5 */
299 	{ "\x02\x98\x90",         "\x02\x98\x90"         }, /* 6 */
300 	{ "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
301 	{ "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
302 	{ "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 9 */
303 	{ "",                     ""                     }, /* 10 */
304 	{ "",                     ""                     }, /* 11 */
305 	{ "",                     ""                     }, /* 12 */
306 	{ "",                     ""                     }, /* 13 */
307 	{ "",                     ""                     }, /* 14 */
308 	{ "",                     ""                     }, /* 15 */
309 
310 	{ "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 16 */
311 	{ "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 17 */
312 	{ "\x02\x88\x90",         "\x02\x88\x90"         }, /* 18 */
313 	{ "\x02\x88\x90",         "\x02\x88\x90"         }, /* 19 */
314 	{ "\x02\x88\x90",         "\x02\x88\x90"         }, /* 20 */
315 	{ "\x02\x88\x90",         "\x02\x88\x90"         }, /* 21 */
316 	{ "\x02\x88\x90",         "\x02\x88\x90"         }, /* 22 */
317 	{ "\x02\x88\x90",         "\x02\x88\x90"         }, /* 23 */
318 	{ "\x02\x88\x90",         "\x02\x88\x90"         }, /* 24 */
319 	{ "\x02\x88\x90",         "\x02\x88\x90"         }, /* 25 */
320 	{ "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 26 */
321 	{ "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 27 */
322 	{ "\x02\x88\x90",         "\x02\x88\x90"         }  /* 28 */
323 };
324 
325 static byte *cip_hlc[29] = {
326 	"",                           /* 0 */
327 	"",                           /* 1 */
328 	"",                           /* 2 */
329 	"",                           /* 3 */
330 	"",                           /* 4 */
331 	"",                           /* 5 */
332 	"",                           /* 6 */
333 	"",                           /* 7 */
334 	"",                           /* 8 */
335 	"",                           /* 9 */
336 	"",                           /* 10 */
337 	"",                           /* 11 */
338 	"",                           /* 12 */
339 	"",                           /* 13 */
340 	"",                           /* 14 */
341 	"",                           /* 15 */
342 
343 	"\x02\x91\x81",               /* 16 */
344 	"\x02\x91\x84",               /* 17 */
345 	"\x02\x91\xa1",               /* 18 */
346 	"\x02\x91\xa4",               /* 19 */
347 	"\x02\x91\xa8",               /* 20 */
348 	"\x02\x91\xb1",               /* 21 */
349 	"\x02\x91\xb2",               /* 22 */
350 	"\x02\x91\xb5",               /* 23 */
351 	"\x02\x91\xb8",               /* 24 */
352 	"\x02\x91\xc1",               /* 25 */
353 	"\x02\x91\x81",               /* 26 */
354 	"\x03\x91\xe0\x01",           /* 27 */
355 	"\x03\x91\xe0\x02"            /* 28 */
356 };
357 
358 /*------------------------------------------------------------------*/
359 
360 #define V120_HEADER_LENGTH 1
361 #define V120_HEADER_EXTEND_BIT  0x80
362 #define V120_HEADER_BREAK_BIT   0x40
363 #define V120_HEADER_C1_BIT      0x04
364 #define V120_HEADER_C2_BIT      0x08
365 #define V120_HEADER_FLUSH_COND  (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
366 
367 static byte v120_default_header[] =
368 {
369 
370 	0x83                          /*  Ext, BR , res, res, C2 , C1 , B  , F   */
371 
372 };
373 
374 static byte v120_break_header[] =
375 {
376 
377 	0xc3 | V120_HEADER_BREAK_BIT  /*  Ext, BR , res, res, C2 , C1 , B  , F   */
378 
379 };
380 
381 
382 /*------------------------------------------------------------------*/
383 /* API_PUT function                                                 */
384 /*------------------------------------------------------------------*/
385 
api_put(APPL * appl,CAPI_MSG * msg)386 word api_put(APPL *appl, CAPI_MSG *msg)
387 {
388 	word i, j, k, l, n;
389 	word ret;
390 	byte c;
391 	byte controller;
392 	DIVA_CAPI_ADAPTER *a;
393 	PLCI *plci;
394 	NCCI *ncci_ptr;
395 	word ncci;
396 	CAPI_MSG *m;
397 	API_PARSE msg_parms[MAX_MSG_PARMS + 1];
398 
399 	if (msg->header.length < sizeof(msg->header) ||
400 	    msg->header.length > MAX_MSG_SIZE) {
401 		dbug(1, dprintf("bad len"));
402 		return _BAD_MSG;
403 	}
404 
405 	controller = (byte)((msg->header.controller & 0x7f) - 1);
406 
407 	/* controller starts with 0 up to (max_adapter - 1) */
408 	if (controller >= max_adapter)
409 	{
410 		dbug(1, dprintf("invalid ctrl"));
411 		return _BAD_MSG;
412 	}
413 
414 	a = &adapter[controller];
415 	plci = NULL;
416 	if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
417 	{
418 		dbug(1, dprintf("plci=%x", msg->header.plci));
419 		plci = &a->plci[msg->header.plci - 1];
420 		ncci = GET_WORD(&msg->header.ncci);
421 		if (plci->Id
422 		    && (plci->appl
423 			|| (plci->State == INC_CON_PENDING)
424 			|| (plci->State == INC_CON_ALERT)
425 			|| (msg->header.command == (_DISCONNECT_I | RESPONSE)))
426 		    && ((ncci == 0)
427 			|| (msg->header.command == (_DISCONNECT_B3_I | RESPONSE))
428 			|| ((ncci < MAX_NCCI + 1) && (a->ncci_plci[ncci] == plci->Id))))
429 		{
430 			i = plci->msg_in_read_pos;
431 			j = plci->msg_in_write_pos;
432 			if (j >= i)
433 			{
434 				if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
435 					i += MSG_IN_QUEUE_SIZE - j;
436 				else
437 					j = 0;
438 			}
439 			else
440 			{
441 
442 				n = (((CAPI_MSG *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
443 
444 				if (i > MSG_IN_QUEUE_SIZE - n)
445 					i = MSG_IN_QUEUE_SIZE - n + 1;
446 				i -= j;
447 			}
448 
449 			if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
450 
451 			{
452 				dbug(0, dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
453 						msg->header.length, plci->msg_in_write_pos,
454 						plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
455 
456 				return _QUEUE_FULL;
457 			}
458 			c = false;
459 			if ((((byte *) msg) < ((byte *)(plci->msg_in_queue)))
460 			    || (((byte *) msg) >= ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
461 			{
462 				if (plci->msg_in_write_pos != plci->msg_in_read_pos)
463 					c = true;
464 			}
465 			if (msg->header.command == _DATA_B3_R)
466 			{
467 				if (msg->header.length < 20)
468 				{
469 					dbug(1, dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
470 					return _BAD_MSG;
471 				}
472 				ncci_ptr = &(a->ncci[ncci]);
473 				n = ncci_ptr->data_pending;
474 				l = ncci_ptr->data_ack_pending;
475 				k = plci->msg_in_read_pos;
476 				while (k != plci->msg_in_write_pos)
477 				{
478 					if (k == plci->msg_in_wrap_pos)
479 						k = 0;
480 					if ((((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
481 					    && (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
482 					{
483 						n++;
484 						if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
485 							l++;
486 					}
487 
488 					k += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[k]))->header.length +
489 					      MSG_IN_OVERHEAD + 3) & 0xfffc;
490 
491 				}
492 				if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
493 				{
494 					dbug(0, dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
495 							ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
496 
497 					return _QUEUE_FULL;
498 				}
499 				if (plci->req_in || plci->internal_command)
500 				{
501 					if ((((byte *) msg) >= ((byte *)(plci->msg_in_queue)))
502 					    && (((byte *) msg) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
503 					{
504 						dbug(0, dprintf("Q-FULL3(requeue)"));
505 
506 						return _QUEUE_FULL;
507 					}
508 					c = true;
509 				}
510 			}
511 			else
512 			{
513 				if (plci->req_in || plci->internal_command)
514 					c = true;
515 				else
516 				{
517 					plci->command = msg->header.command;
518 					plci->number = msg->header.number;
519 				}
520 			}
521 			if (c)
522 			{
523 				dbug(1, dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
524 						msg->header.command, plci->req_in, plci->internal_command,
525 						msg->header.length, plci->msg_in_write_pos,
526 						plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
527 				if (j == 0)
528 					plci->msg_in_wrap_pos = plci->msg_in_write_pos;
529 				m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
530 				for (i = 0; i < msg->header.length; i++)
531 					((byte *)(plci->msg_in_queue))[j++] = ((byte *) msg)[i];
532 				if (m->header.command == _DATA_B3_R)
533 				{
534 
535 					m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet(appl, m->info.data_b3_req.Data));
536 
537 				}
538 
539 				j = (j + 3) & 0xfffc;
540 
541 				*((APPL **)(&((byte *)(plci->msg_in_queue))[j])) = appl;
542 				plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
543 				return 0;
544 			}
545 		}
546 		else
547 		{
548 			plci = NULL;
549 		}
550 	}
551 	dbug(1, dprintf("com=%x", msg->header.command));
552 
553 	for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
554 	for (i = 0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
555 
556 		if (ftable[i].command == msg->header.command) {
557 			/* break loop if the message is correct, otherwise continue scan  */
558 			/* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */
559 			if (!api_parse(msg->info.b, (word)(msg->header.length - 12), ftable[i].format, msg_parms)) {
560 				ret = 0;
561 				break;
562 			}
563 			for (j = 0; j < MAX_MSG_PARMS + 1; j++) msg_parms[j].length = 0;
564 		}
565 	}
566 	if (ret) {
567 		dbug(1, dprintf("BAD_MSG"));
568 		if (plci) plci->command = 0;
569 		return ret;
570 	}
571 
572 
573 	c = ftable[i].function(GET_DWORD(&msg->header.controller),
574 			       msg->header.number,
575 			       a,
576 			       plci,
577 			       appl,
578 			       msg_parms);
579 
580 	channel_xmit_extended_xon(plci);
581 
582 	if (c == 1) send_req(plci);
583 	if (c == 2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
584 	if (plci && !plci->req_in) plci->command = 0;
585 	return 0;
586 }
587 
588 
589 /*------------------------------------------------------------------*/
590 /* api_parse function, check the format of api messages             */
591 /*------------------------------------------------------------------*/
592 
api_parse(byte * msg,word length,byte * format,API_PARSE * parms)593 static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
594 {
595 	word i;
596 	word p;
597 
598 	for (i = 0, p = 0; format[i]; i++) {
599 		if (parms)
600 		{
601 			parms[i].info = &msg[p];
602 		}
603 		switch (format[i]) {
604 		case 'b':
605 			p += 1;
606 			break;
607 		case 'w':
608 			p += 2;
609 			break;
610 		case 'd':
611 			p += 4;
612 			break;
613 		case 's':
614 			if (msg[p] == 0xff) {
615 				parms[i].info += 2;
616 				parms[i].length = msg[p + 1] + (msg[p + 2] << 8);
617 				p += (parms[i].length + 3);
618 			}
619 			else {
620 				parms[i].length = msg[p];
621 				p += (parms[i].length + 1);
622 			}
623 			break;
624 		}
625 
626 		if (p > length) return true;
627 	}
628 	if (parms) parms[i].info = NULL;
629 	return false;
630 }
631 
api_save_msg(API_PARSE * in,byte * format,API_SAVE * out)632 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
633 {
634 	word i, j, n = 0;
635 	byte *p;
636 
637 	p = out->info;
638 	for (i = 0; format[i] != '\0'; i++)
639 	{
640 		out->parms[i].info = p;
641 		out->parms[i].length = in[i].length;
642 		switch (format[i])
643 		{
644 		case 'b':
645 			n = 1;
646 			break;
647 		case 'w':
648 			n = 2;
649 			break;
650 		case 'd':
651 			n = 4;
652 			break;
653 		case 's':
654 			n = in[i].length + 1;
655 			break;
656 		}
657 		for (j = 0; j < n; j++)
658 			*(p++) = in[i].info[j];
659 	}
660 	out->parms[i].info = NULL;
661 	out->parms[i].length = 0;
662 }
663 
api_load_msg(API_SAVE * in,API_PARSE * out)664 static void api_load_msg(API_SAVE *in, API_PARSE *out)
665 {
666 	word i;
667 
668 	i = 0;
669 	do
670 	{
671 		out[i].info = in->parms[i].info;
672 		out[i].length = in->parms[i].length;
673 	} while (in->parms[i++].info);
674 }
675 
676 
677 /*------------------------------------------------------------------*/
678 /* CAPI remove function                                             */
679 /*------------------------------------------------------------------*/
680 
api_remove_start(void)681 word api_remove_start(void)
682 {
683 	word i;
684 	word j;
685 
686 	if (!remove_started) {
687 		remove_started = true;
688 		for (i = 0; i < max_adapter; i++) {
689 			if (adapter[i].request) {
690 				for (j = 0; j < adapter[i].max_plci; j++) {
691 					if (adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
692 				}
693 			}
694 		}
695 		return 1;
696 	}
697 	else {
698 		for (i = 0; i < max_adapter; i++) {
699 			if (adapter[i].request) {
700 				for (j = 0; j < adapter[i].max_plci; j++) {
701 					if (adapter[i].plci[j].Sig.Id) return 1;
702 				}
703 			}
704 		}
705 	}
706 	api_remove_complete();
707 	return 0;
708 }
709 
710 
711 /*------------------------------------------------------------------*/
712 /* internal command queue                                           */
713 /*------------------------------------------------------------------*/
714 
init_internal_command_queue(PLCI * plci)715 static void init_internal_command_queue(PLCI *plci)
716 {
717 	word i;
718 
719 	dbug(1, dprintf("%s,%d: init_internal_command_queue",
720 			(char *)(FILE_), __LINE__));
721 
722 	plci->internal_command = 0;
723 	for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
724 		plci->internal_command_queue[i] = NULL;
725 }
726 
727 
start_internal_command(dword Id,PLCI * plci,t_std_internal_command command_function)728 static void start_internal_command(dword Id, PLCI *plci, t_std_internal_command command_function)
729 {
730 	word i;
731 
732 	dbug(1, dprintf("[%06lx] %s,%d: start_internal_command",
733 			UnMapId(Id), (char *)(FILE_), __LINE__));
734 
735 	if (plci->internal_command == 0)
736 	{
737 		plci->internal_command_queue[0] = command_function;
738 		(*command_function)(Id, plci, OK);
739 	}
740 	else
741 	{
742 		i = 1;
743 		while (plci->internal_command_queue[i] != NULL)
744 			i++;
745 		plci->internal_command_queue[i] = command_function;
746 	}
747 }
748 
749 
next_internal_command(dword Id,PLCI * plci)750 static void next_internal_command(dword Id, PLCI *plci)
751 {
752 	word i;
753 
754 	dbug(1, dprintf("[%06lx] %s,%d: next_internal_command",
755 			UnMapId(Id), (char *)(FILE_), __LINE__));
756 
757 	plci->internal_command = 0;
758 	plci->internal_command_queue[0] = NULL;
759 	while (plci->internal_command_queue[1] != NULL)
760 	{
761 		for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
762 			plci->internal_command_queue[i] = plci->internal_command_queue[i + 1];
763 		plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
764 		(*(plci->internal_command_queue[0]))(Id, plci, OK);
765 		if (plci->internal_command != 0)
766 			return;
767 		plci->internal_command_queue[0] = NULL;
768 	}
769 }
770 
771 
772 /*------------------------------------------------------------------*/
773 /* NCCI allocate/remove function                                    */
774 /*------------------------------------------------------------------*/
775 
776 static dword ncci_mapping_bug = 0;
777 
get_ncci(PLCI * plci,byte ch,word force_ncci)778 static word get_ncci(PLCI *plci, byte ch, word force_ncci)
779 {
780 	DIVA_CAPI_ADAPTER *a;
781 	word ncci, i, j, k;
782 
783 	a = plci->adapter;
784 	if (!ch || a->ch_ncci[ch])
785 	{
786 		ncci_mapping_bug++;
787 		dbug(1, dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
788 				ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
789 		ncci = ch;
790 	}
791 	else
792 	{
793 		if (force_ncci)
794 			ncci = force_ncci;
795 		else
796 		{
797 			if ((ch < MAX_NCCI + 1) && !a->ncci_ch[ch])
798 				ncci = ch;
799 			else
800 			{
801 				ncci = 1;
802 				while ((ncci < MAX_NCCI + 1) && a->ncci_ch[ncci])
803 					ncci++;
804 				if (ncci == MAX_NCCI + 1)
805 				{
806 					ncci_mapping_bug++;
807 					i = 1;
808 					do
809 					{
810 						j = 1;
811 						while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i))
812 							j++;
813 						k = j;
814 						if (j < MAX_NCCI + 1)
815 						{
816 							do
817 							{
818 								j++;
819 							} while ((j < MAX_NCCI + 1) && (a->ncci_ch[j] != i));
820 						}
821 					} while ((i < MAX_NL_CHANNEL + 1) && (j < MAX_NCCI + 1));
822 					if (i < MAX_NL_CHANNEL + 1)
823 					{
824 						dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
825 								ncci_mapping_bug, ch, force_ncci, i, k, j));
826 					}
827 					else
828 					{
829 						dbug(1, dprintf("NCCI mapping overflow %ld %02x %02x",
830 								ncci_mapping_bug, ch, force_ncci));
831 					}
832 					ncci = ch;
833 				}
834 			}
835 			a->ncci_plci[ncci] = plci->Id;
836 			a->ncci_state[ncci] = IDLE;
837 			if (!plci->ncci_ring_list)
838 				plci->ncci_ring_list = ncci;
839 			else
840 				a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
841 			a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
842 		}
843 		a->ncci_ch[ncci] = ch;
844 		a->ch_ncci[ch] = (byte) ncci;
845 		dbug(1, dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
846 				ncci_mapping_bug, ch, force_ncci, ch, ncci));
847 	}
848 	return (ncci);
849 }
850 
851 
ncci_free_receive_buffers(PLCI * plci,word ncci)852 static void ncci_free_receive_buffers(PLCI *plci, word ncci)
853 {
854 	DIVA_CAPI_ADAPTER *a;
855 	APPL *appl;
856 	word i, ncci_code;
857 	dword Id;
858 
859 	a = plci->adapter;
860 	Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
861 	if (ncci)
862 	{
863 		if (a->ncci_plci[ncci] == plci->Id)
864 		{
865 			if (!plci->appl)
866 			{
867 				ncci_mapping_bug++;
868 				dbug(1, dprintf("NCCI mapping appl expected %ld %08lx",
869 						ncci_mapping_bug, Id));
870 			}
871 			else
872 			{
873 				appl = plci->appl;
874 				ncci_code = ncci | (((word) a->Id) << 8);
875 				for (i = 0; i < appl->MaxBuffer; i++)
876 				{
877 					if ((appl->DataNCCI[i] == ncci_code)
878 					    && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
879 					{
880 						appl->DataNCCI[i] = 0;
881 					}
882 				}
883 			}
884 		}
885 	}
886 	else
887 	{
888 		for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
889 		{
890 			if (a->ncci_plci[ncci] == plci->Id)
891 			{
892 				if (!plci->appl)
893 				{
894 					ncci_mapping_bug++;
895 					dbug(1, dprintf("NCCI mapping no appl %ld %08lx",
896 							ncci_mapping_bug, Id));
897 				}
898 				else
899 				{
900 					appl = plci->appl;
901 					ncci_code = ncci | (((word) a->Id) << 8);
902 					for (i = 0; i < appl->MaxBuffer; i++)
903 					{
904 						if ((appl->DataNCCI[i] == ncci_code)
905 						    && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
906 						{
907 							appl->DataNCCI[i] = 0;
908 						}
909 					}
910 				}
911 			}
912 		}
913 	}
914 }
915 
916 
cleanup_ncci_data(PLCI * plci,word ncci)917 static void cleanup_ncci_data(PLCI *plci, word ncci)
918 {
919 	NCCI *ncci_ptr;
920 
921 	if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
922 	{
923 		ncci_ptr = &(plci->adapter->ncci[ncci]);
924 		if (plci->appl)
925 		{
926 			while (ncci_ptr->data_pending != 0)
927 			{
928 				if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
929 					TransmitBufferFree(plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
930 				(ncci_ptr->data_out)++;
931 				if (ncci_ptr->data_out == MAX_DATA_B3)
932 					ncci_ptr->data_out = 0;
933 				(ncci_ptr->data_pending)--;
934 			}
935 		}
936 		ncci_ptr->data_out = 0;
937 		ncci_ptr->data_pending = 0;
938 		ncci_ptr->data_ack_out = 0;
939 		ncci_ptr->data_ack_pending = 0;
940 	}
941 }
942 
943 
ncci_remove(PLCI * plci,word ncci,byte preserve_ncci)944 static void ncci_remove(PLCI *plci, word ncci, byte preserve_ncci)
945 {
946 	DIVA_CAPI_ADAPTER *a;
947 	dword Id;
948 	word i;
949 
950 	a = plci->adapter;
951 	Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
952 	if (!preserve_ncci)
953 		ncci_free_receive_buffers(plci, ncci);
954 	if (ncci)
955 	{
956 		if (a->ncci_plci[ncci] != plci->Id)
957 		{
958 			ncci_mapping_bug++;
959 			dbug(1, dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
960 					ncci_mapping_bug, Id, preserve_ncci));
961 		}
962 		else
963 		{
964 			cleanup_ncci_data(plci, ncci);
965 			dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
966 					ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
967 			a->ch_ncci[a->ncci_ch[ncci]] = 0;
968 			if (!preserve_ncci)
969 			{
970 				a->ncci_ch[ncci] = 0;
971 				a->ncci_plci[ncci] = 0;
972 				a->ncci_state[ncci] = IDLE;
973 				i = plci->ncci_ring_list;
974 				while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
975 					i = a->ncci_next[i];
976 				if ((i != 0) && (a->ncci_next[i] == ncci))
977 				{
978 					if (i == ncci)
979 						plci->ncci_ring_list = 0;
980 					else if (plci->ncci_ring_list == ncci)
981 						plci->ncci_ring_list = i;
982 					a->ncci_next[i] = a->ncci_next[ncci];
983 				}
984 				a->ncci_next[ncci] = 0;
985 			}
986 		}
987 	}
988 	else
989 	{
990 		for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
991 		{
992 			if (a->ncci_plci[ncci] == plci->Id)
993 			{
994 				cleanup_ncci_data(plci, ncci);
995 				dbug(1, dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
996 						ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
997 				a->ch_ncci[a->ncci_ch[ncci]] = 0;
998 				if (!preserve_ncci)
999 				{
1000 					a->ncci_ch[ncci] = 0;
1001 					a->ncci_plci[ncci] = 0;
1002 					a->ncci_state[ncci] = IDLE;
1003 					a->ncci_next[ncci] = 0;
1004 				}
1005 			}
1006 		}
1007 		if (!preserve_ncci)
1008 			plci->ncci_ring_list = 0;
1009 	}
1010 }
1011 
1012 
1013 /*------------------------------------------------------------------*/
1014 /* PLCI remove function                                             */
1015 /*------------------------------------------------------------------*/
1016 
plci_free_msg_in_queue(PLCI * plci)1017 static void plci_free_msg_in_queue(PLCI *plci)
1018 {
1019 	word i;
1020 
1021 	if (plci->appl)
1022 	{
1023 		i = plci->msg_in_read_pos;
1024 		while (i != plci->msg_in_write_pos)
1025 		{
1026 			if (i == plci->msg_in_wrap_pos)
1027 				i = 0;
1028 			if (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1029 			{
1030 
1031 				TransmitBufferFree(plci->appl,
1032 						   (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1033 
1034 			}
1035 
1036 			i += (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->header.length +
1037 			      MSG_IN_OVERHEAD + 3) & 0xfffc;
1038 
1039 		}
1040 	}
1041 	plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1042 	plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1043 	plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1044 }
1045 
1046 
plci_remove(PLCI * plci)1047 static void plci_remove(PLCI *plci)
1048 {
1049 
1050 	if (!plci) {
1051 		dbug(1, dprintf("plci_remove(no plci)"));
1052 		return;
1053 	}
1054 	init_internal_command_queue(plci);
1055 	dbug(1, dprintf("plci_remove(%x,tel=%x)", plci->Id, plci->tel));
1056 	if (plci_remove_check(plci))
1057 	{
1058 		return;
1059 	}
1060 	if (plci->Sig.Id == 0xff)
1061 	{
1062 		dbug(1, dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1063 		if (plci->NL.Id && !plci->nl_remove_id)
1064 		{
1065 			nl_req_ncci(plci, REMOVE, 0);
1066 			send_req(plci);
1067 		}
1068 	}
1069 	else
1070 	{
1071 		if (!plci->sig_remove_id
1072 		    && (plci->Sig.Id
1073 			|| (plci->req_in != plci->req_out)
1074 			|| (plci->nl_req || plci->sig_req)))
1075 		{
1076 			sig_req(plci, HANGUP, 0);
1077 			send_req(plci);
1078 		}
1079 	}
1080 	ncci_remove(plci, 0, false);
1081 	plci_free_msg_in_queue(plci);
1082 
1083 	plci->channels = 0;
1084 	plci->appl = NULL;
1085 	if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1086 		plci->State = OUTG_DIS_PENDING;
1087 }
1088 
1089 /*------------------------------------------------------------------*/
1090 /* Application Group function helpers                               */
1091 /*------------------------------------------------------------------*/
1092 
set_group_ind_mask(PLCI * plci)1093 static void set_group_ind_mask(PLCI *plci)
1094 {
1095 	word i;
1096 
1097 	for (i = 0; i < C_IND_MASK_DWORDS; i++)
1098 		plci->group_optimization_mask_table[i] = 0xffffffffL;
1099 }
1100 
clear_group_ind_mask_bit(PLCI * plci,word b)1101 static void clear_group_ind_mask_bit(PLCI *plci, word b)
1102 {
1103 	plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1104 }
1105 
test_group_ind_mask_bit(PLCI * plci,word b)1106 static byte test_group_ind_mask_bit(PLCI *plci, word b)
1107 {
1108 	return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1109 }
1110 
1111 /*------------------------------------------------------------------*/
1112 /* c_ind_mask operations for arbitrary MAX_APPL                     */
1113 /*------------------------------------------------------------------*/
1114 
clear_c_ind_mask(PLCI * plci)1115 static void clear_c_ind_mask(PLCI *plci)
1116 {
1117 	word i;
1118 
1119 	for (i = 0; i < C_IND_MASK_DWORDS; i++)
1120 		plci->c_ind_mask_table[i] = 0;
1121 }
1122 
c_ind_mask_empty(PLCI * plci)1123 static byte c_ind_mask_empty(PLCI *plci)
1124 {
1125 	word i;
1126 
1127 	i = 0;
1128 	while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1129 		i++;
1130 	return (i == C_IND_MASK_DWORDS);
1131 }
1132 
set_c_ind_mask_bit(PLCI * plci,word b)1133 static void set_c_ind_mask_bit(PLCI *plci, word b)
1134 {
1135 	plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1136 }
1137 
clear_c_ind_mask_bit(PLCI * plci,word b)1138 static void clear_c_ind_mask_bit(PLCI *plci, word b)
1139 {
1140 	plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1141 }
1142 
test_c_ind_mask_bit(PLCI * plci,word b)1143 static byte test_c_ind_mask_bit(PLCI *plci, word b)
1144 {
1145 	return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1146 }
1147 
dump_c_ind_mask(PLCI * plci)1148 static void dump_c_ind_mask(PLCI *plci)
1149 {
1150 	static char hex_digit_table[0x10] =
1151 		{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
1152 	word i, j, k;
1153 	dword d;
1154 	char *p;
1155 	char buf[40];
1156 
1157 	for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1158 	{
1159 		p = buf + 36;
1160 		*p = '\0';
1161 		for (j = 0; j < 4; j++)
1162 		{
1163 			if (i + j < C_IND_MASK_DWORDS)
1164 			{
1165 				d = plci->c_ind_mask_table[i + j];
1166 				for (k = 0; k < 8; k++)
1167 				{
1168 					*(--p) = hex_digit_table[d & 0xf];
1169 					d >>= 4;
1170 				}
1171 			}
1172 			else if (i != 0)
1173 			{
1174 				for (k = 0; k < 8; k++)
1175 					*(--p) = ' ';
1176 			}
1177 			*(--p) = ' ';
1178 		}
1179 		dbug(1, dprintf("c_ind_mask =%s", (char *) p));
1180 	}
1181 }
1182 
1183 
1184 
1185 
1186 
1187 #define dump_plcis(a)
1188 
1189 
1190 
1191 /*------------------------------------------------------------------*/
1192 /* translation function for each message                            */
1193 /*------------------------------------------------------------------*/
1194 
connect_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)1195 static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1196 			PLCI *plci, APPL *appl, API_PARSE *parms)
1197 {
1198 	word ch;
1199 	word i;
1200 	word Info;
1201 	byte LinkLayer;
1202 	API_PARSE *ai;
1203 	API_PARSE *bp;
1204 	API_PARSE ai_parms[5];
1205 	word channel = 0;
1206 	dword ch_mask;
1207 	byte m;
1208 	static byte esc_chi[35] = {0x02, 0x18, 0x01};
1209 	static byte lli[2] = {0x01, 0x00};
1210 	byte noCh = 0;
1211 	word dir = 0;
1212 	byte *p_chi = "";
1213 
1214 	for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1215 
1216 	dbug(1, dprintf("connect_req(%d)", parms->length));
1217 	Info = _WRONG_IDENTIFIER;
1218 	if (a)
1219 	{
1220 		if (a->adapter_disabled)
1221 		{
1222 			dbug(1, dprintf("adapter disabled"));
1223 			Id = ((word)1 << 8) | a->Id;
1224 			sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
1225 			sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1226 			return false;
1227 		}
1228 		Info = _OUT_OF_PLCI;
1229 		if ((i = get_plci(a)))
1230 		{
1231 			Info = 0;
1232 			plci = &a->plci[i - 1];
1233 			plci->appl = appl;
1234 			plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1235 			/* check 'external controller' bit for codec support */
1236 			if (Id & EXT_CONTROLLER)
1237 			{
1238 				if (AdvCodecSupport(a, plci, appl, 0))
1239 				{
1240 					plci->Id = 0;
1241 					sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1242 					return 2;
1243 				}
1244 			}
1245 			ai = &parms[9];
1246 			bp = &parms[5];
1247 			ch = 0;
1248 			if (bp->length)LinkLayer = bp->info[3];
1249 			else LinkLayer = 0;
1250 			if (ai->length)
1251 			{
1252 				ch = 0xffff;
1253 				if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1254 				{
1255 					ch = 0;
1256 					if (ai_parms[0].length)
1257 					{
1258 						ch = GET_WORD(ai_parms[0].info + 1);
1259 						if (ch > 4) ch = 0; /* safety -> ignore ChannelID */
1260 						if (ch == 4) /* explizit CHI in message */
1261 						{
1262 							/* check length of B-CH struct */
1263 							if ((ai_parms[0].info)[3] >= 1)
1264 							{
1265 								if ((ai_parms[0].info)[4] == CHI)
1266 								{
1267 									p_chi = &((ai_parms[0].info)[5]);
1268 								}
1269 								else
1270 								{
1271 									p_chi = &((ai_parms[0].info)[3]);
1272 								}
1273 								if (p_chi[0] > 35) /* check length of channel ID */
1274 								{
1275 									Info = _WRONG_MESSAGE_FORMAT;
1276 								}
1277 							}
1278 							else Info = _WRONG_MESSAGE_FORMAT;
1279 						}
1280 
1281 						if (ch == 3 && ai_parms[0].length >= 7 && ai_parms[0].length <= 36)
1282 						{
1283 							dir = GET_WORD(ai_parms[0].info + 3);
1284 							ch_mask = 0;
1285 							m = 0x3f;
1286 							for (i = 0; i + 5 <= ai_parms[0].length; i++)
1287 							{
1288 								if (ai_parms[0].info[i + 5] != 0)
1289 								{
1290 									if ((ai_parms[0].info[i + 5] | m) != 0xff)
1291 										Info = _WRONG_MESSAGE_FORMAT;
1292 									else
1293 									{
1294 										if (ch_mask == 0)
1295 											channel = i;
1296 										ch_mask |= 1L << i;
1297 									}
1298 								}
1299 								m = 0;
1300 							}
1301 							if (ch_mask == 0)
1302 								Info = _WRONG_MESSAGE_FORMAT;
1303 							if (!Info)
1304 							{
1305 								if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1306 								{
1307 									esc_chi[0] = (byte)(ai_parms[0].length - 2);
1308 									for (i = 0; i + 5 <= ai_parms[0].length; i++)
1309 										esc_chi[i + 3] = ai_parms[0].info[i + 5];
1310 								}
1311 								else
1312 									esc_chi[0] = 2;
1313 								esc_chi[2] = (byte)channel;
1314 								plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1315 								add_p(plci, LLI, lli);
1316 								add_p(plci, ESC, esc_chi);
1317 								plci->State = LOCAL_CONNECT;
1318 								if (!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
1319 							}
1320 						}
1321 					}
1322 				}
1323 				else  Info = _WRONG_MESSAGE_FORMAT;
1324 			}
1325 
1326 			dbug(1, dprintf("ch=%x,dir=%x,p_ch=%d", ch, dir, channel));
1327 			plci->command = _CONNECT_R;
1328 			plci->number = Number;
1329 			/* x.31 or D-ch free SAPI in LinkLayer? */
1330 			if (ch == 1 && LinkLayer != 3 && LinkLayer != 12) noCh = true;
1331 			if ((ch == 0 || ch == 2 || noCh || ch == 3 || ch == 4) && !Info)
1332 			{
1333 				/* B-channel used for B3 connections (ch==0), or no B channel    */
1334 				/* is used (ch==2) or perm. connection (3) is used  do a CALL    */
1335 				if (noCh) Info = add_b1(plci, &parms[5], 2, 0);    /* no resource    */
1336 				else     Info = add_b1(plci, &parms[5], ch, 0);
1337 				add_s(plci, OAD, &parms[2]);
1338 				add_s(plci, OSA, &parms[4]);
1339 				add_s(plci, BC, &parms[6]);
1340 				add_s(plci, LLC, &parms[7]);
1341 				add_s(plci, HLC, &parms[8]);
1342 				if (a->Info_Mask[appl->Id - 1] & 0x200)
1343 				{
1344 					/* early B3 connect (CIP mask bit 9) no release after a disc */
1345 					add_p(plci, LLI, "\x01\x01");
1346 				}
1347 				if (GET_WORD(parms[0].info) < 29) {
1348 					add_p(plci, BC, cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1349 					add_p(plci, HLC, cip_hlc[GET_WORD(parms[0].info)]);
1350 				}
1351 				add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1352 				sig_req(plci, ASSIGN, DSIG_ID);
1353 			}
1354 			else if (ch == 1) {
1355 
1356 				/* D-Channel used for B3 connections */
1357 				plci->Sig.Id = 0xff;
1358 				Info = 0;
1359 			}
1360 
1361 			if (!Info && ch != 2 && !noCh) {
1362 				Info = add_b23(plci, &parms[5]);
1363 				if (!Info) {
1364 					if (!(plci->tel && !plci->adv_nl))nl_req_ncci(plci, ASSIGN, 0);
1365 				}
1366 			}
1367 
1368 			if (!Info)
1369 			{
1370 				if (ch == 0 || ch == 2 || ch == 3 || noCh || ch == 4)
1371 				{
1372 					if (plci->spoofed_msg == SPOOFING_REQUIRED)
1373 					{
1374 						api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1375 						plci->spoofed_msg = CALL_REQ;
1376 						plci->internal_command = BLOCK_PLCI;
1377 						plci->command = 0;
1378 						dbug(1, dprintf("Spoof"));
1379 						send_req(plci);
1380 						return false;
1381 					}
1382 					if (ch == 4)add_p(plci, CHI, p_chi);
1383 					add_s(plci, CPN, &parms[1]);
1384 					add_s(plci, DSA, &parms[3]);
1385 					if (noCh) add_p(plci, ESC, "\x02\x18\xfd");  /* D-channel, no B-L3 */
1386 					add_ai(plci, &parms[9]);
1387 					if (!dir)sig_req(plci, CALL_REQ, 0);
1388 					else
1389 					{
1390 						plci->command = PERM_LIST_REQ;
1391 						plci->appl = appl;
1392 						sig_req(plci, LISTEN_REQ, 0);
1393 						send_req(plci);
1394 						return false;
1395 					}
1396 				}
1397 				send_req(plci);
1398 				return false;
1399 			}
1400 			plci->Id = 0;
1401 		}
1402 	}
1403 	sendf(appl,
1404 	      _CONNECT_R | CONFIRM,
1405 	      Id,
1406 	      Number,
1407 	      "w", Info);
1408 	return 2;
1409 }
1410 
connect_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)1411 static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1412 			PLCI *plci, APPL *appl, API_PARSE *parms)
1413 {
1414 	word i, Info;
1415 	word Reject;
1416 	static byte cau_t[] = {0, 0, 0x90, 0x91, 0xac, 0x9d, 0x86, 0xd8, 0x9b};
1417 	static byte esc_t[] = {0x03, 0x08, 0x00, 0x00};
1418 	API_PARSE *ai;
1419 	API_PARSE ai_parms[5];
1420 	word ch = 0;
1421 
1422 	if (!plci) {
1423 		dbug(1, dprintf("connect_res(no plci)"));
1424 		return 0;  /* no plci, no send */
1425 	}
1426 
1427 	dbug(1, dprintf("connect_res(State=0x%x)", plci->State));
1428 	for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1429 	ai = &parms[5];
1430 	dbug(1, dprintf("ai->length=%d", ai->length));
1431 
1432 	if (ai->length)
1433 	{
1434 		if (!api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1435 		{
1436 			dbug(1, dprintf("ai_parms[0].length=%d/0x%x", ai_parms[0].length, GET_WORD(ai_parms[0].info + 1)));
1437 			ch = 0;
1438 			if (ai_parms[0].length)
1439 			{
1440 				ch = GET_WORD(ai_parms[0].info + 1);
1441 				dbug(1, dprintf("BCH-I=0x%x", ch));
1442 			}
1443 		}
1444 	}
1445 
1446 	if (plci->State == INC_CON_CONNECTED_ALERT)
1447 	{
1448 		dbug(1, dprintf("Connected Alert Call_Res"));
1449 		if (a->Info_Mask[appl->Id - 1] & 0x200)
1450 		{
1451 			/* early B3 connect (CIP mask bit 9) no release after a disc */
1452 			add_p(plci, LLI, "\x01\x01");
1453 		}
1454 		add_s(plci, CONN_NR, &parms[2]);
1455 		add_s(plci, LLC, &parms[4]);
1456 		add_ai(plci, &parms[5]);
1457 		plci->State = INC_CON_ACCEPT;
1458 		sig_req(plci, CALL_RES, 0);
1459 		return 1;
1460 	}
1461 	else if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT) {
1462 		clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1463 		dump_c_ind_mask(plci);
1464 		Reject = GET_WORD(parms[0].info);
1465 		dbug(1, dprintf("Reject=0x%x", Reject));
1466 		if (Reject)
1467 		{
1468 			if (c_ind_mask_empty(plci))
1469 			{
1470 				if ((Reject & 0xff00) == 0x3400)
1471 				{
1472 					esc_t[2] = ((byte)(Reject & 0x00ff)) | 0x80;
1473 					add_p(plci, ESC, esc_t);
1474 					add_ai(plci, &parms[5]);
1475 					sig_req(plci, REJECT, 0);
1476 				}
1477 				else if (Reject == 1 || Reject > 9)
1478 				{
1479 					add_ai(plci, &parms[5]);
1480 					sig_req(plci, HANGUP, 0);
1481 				}
1482 				else
1483 				{
1484 					esc_t[2] = cau_t[(Reject&0x000f)];
1485 					add_p(plci, ESC, esc_t);
1486 					add_ai(plci, &parms[5]);
1487 					sig_req(plci, REJECT, 0);
1488 				}
1489 				plci->appl = appl;
1490 			}
1491 			else
1492 			{
1493 				sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1494 			}
1495 		}
1496 		else {
1497 			plci->appl = appl;
1498 			if (Id & EXT_CONTROLLER) {
1499 				if (AdvCodecSupport(a, plci, appl, 0)) {
1500 					dbug(1, dprintf("connect_res(error from AdvCodecSupport)"));
1501 					sig_req(plci, HANGUP, 0);
1502 					return 1;
1503 				}
1504 				if (plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1505 				{
1506 					Info = add_b23(plci, &parms[1]);
1507 					if (Info)
1508 					{
1509 						dbug(1, dprintf("connect_res(error from add_b23)"));
1510 						sig_req(plci, HANGUP, 0);
1511 						return 1;
1512 					}
1513 					if (plci->adv_nl)
1514 					{
1515 						nl_req_ncci(plci, ASSIGN, 0);
1516 					}
1517 				}
1518 			}
1519 			else
1520 			{
1521 				plci->tel = 0;
1522 				if (ch != 2)
1523 				{
1524 					Info = add_b23(plci, &parms[1]);
1525 					if (Info)
1526 					{
1527 						dbug(1, dprintf("connect_res(error from add_b23 2)"));
1528 						sig_req(plci, HANGUP, 0);
1529 						return 1;
1530 					}
1531 				}
1532 				nl_req_ncci(plci, ASSIGN, 0);
1533 			}
1534 
1535 			if (plci->spoofed_msg == SPOOFING_REQUIRED)
1536 			{
1537 				api_save_msg(parms, "wsssss", &plci->saved_msg);
1538 				plci->spoofed_msg = CALL_RES;
1539 				plci->internal_command = BLOCK_PLCI;
1540 				plci->command = 0;
1541 				dbug(1, dprintf("Spoof"));
1542 			}
1543 			else
1544 			{
1545 				add_b1(plci, &parms[1], ch, plci->B1_facilities);
1546 				if (a->Info_Mask[appl->Id - 1] & 0x200)
1547 				{
1548 					/* early B3 connect (CIP mask bit 9) no release after a disc */
1549 					add_p(plci, LLI, "\x01\x01");
1550 				}
1551 				add_s(plci, CONN_NR, &parms[2]);
1552 				add_s(plci, LLC, &parms[4]);
1553 				add_ai(plci, &parms[5]);
1554 				plci->State = INC_CON_ACCEPT;
1555 				sig_req(plci, CALL_RES, 0);
1556 			}
1557 
1558 			for (i = 0; i < max_appl; i++) {
1559 				if (test_c_ind_mask_bit(plci, i)) {
1560 					sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1561 				}
1562 			}
1563 		}
1564 	}
1565 	return 1;
1566 }
1567 
connect_a_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)1568 static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1569 			  PLCI *plci, APPL *appl, API_PARSE *msg)
1570 {
1571 	dbug(1, dprintf("connect_a_res"));
1572 	return false;
1573 }
1574 
disconnect_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)1575 static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1576 			   PLCI *plci, APPL *appl, API_PARSE *msg)
1577 {
1578 	word Info;
1579 	word i;
1580 
1581 	dbug(1, dprintf("disconnect_req"));
1582 
1583 	Info = _WRONG_IDENTIFIER;
1584 
1585 	if (plci)
1586 	{
1587 		if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
1588 		{
1589 			clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1590 			plci->appl = appl;
1591 			for (i = 0; i < max_appl; i++)
1592 			{
1593 				if (test_c_ind_mask_bit(plci, i))
1594 					sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1595 			}
1596 			plci->State = OUTG_DIS_PENDING;
1597 		}
1598 		if (plci->Sig.Id && plci->appl)
1599 		{
1600 			Info = 0;
1601 			if (plci->Sig.Id != 0xff)
1602 			{
1603 				if (plci->State != INC_DIS_PENDING)
1604 				{
1605 					add_ai(plci, &msg[0]);
1606 					sig_req(plci, HANGUP, 0);
1607 					plci->State = OUTG_DIS_PENDING;
1608 					return 1;
1609 				}
1610 			}
1611 			else
1612 			{
1613 				if (plci->NL.Id && !plci->nl_remove_id)
1614 				{
1615 					mixer_remove(plci);
1616 					nl_req_ncci(plci, REMOVE, 0);
1617 					sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
1618 					sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1619 					plci->State = INC_DIS_PENDING;
1620 				}
1621 				return 1;
1622 			}
1623 		}
1624 	}
1625 
1626 	if (!appl)  return false;
1627 	sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", Info);
1628 	return false;
1629 }
1630 
disconnect_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)1631 static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1632 			   PLCI *plci, APPL *appl, API_PARSE *msg)
1633 {
1634 	dbug(1, dprintf("disconnect_res"));
1635 	if (plci)
1636 	{
1637 		/* clear ind mask bit, just in case of collsion of          */
1638 		/* DISCONNECT_IND and CONNECT_RES                           */
1639 		clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
1640 		ncci_free_receive_buffers(plci, 0);
1641 		if (plci_remove_check(plci))
1642 		{
1643 			return 0;
1644 		}
1645 		if (plci->State == INC_DIS_PENDING
1646 		    || plci->State == SUSPENDING) {
1647 			if (c_ind_mask_empty(plci)) {
1648 				if (plci->State != SUSPENDING) plci->State = IDLE;
1649 				dbug(1, dprintf("chs=%d", plci->channels));
1650 				if (!plci->channels) {
1651 					plci_remove(plci);
1652 				}
1653 			}
1654 		}
1655 	}
1656 	return 0;
1657 }
1658 
listen_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)1659 static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1660 		       PLCI *plci, APPL *appl, API_PARSE *parms)
1661 {
1662 	word Info;
1663 	byte i;
1664 
1665 	dbug(1, dprintf("listen_req(Appl=0x%x)", appl->Id));
1666 
1667 	Info = _WRONG_IDENTIFIER;
1668 	if (a) {
1669 		Info = 0;
1670 		a->Info_Mask[appl->Id - 1] = GET_DWORD(parms[0].info);
1671 		a->CIP_Mask[appl->Id - 1] = GET_DWORD(parms[1].info);
1672 		dbug(1, dprintf("CIP_MASK=0x%lx", GET_DWORD(parms[1].info)));
1673 		if (a->Info_Mask[appl->Id - 1] & 0x200) { /* early B3 connect provides */
1674 			a->Info_Mask[appl->Id - 1] |=  0x10;   /* call progression infos    */
1675 		}
1676 
1677 		/* check if external controller listen and switch listen on or off*/
1678 		if (Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)) {
1679 			if (a->profile.Global_Options & ON_BOARD_CODEC) {
1680 				dummy_plci.State = IDLE;
1681 				a->codec_listen[appl->Id - 1] = &dummy_plci;
1682 				a->TelOAD[0] = (byte)(parms[3].length);
1683 				for (i = 1; parms[3].length >= i && i < 22; i++) {
1684 					a->TelOAD[i] = parms[3].info[i];
1685 				}
1686 				a->TelOAD[i] = 0;
1687 				a->TelOSA[0] = (byte)(parms[4].length);
1688 				for (i = 1; parms[4].length >= i && i < 22; i++) {
1689 					a->TelOSA[i] = parms[4].info[i];
1690 				}
1691 				a->TelOSA[i] = 0;
1692 			}
1693 			else Info = 0x2002; /* wrong controller, codec not supported */
1694 		}
1695 		else{               /* clear listen */
1696 			a->codec_listen[appl->Id - 1] = (PLCI *)0;
1697 		}
1698 	}
1699 	sendf(appl,
1700 	      _LISTEN_R | CONFIRM,
1701 	      Id,
1702 	      Number,
1703 	      "w", Info);
1704 
1705 	if (a) listen_check(a);
1706 	return false;
1707 }
1708 
info_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)1709 static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1710 		     PLCI *plci, APPL *appl, API_PARSE *msg)
1711 {
1712 	word i;
1713 	API_PARSE *ai;
1714 	PLCI *rc_plci = NULL;
1715 	API_PARSE ai_parms[5];
1716 	word Info = 0;
1717 
1718 	dbug(1, dprintf("info_req"));
1719 	for (i = 0; i < 5; i++) ai_parms[i].length = 0;
1720 
1721 	ai = &msg[1];
1722 
1723 	if (ai->length)
1724 	{
1725 		if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
1726 		{
1727 			dbug(1, dprintf("AddInfo wrong"));
1728 			Info = _WRONG_MESSAGE_FORMAT;
1729 		}
1730 	}
1731 	if (!a) Info = _WRONG_STATE;
1732 
1733 	if (!Info && plci)
1734 	{                /* no fac, with CPN, or KEY */
1735 		rc_plci = plci;
1736 		if (!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length))
1737 		{
1738 			/* overlap sending option */
1739 			dbug(1, dprintf("OvlSnd"));
1740 			add_s(plci, CPN, &msg[0]);
1741 			add_s(plci, KEY, &ai_parms[1]);
1742 			sig_req(plci, INFO_REQ, 0);
1743 			send_req(plci);
1744 			return false;
1745 		}
1746 
1747 		if (plci->State && ai_parms[2].length)
1748 		{
1749 			/* User_Info option */
1750 			dbug(1, dprintf("UUI"));
1751 			add_s(plci, UUI, &ai_parms[2]);
1752 			sig_req(plci, USER_DATA, 0);
1753 		}
1754 		else if (plci->State && ai_parms[3].length)
1755 		{
1756 			/* Facility option */
1757 			dbug(1, dprintf("FAC"));
1758 			add_s(plci, CPN, &msg[0]);
1759 			add_ai(plci, &msg[1]);
1760 			sig_req(plci, FACILITY_REQ, 0);
1761 		}
1762 		else
1763 		{
1764 			Info = _WRONG_STATE;
1765 		}
1766 	}
1767 	else if ((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1768 	{
1769 		/* NCR_Facility option -> send UUI and Keypad too */
1770 		dbug(1, dprintf("NCR_FAC"));
1771 		if ((i = get_plci(a)))
1772 		{
1773 			rc_plci = &a->plci[i - 1];
1774 			appl->NullCREnable = true;
1775 			rc_plci->internal_command = C_NCR_FAC_REQ;
1776 			rc_plci->appl = appl;
1777 			add_p(rc_plci, CAI, "\x01\x80");
1778 			add_p(rc_plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1779 			sig_req(rc_plci, ASSIGN, DSIG_ID);
1780 			send_req(rc_plci);
1781 		}
1782 		else
1783 		{
1784 			Info = _OUT_OF_PLCI;
1785 		}
1786 
1787 		if (!Info)
1788 		{
1789 			add_s(rc_plci, CPN, &msg[0]);
1790 			add_ai(rc_plci, &msg[1]);
1791 			sig_req(rc_plci, NCR_FACILITY, 0);
1792 			send_req(rc_plci);
1793 			return false;
1794 			/* for application controlled supplementary services    */
1795 		}
1796 	}
1797 
1798 	if (!rc_plci)
1799 	{
1800 		Info = _WRONG_MESSAGE_FORMAT;
1801 	}
1802 
1803 	if (!Info)
1804 	{
1805 		send_req(rc_plci);
1806 	}
1807 	else
1808 	{  /* appl is not assigned to a PLCI or error condition */
1809 		dbug(1, dprintf("localInfoCon"));
1810 		sendf(appl,
1811 		      _INFO_R | CONFIRM,
1812 		      Id,
1813 		      Number,
1814 		      "w", Info);
1815 	}
1816 	return false;
1817 }
1818 
info_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)1819 static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1820 		     PLCI *plci, APPL *appl, API_PARSE *msg)
1821 {
1822 	dbug(1, dprintf("info_res"));
1823 	return false;
1824 }
1825 
alert_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)1826 static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1827 		      PLCI *plci, APPL *appl, API_PARSE *msg)
1828 {
1829 	word Info;
1830 	byte ret;
1831 
1832 	dbug(1, dprintf("alert_req"));
1833 
1834 	Info = _WRONG_IDENTIFIER;
1835 	ret = false;
1836 	if (plci) {
1837 		Info = _ALERT_IGNORED;
1838 		if (plci->State != INC_CON_ALERT) {
1839 			Info = _WRONG_STATE;
1840 			if (plci->State == INC_CON_PENDING) {
1841 				Info = 0;
1842 				plci->State = INC_CON_ALERT;
1843 				add_ai(plci, &msg[0]);
1844 				sig_req(plci, CALL_ALERT, 0);
1845 				ret = 1;
1846 			}
1847 		}
1848 	}
1849 	sendf(appl,
1850 	      _ALERT_R | CONFIRM,
1851 	      Id,
1852 	      Number,
1853 	      "w", Info);
1854 	return ret;
1855 }
1856 
facility_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)1857 static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1858 			 PLCI *plci, APPL *appl, API_PARSE *msg)
1859 {
1860 	word Info = 0;
1861 	word i    = 0;
1862 
1863 	word selector;
1864 	word SSreq;
1865 	long relatedPLCIvalue;
1866 	DIVA_CAPI_ADAPTER *relatedadapter;
1867 	byte *SSparms  = "";
1868 	byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1869 	byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1870 	API_PARSE *parms;
1871 	API_PARSE ss_parms[11];
1872 	PLCI *rplci;
1873 	byte cai[15];
1874 	dword d;
1875 	API_PARSE dummy;
1876 
1877 	dbug(1, dprintf("facility_req"));
1878 	for (i = 0; i < 9; i++) ss_parms[i].length = 0;
1879 
1880 	parms = &msg[1];
1881 
1882 	if (!a)
1883 	{
1884 		dbug(1, dprintf("wrong Ctrl"));
1885 		Info = _WRONG_IDENTIFIER;
1886 	}
1887 
1888 	selector = GET_WORD(msg[0].info);
1889 
1890 	if (!Info)
1891 	{
1892 		switch (selector)
1893 		{
1894 		case SELECTOR_HANDSET:
1895 			Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1896 			break;
1897 
1898 		case SELECTOR_SU_SERV:
1899 			if (!msg[1].length)
1900 			{
1901 				Info = _WRONG_MESSAGE_FORMAT;
1902 				break;
1903 			}
1904 			SSreq = GET_WORD(&(msg[1].info[1]));
1905 			PUT_WORD(&RCparms[1], SSreq);
1906 			SSparms = RCparms;
1907 			switch (SSreq)
1908 			{
1909 			case S_GET_SUPPORTED_SERVICES:
1910 				if ((i = get_plci(a)))
1911 				{
1912 					rplci = &a->plci[i - 1];
1913 					rplci->appl = appl;
1914 					add_p(rplci, CAI, "\x01\x80");
1915 					add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1916 					sig_req(rplci, ASSIGN, DSIG_ID);
1917 					send_req(rplci);
1918 				}
1919 				else
1920 				{
1921 					PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1922 					SSparms = (byte *)SSstruct;
1923 					break;
1924 				}
1925 				rplci->internal_command = GETSERV_REQ_PEND;
1926 				rplci->number = Number;
1927 				rplci->appl = appl;
1928 				sig_req(rplci, S_SUPPORTED, 0);
1929 				send_req(rplci);
1930 				return false;
1931 				break;
1932 
1933 			case S_LISTEN:
1934 				if (parms->length == 7)
1935 				{
1936 					if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
1937 					{
1938 						dbug(1, dprintf("format wrong"));
1939 						Info = _WRONG_MESSAGE_FORMAT;
1940 						break;
1941 					}
1942 				}
1943 				else
1944 				{
1945 					Info = _WRONG_MESSAGE_FORMAT;
1946 					break;
1947 				}
1948 				a->Notification_Mask[appl->Id - 1] = GET_DWORD(ss_parms[2].info);
1949 				if (a->Notification_Mask[appl->Id - 1] & SMASK_MWI) /* MWI active? */
1950 				{
1951 					if ((i = get_plci(a)))
1952 					{
1953 						rplci = &a->plci[i - 1];
1954 						rplci->appl = appl;
1955 						add_p(rplci, CAI, "\x01\x80");
1956 						add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
1957 						sig_req(rplci, ASSIGN, DSIG_ID);
1958 						send_req(rplci);
1959 					}
1960 					else
1961 					{
1962 						break;
1963 					}
1964 					rplci->internal_command = GET_MWI_STATE;
1965 					rplci->number = Number;
1966 					sig_req(rplci, MWI_POLL, 0);
1967 					send_req(rplci);
1968 				}
1969 				break;
1970 
1971 			case S_HOLD:
1972 				api_parse(&parms->info[1], (word)parms->length, "ws", ss_parms);
1973 				if (plci && plci->State && plci->SuppState == IDLE)
1974 				{
1975 					plci->SuppState = HOLD_REQUEST;
1976 					plci->command = C_HOLD_REQ;
1977 					add_s(plci, CAI, &ss_parms[1]);
1978 					sig_req(plci, CALL_HOLD, 0);
1979 					send_req(plci);
1980 					return false;
1981 				}
1982 				else Info = 0x3010;                    /* wrong state           */
1983 				break;
1984 			case S_RETRIEVE:
1985 				if (plci && plci->State && plci->SuppState == CALL_HELD)
1986 				{
1987 					if (Id & EXT_CONTROLLER)
1988 					{
1989 						if (AdvCodecSupport(a, plci, appl, 0))
1990 						{
1991 							Info = 0x3010;                    /* wrong state           */
1992 							break;
1993 						}
1994 					}
1995 					else plci->tel = 0;
1996 
1997 					plci->SuppState = RETRIEVE_REQUEST;
1998 					plci->command = C_RETRIEVE_REQ;
1999 					if (plci->spoofed_msg == SPOOFING_REQUIRED)
2000 					{
2001 						plci->spoofed_msg = CALL_RETRIEVE;
2002 						plci->internal_command = BLOCK_PLCI;
2003 						plci->command = 0;
2004 						dbug(1, dprintf("Spoof"));
2005 						return false;
2006 					}
2007 					else
2008 					{
2009 						sig_req(plci, CALL_RETRIEVE, 0);
2010 						send_req(plci);
2011 						return false;
2012 					}
2013 				}
2014 				else Info = 0x3010;                    /* wrong state           */
2015 				break;
2016 			case S_SUSPEND:
2017 				if (parms->length)
2018 				{
2019 					if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2020 					{
2021 						dbug(1, dprintf("format wrong"));
2022 						Info = _WRONG_MESSAGE_FORMAT;
2023 						break;
2024 					}
2025 				}
2026 				if (plci && plci->State)
2027 				{
2028 					add_s(plci, CAI, &ss_parms[2]);
2029 					plci->command = SUSPEND_REQ;
2030 					sig_req(plci, SUSPEND, 0);
2031 					plci->State = SUSPENDING;
2032 					send_req(plci);
2033 				}
2034 				else Info = 0x3010;                    /* wrong state           */
2035 				break;
2036 
2037 			case S_RESUME:
2038 				if (!(i = get_plci(a)))
2039 				{
2040 					Info = _OUT_OF_PLCI;
2041 					break;
2042 				}
2043 				rplci = &a->plci[i - 1];
2044 				rplci->appl = appl;
2045 				rplci->number = Number;
2046 				rplci->tel = 0;
2047 				rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2048 				/* check 'external controller' bit for codec support */
2049 				if (Id & EXT_CONTROLLER)
2050 				{
2051 					if (AdvCodecSupport(a, rplci, appl, 0))
2052 					{
2053 						rplci->Id = 0;
2054 						Info = 0x300A;
2055 						break;
2056 					}
2057 				}
2058 				if (parms->length)
2059 				{
2060 					if (api_parse(&parms->info[1], (word)parms->length, "wbs", ss_parms))
2061 					{
2062 						dbug(1, dprintf("format wrong"));
2063 						rplci->Id = 0;
2064 						Info = _WRONG_MESSAGE_FORMAT;
2065 						break;
2066 					}
2067 				}
2068 				dummy.length = 0;
2069 				dummy.info = "\x00";
2070 				add_b1(rplci, &dummy, 0, 0);
2071 				if (a->Info_Mask[appl->Id - 1] & 0x200)
2072 				{
2073 					/* early B3 connect (CIP mask bit 9) no release after a disc */
2074 					add_p(rplci, LLI, "\x01\x01");
2075 				}
2076 				add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2077 				sig_req(rplci, ASSIGN, DSIG_ID);
2078 				send_req(rplci);
2079 				add_s(rplci, CAI, &ss_parms[2]);
2080 				rplci->command = RESUME_REQ;
2081 				sig_req(rplci, RESUME, 0);
2082 				rplci->State = RESUMING;
2083 				send_req(rplci);
2084 				break;
2085 
2086 			case S_CONF_BEGIN: /* Request */
2087 			case S_CONF_DROP:
2088 			case S_CONF_ISOLATE:
2089 			case S_CONF_REATTACH:
2090 				if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2091 				{
2092 					dbug(1, dprintf("format wrong"));
2093 					Info = _WRONG_MESSAGE_FORMAT;
2094 					break;
2095 				}
2096 				if (plci && plci->State && ((plci->SuppState == IDLE) || (plci->SuppState == CALL_HELD)))
2097 				{
2098 					d = GET_DWORD(ss_parms[2].info);
2099 					if (d >= 0x80)
2100 					{
2101 						dbug(1, dprintf("format wrong"));
2102 						Info = _WRONG_MESSAGE_FORMAT;
2103 						break;
2104 					}
2105 					plci->ptyState = (byte)SSreq;
2106 					plci->command = 0;
2107 					cai[0] = 2;
2108 					switch (SSreq)
2109 					{
2110 					case S_CONF_BEGIN:
2111 						cai[1] = CONF_BEGIN;
2112 						plci->internal_command = CONF_BEGIN_REQ_PEND;
2113 						break;
2114 					case S_CONF_DROP:
2115 						cai[1] = CONF_DROP;
2116 						plci->internal_command = CONF_DROP_REQ_PEND;
2117 						break;
2118 					case S_CONF_ISOLATE:
2119 						cai[1] = CONF_ISOLATE;
2120 						plci->internal_command = CONF_ISOLATE_REQ_PEND;
2121 						break;
2122 					case S_CONF_REATTACH:
2123 						cai[1] = CONF_REATTACH;
2124 						plci->internal_command = CONF_REATTACH_REQ_PEND;
2125 						break;
2126 					}
2127 					cai[2] = (byte)d; /* Conference Size resp. PartyId */
2128 					add_p(plci, CAI, cai);
2129 					sig_req(plci, S_SERVICE, 0);
2130 					send_req(plci);
2131 					return false;
2132 				}
2133 				else Info = 0x3010;                    /* wrong state           */
2134 				break;
2135 
2136 			case S_ECT:
2137 			case S_3PTY_BEGIN:
2138 			case S_3PTY_END:
2139 			case S_CONF_ADD:
2140 				if (parms->length == 7)
2141 				{
2142 					if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2143 					{
2144 						dbug(1, dprintf("format wrong"));
2145 						Info = _WRONG_MESSAGE_FORMAT;
2146 						break;
2147 					}
2148 				}
2149 				else if (parms->length == 8) /* workaround for the T-View-S */
2150 				{
2151 					if (api_parse(&parms->info[1], (word)parms->length, "wbdb", ss_parms))
2152 					{
2153 						dbug(1, dprintf("format wrong"));
2154 						Info = _WRONG_MESSAGE_FORMAT;
2155 						break;
2156 					}
2157 				}
2158 				else
2159 				{
2160 					Info = _WRONG_MESSAGE_FORMAT;
2161 					break;
2162 				}
2163 				if (!msg[1].length)
2164 				{
2165 					Info = _WRONG_MESSAGE_FORMAT;
2166 					break;
2167 				}
2168 				if (!plci)
2169 				{
2170 					Info = _WRONG_IDENTIFIER;
2171 					break;
2172 				}
2173 				relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2174 				relatedPLCIvalue &= 0x0000FFFF;
2175 				dbug(1, dprintf("PTY/ECT/addCONF,relPLCI=%lx", relatedPLCIvalue));
2176 				/* controller starts with 0 up to (max_adapter - 1) */
2177 				if (((relatedPLCIvalue & 0x7f) == 0)
2178 				    || (MapController((byte)(relatedPLCIvalue & 0x7f)) == 0)
2179 				    || (MapController((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2180 				{
2181 					if (SSreq == S_3PTY_END)
2182 					{
2183 						dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2184 						rplci = plci;
2185 					}
2186 					else
2187 					{
2188 						Info = 0x3010;                    /* wrong state           */
2189 						break;
2190 					}
2191 				}
2192 				else
2193 				{
2194 					relatedadapter = &adapter[MapController((byte)(relatedPLCIvalue & 0x7f)) - 1];
2195 					relatedPLCIvalue >>= 8;
2196 					/* find PLCI PTR*/
2197 					for (i = 0, rplci = NULL; i < relatedadapter->max_plci; i++)
2198 					{
2199 						if (relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2200 						{
2201 							rplci = &relatedadapter->plci[i];
2202 						}
2203 					}
2204 					if (!rplci || !relatedPLCIvalue)
2205 					{
2206 						if (SSreq == S_3PTY_END)
2207 						{
2208 							dbug(1, dprintf("use 2nd PLCI=PLCI"));
2209 							rplci = plci;
2210 						}
2211 						else
2212 						{
2213 							Info = 0x3010;                    /* wrong state           */
2214 							break;
2215 						}
2216 					}
2217 				}
2218 /*
2219   dbug(1, dprintf("rplci:%x", rplci));
2220   dbug(1, dprintf("plci:%x", plci));
2221   dbug(1, dprintf("rplci->ptyState:%x", rplci->ptyState));
2222   dbug(1, dprintf("plci->ptyState:%x", plci->ptyState));
2223   dbug(1, dprintf("SSreq:%x", SSreq));
2224   dbug(1, dprintf("rplci->internal_command:%x", rplci->internal_command));
2225   dbug(1, dprintf("rplci->appl:%x", rplci->appl));
2226   dbug(1, dprintf("rplci->Id:%x", rplci->Id));
2227 */
2228 				/* send PTY/ECT req, cannot check all states because of US stuff */
2229 				if (!rplci->internal_command && rplci->appl)
2230 				{
2231 					plci->command = 0;
2232 					rplci->relatedPTYPLCI = plci;
2233 					plci->relatedPTYPLCI = rplci;
2234 					rplci->ptyState = (byte)SSreq;
2235 					if (SSreq == S_ECT)
2236 					{
2237 						rplci->internal_command = ECT_REQ_PEND;
2238 						cai[1] = ECT_EXECUTE;
2239 
2240 						rplci->vswitchstate = 0;
2241 						rplci->vsprot = 0;
2242 						rplci->vsprotdialect = 0;
2243 						plci->vswitchstate = 0;
2244 						plci->vsprot = 0;
2245 						plci->vsprotdialect = 0;
2246 
2247 					}
2248 					else if (SSreq == S_CONF_ADD)
2249 					{
2250 						rplci->internal_command = CONF_ADD_REQ_PEND;
2251 						cai[1] = CONF_ADD;
2252 					}
2253 					else
2254 					{
2255 						rplci->internal_command = PTY_REQ_PEND;
2256 						cai[1] = (byte)(SSreq - 3);
2257 					}
2258 					rplci->number = Number;
2259 					if (plci != rplci) /* explicit invocation */
2260 					{
2261 						cai[0] = 2;
2262 						cai[2] = plci->Sig.Id;
2263 						dbug(1, dprintf("explicit invocation"));
2264 					}
2265 					else
2266 					{
2267 						dbug(1, dprintf("implicit invocation"));
2268 						cai[0] = 1;
2269 					}
2270 					add_p(rplci, CAI, cai);
2271 					sig_req(rplci, S_SERVICE, 0);
2272 					send_req(rplci);
2273 					return false;
2274 				}
2275 				else
2276 				{
2277 					dbug(0, dprintf("Wrong line"));
2278 					Info = 0x3010;                    /* wrong state           */
2279 					break;
2280 				}
2281 				break;
2282 
2283 			case S_CALL_DEFLECTION:
2284 				if (api_parse(&parms->info[1], (word)parms->length, "wbwss", ss_parms))
2285 				{
2286 					dbug(1, dprintf("format wrong"));
2287 					Info = _WRONG_MESSAGE_FORMAT;
2288 					break;
2289 				}
2290 				if (!plci)
2291 				{
2292 					Info = _WRONG_IDENTIFIER;
2293 					break;
2294 				}
2295 				/* reuse unused screening indicator */
2296 				ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2297 				plci->command = 0;
2298 				plci->internal_command = CD_REQ_PEND;
2299 				appl->CDEnable = true;
2300 				cai[0] = 1;
2301 				cai[1] = CALL_DEFLECTION;
2302 				add_p(plci, CAI, cai);
2303 				add_p(plci, CPN, ss_parms[3].info);
2304 				sig_req(plci, S_SERVICE, 0);
2305 				send_req(plci);
2306 				return false;
2307 				break;
2308 
2309 			case S_CALL_FORWARDING_START:
2310 				if (api_parse(&parms->info[1], (word)parms->length, "wbdwwsss", ss_parms))
2311 				{
2312 					dbug(1, dprintf("format wrong"));
2313 					Info = _WRONG_MESSAGE_FORMAT;
2314 					break;
2315 				}
2316 
2317 				if ((i = get_plci(a)))
2318 				{
2319 					rplci = &a->plci[i - 1];
2320 					rplci->appl = appl;
2321 					add_p(rplci, CAI, "\x01\x80");
2322 					add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2323 					sig_req(rplci, ASSIGN, DSIG_ID);
2324 					send_req(rplci);
2325 				}
2326 				else
2327 				{
2328 					Info = _OUT_OF_PLCI;
2329 					break;
2330 				}
2331 
2332 				/* reuse unused screening indicator */
2333 				rplci->internal_command = CF_START_PEND;
2334 				rplci->appl = appl;
2335 				rplci->number = Number;
2336 				appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2337 				cai[0] = 2;
2338 				cai[1] = 0x70 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2339 				cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2340 				add_p(rplci, CAI, cai);
2341 				add_p(rplci, OAD, ss_parms[5].info);
2342 				add_p(rplci, CPN, ss_parms[6].info);
2343 				sig_req(rplci, S_SERVICE, 0);
2344 				send_req(rplci);
2345 				return false;
2346 				break;
2347 
2348 			case S_INTERROGATE_DIVERSION:
2349 			case S_INTERROGATE_NUMBERS:
2350 			case S_CALL_FORWARDING_STOP:
2351 			case S_CCBS_REQUEST:
2352 			case S_CCBS_DEACTIVATE:
2353 			case S_CCBS_INTERROGATE:
2354 				switch (SSreq)
2355 				{
2356 				case S_INTERROGATE_NUMBERS:
2357 					if (api_parse(&parms->info[1], (word)parms->length, "wbd", ss_parms))
2358 					{
2359 						dbug(0, dprintf("format wrong"));
2360 						Info = _WRONG_MESSAGE_FORMAT;
2361 					}
2362 					break;
2363 				case S_CCBS_REQUEST:
2364 				case S_CCBS_DEACTIVATE:
2365 					if (api_parse(&parms->info[1], (word)parms->length, "wbdw", ss_parms))
2366 					{
2367 						dbug(0, dprintf("format wrong"));
2368 						Info = _WRONG_MESSAGE_FORMAT;
2369 					}
2370 					break;
2371 				case S_CCBS_INTERROGATE:
2372 					if (api_parse(&parms->info[1], (word)parms->length, "wbdws", ss_parms))
2373 					{
2374 						dbug(0, dprintf("format wrong"));
2375 						Info = _WRONG_MESSAGE_FORMAT;
2376 					}
2377 					break;
2378 				default:
2379 					if (api_parse(&parms->info[1], (word)parms->length, "wbdwws", ss_parms))
2380 					{
2381 						dbug(0, dprintf("format wrong"));
2382 						Info = _WRONG_MESSAGE_FORMAT;
2383 						break;
2384 					}
2385 					break;
2386 				}
2387 
2388 				if (Info) break;
2389 				if ((i = get_plci(a)))
2390 				{
2391 					rplci = &a->plci[i - 1];
2392 					switch (SSreq)
2393 					{
2394 					case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2395 						cai[1] = 0x60 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2396 						rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2397 						break;
2398 					case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2399 						cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2400 						rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2401 						break;
2402 					case S_CALL_FORWARDING_STOP:
2403 						rplci->internal_command = CF_STOP_PEND;
2404 						cai[1] = 0x80 | (byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2405 						break;
2406 					case S_CCBS_REQUEST:
2407 						cai[1] = CCBS_REQUEST;
2408 						rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2409 						break;
2410 					case S_CCBS_DEACTIVATE:
2411 						cai[1] = CCBS_DEACTIVATE;
2412 						rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2413 						break;
2414 					case S_CCBS_INTERROGATE:
2415 						cai[1] = CCBS_INTERROGATE;
2416 						rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2417 						break;
2418 					default:
2419 						cai[1] = 0;
2420 						break;
2421 					}
2422 					rplci->appl = appl;
2423 					rplci->number = Number;
2424 					add_p(rplci, CAI, "\x01\x80");
2425 					add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2426 					sig_req(rplci, ASSIGN, DSIG_ID);
2427 					send_req(rplci);
2428 				}
2429 				else
2430 				{
2431 					Info = _OUT_OF_PLCI;
2432 					break;
2433 				}
2434 
2435 				appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2436 				switch (SSreq)
2437 				{
2438 				case S_INTERROGATE_NUMBERS:
2439 					cai[0] = 1;
2440 					add_p(rplci, CAI, cai);
2441 					break;
2442 				case S_CCBS_REQUEST:
2443 				case S_CCBS_DEACTIVATE:
2444 					cai[0] = 3;
2445 					PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2446 					add_p(rplci, CAI, cai);
2447 					break;
2448 				case S_CCBS_INTERROGATE:
2449 					cai[0] = 3;
2450 					PUT_WORD(&cai[2], GET_WORD(&(ss_parms[3].info[0])));
2451 					add_p(rplci, CAI, cai);
2452 					add_p(rplci, OAD, ss_parms[4].info);
2453 					break;
2454 				default:
2455 					cai[0] = 2;
2456 					cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2457 					add_p(rplci, CAI, cai);
2458 					add_p(rplci, OAD, ss_parms[5].info);
2459 					break;
2460 				}
2461 
2462 				sig_req(rplci, S_SERVICE, 0);
2463 				send_req(rplci);
2464 				return false;
2465 				break;
2466 
2467 			case S_MWI_ACTIVATE:
2468 				if (api_parse(&parms->info[1], (word)parms->length, "wbwdwwwssss", ss_parms))
2469 				{
2470 					dbug(1, dprintf("format wrong"));
2471 					Info = _WRONG_MESSAGE_FORMAT;
2472 					break;
2473 				}
2474 				if (!plci)
2475 				{
2476 					if ((i = get_plci(a)))
2477 					{
2478 						rplci = &a->plci[i - 1];
2479 						rplci->appl = appl;
2480 						rplci->cr_enquiry = true;
2481 						add_p(rplci, CAI, "\x01\x80");
2482 						add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2483 						sig_req(rplci, ASSIGN, DSIG_ID);
2484 						send_req(rplci);
2485 					}
2486 					else
2487 					{
2488 						Info = _OUT_OF_PLCI;
2489 						break;
2490 					}
2491 				}
2492 				else
2493 				{
2494 					rplci = plci;
2495 					rplci->cr_enquiry = false;
2496 				}
2497 
2498 				rplci->command = 0;
2499 				rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2500 				rplci->appl = appl;
2501 				rplci->number = Number;
2502 
2503 				cai[0] = 13;
2504 				cai[1] = ACTIVATION_MWI; /* Function */
2505 				PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2506 				PUT_DWORD(&cai[4], GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2507 				PUT_WORD(&cai[8], GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2508 				PUT_WORD(&cai[10], GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2509 				PUT_WORD(&cai[12], GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2510 				add_p(rplci, CAI, cai);
2511 				add_p(rplci, CPN, ss_parms[7].info); /* Receiving User Number */
2512 				add_p(rplci, OAD, ss_parms[8].info); /* Controlling User Number */
2513 				add_p(rplci, OSA, ss_parms[9].info); /* Controlling User Provided Number */
2514 				add_p(rplci, UID, ss_parms[10].info); /* Time */
2515 				sig_req(rplci, S_SERVICE, 0);
2516 				send_req(rplci);
2517 				return false;
2518 
2519 			case S_MWI_DEACTIVATE:
2520 				if (api_parse(&parms->info[1], (word)parms->length, "wbwwss", ss_parms))
2521 				{
2522 					dbug(1, dprintf("format wrong"));
2523 					Info = _WRONG_MESSAGE_FORMAT;
2524 					break;
2525 				}
2526 				if (!plci)
2527 				{
2528 					if ((i = get_plci(a)))
2529 					{
2530 						rplci = &a->plci[i - 1];
2531 						rplci->appl = appl;
2532 						rplci->cr_enquiry = true;
2533 						add_p(rplci, CAI, "\x01\x80");
2534 						add_p(rplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
2535 						sig_req(rplci, ASSIGN, DSIG_ID);
2536 						send_req(rplci);
2537 					}
2538 					else
2539 					{
2540 						Info = _OUT_OF_PLCI;
2541 						break;
2542 					}
2543 				}
2544 				else
2545 				{
2546 					rplci = plci;
2547 					rplci->cr_enquiry = false;
2548 				}
2549 
2550 				rplci->command = 0;
2551 				rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2552 				rplci->appl = appl;
2553 				rplci->number = Number;
2554 
2555 				cai[0] = 5;
2556 				cai[1] = DEACTIVATION_MWI; /* Function */
2557 				PUT_WORD(&cai[2], GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2558 				PUT_WORD(&cai[4], GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2559 				add_p(rplci, CAI, cai);
2560 				add_p(rplci, CPN, ss_parms[4].info); /* Receiving User Number */
2561 				add_p(rplci, OAD, ss_parms[5].info); /* Controlling User Number */
2562 				sig_req(rplci, S_SERVICE, 0);
2563 				send_req(rplci);
2564 				return false;
2565 
2566 			default:
2567 				Info = 0x300E;  /* not supported */
2568 				break;
2569 			}
2570 			break; /* case SELECTOR_SU_SERV: end */
2571 
2572 
2573 		case SELECTOR_DTMF:
2574 			return (dtmf_request(Id, Number, a, plci, appl, msg));
2575 
2576 
2577 
2578 		case SELECTOR_LINE_INTERCONNECT:
2579 			return (mixer_request(Id, Number, a, plci, appl, msg));
2580 
2581 
2582 
2583 		case PRIV_SELECTOR_ECHO_CANCELLER:
2584 			appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2585 			return (ec_request(Id, Number, a, plci, appl, msg));
2586 
2587 		case SELECTOR_ECHO_CANCELLER:
2588 			appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2589 			return (ec_request(Id, Number, a, plci, appl, msg));
2590 
2591 
2592 		case SELECTOR_V42BIS:
2593 		default:
2594 			Info = _FACILITY_NOT_SUPPORTED;
2595 			break;
2596 		} /* end of switch (selector) */
2597 	}
2598 
2599 	dbug(1, dprintf("SendFacRc"));
2600 	sendf(appl,
2601 	      _FACILITY_R | CONFIRM,
2602 	      Id,
2603 	      Number,
2604 	      "wws", Info, selector, SSparms);
2605 	return false;
2606 }
2607 
facility_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)2608 static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2609 			 PLCI *plci, APPL *appl, API_PARSE *msg)
2610 {
2611 	dbug(1, dprintf("facility_res"));
2612 	return false;
2613 }
2614 
connect_b3_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)2615 static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2616 			   PLCI *plci, APPL *appl, API_PARSE *parms)
2617 {
2618 	word Info = 0;
2619 	byte req;
2620 	byte len;
2621 	word w;
2622 	word fax_control_bits, fax_feature_bits, fax_info_change;
2623 	API_PARSE *ncpi;
2624 	byte pvc[2];
2625 
2626 	API_PARSE fax_parms[9];
2627 	word i;
2628 
2629 
2630 	dbug(1, dprintf("connect_b3_req"));
2631 	if (plci)
2632 	{
2633 		if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2634 		    || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2635 		{
2636 			Info = _WRONG_STATE;
2637 		}
2638 		else
2639 		{
2640 			/* local reply if assign unsuccessful
2641 			   or B3 protocol allows only one layer 3 connection
2642 			   and already connected
2643 			   or B2 protocol not any LAPD
2644 			   and connect_b3_req contradicts originate/answer direction */
2645 			if (!plci->NL.Id
2646 			    || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2647 				&& ((plci->channels != 0)
2648 				    || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2649 					&& ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2650 			{
2651 				dbug(1, dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2652 						plci->channels, plci->NL.Id, plci->call_dir, plci->SuppState));
2653 				Info = _WRONG_STATE;
2654 				sendf(appl,
2655 				      _CONNECT_B3_R | CONFIRM,
2656 				      Id,
2657 				      Number,
2658 				      "w", Info);
2659 				return false;
2660 			}
2661 			plci->requested_options_conn = 0;
2662 
2663 			req = N_CONNECT;
2664 			ncpi = &parms[0];
2665 			if (plci->B3_prot == 2 || plci->B3_prot == 3)
2666 			{
2667 				if (ncpi->length > 2)
2668 				{
2669 					/* check for PVC */
2670 					if (ncpi->info[2] || ncpi->info[3])
2671 					{
2672 						pvc[0] = ncpi->info[3];
2673 						pvc[1] = ncpi->info[2];
2674 						add_d(plci, 2, pvc);
2675 						req = N_RESET;
2676 					}
2677 					else
2678 					{
2679 						if (ncpi->info[1] & 1) req = N_CONNECT | N_D_BIT;
2680 						add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2681 					}
2682 				}
2683 			}
2684 			else if (plci->B3_prot == 5)
2685 			{
2686 				if (plci->NL.Id && !plci->nl_remove_id)
2687 				{
2688 					fax_control_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low);
2689 					fax_feature_bits = GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low);
2690 					if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2691 					    || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2692 					{
2693 						len = offsetof(T30_INFO, universal_6);
2694 						fax_info_change = false;
2695 						if (ncpi->length >= 4)
2696 						{
2697 							w = GET_WORD(&ncpi->info[3]);
2698 							if ((w & 0x0001) != ((word)(((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2699 							{
2700 								((T30_INFO *)(plci->fax_connect_info_buffer))->resolution =
2701 									(byte)((((T30_INFO *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2702 									       ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2703 								fax_info_change = true;
2704 							}
2705 							fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2706 							if (w & 0x0002)  /* Fax-polling request */
2707 								fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2708 							if ((w & 0x0004) /* Request to send / poll another document */
2709 							    && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2710 							{
2711 								fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2712 							}
2713 							if (ncpi->length >= 6)
2714 							{
2715 								w = GET_WORD(&ncpi->info[5]);
2716 								if (((byte) w) != ((T30_INFO *)(plci->fax_connect_info_buffer))->data_format)
2717 								{
2718 									((T30_INFO *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2719 									fax_info_change = true;
2720 								}
2721 
2722 								if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2723 								    && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2724 								{
2725 									plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2726 								}
2727 								if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2728 								    && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2729 								{
2730 									plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2731 								}
2732 								fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2733 										      T30_CONTROL_BIT_ACCEPT_PASSWORD);
2734 								if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2735 								    & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2736 								{
2737 									if (api_parse(&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2738 										Info = _WRONG_MESSAGE_FORMAT;
2739 									else
2740 									{
2741 										if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2742 										    & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2743 										{
2744 											fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2745 											if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2746 												fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2747 										}
2748 										w = fax_parms[4].length;
2749 										if (w > 20)
2750 											w = 20;
2751 										((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2752 										for (i = 0; i < w; i++)
2753 											((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1 + i];
2754 										((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2755 										len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2756 										w = fax_parms[5].length;
2757 										if (w > 20)
2758 											w = 20;
2759 										plci->fax_connect_info_buffer[len++] = (byte) w;
2760 										for (i = 0; i < w; i++)
2761 											plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1 + i];
2762 										w = fax_parms[6].length;
2763 										if (w > 20)
2764 											w = 20;
2765 										plci->fax_connect_info_buffer[len++] = (byte) w;
2766 										for (i = 0; i < w; i++)
2767 											plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1 + i];
2768 										if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id - 1])
2769 										    & (1L << PRIVATE_FAX_NONSTANDARD))
2770 										{
2771 											if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2772 											{
2773 												dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2774 												plci->fax_connect_info_buffer[len++] = 0;
2775 											}
2776 											else
2777 											{
2778 												if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2779 													plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2780 												plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2781 												for (i = 0; i < fax_parms[7].length; i++)
2782 													plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2783 											}
2784 										}
2785 									}
2786 								}
2787 								else
2788 								{
2789 									len = offsetof(T30_INFO, universal_6);
2790 								}
2791 								fax_info_change = true;
2792 
2793 							}
2794 							if (fax_control_bits != GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low))
2795 							{
2796 								PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2797 								fax_info_change = true;
2798 							}
2799 						}
2800 						if (Info == GOOD)
2801 						{
2802 							plci->fax_connect_info_length = len;
2803 							if (fax_info_change)
2804 							{
2805 								if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2806 								{
2807 									start_internal_command(Id, plci, fax_connect_info_command);
2808 									return false;
2809 								}
2810 								else
2811 								{
2812 									start_internal_command(Id, plci, fax_adjust_b23_command);
2813 									return false;
2814 								}
2815 							}
2816 						}
2817 					}
2818 					else  Info = _WRONG_STATE;
2819 				}
2820 				else  Info = _WRONG_STATE;
2821 			}
2822 
2823 			else if (plci->B3_prot == B3_RTP)
2824 			{
2825 				plci->internal_req_buffer[0] = ncpi->length + 1;
2826 				plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2827 				for (w = 0; w < ncpi->length; w++)
2828 					plci->internal_req_buffer[2 + w] = ncpi->info[1 + w];
2829 				start_internal_command(Id, plci, rtp_connect_b3_req_command);
2830 				return false;
2831 			}
2832 
2833 			if (!Info)
2834 			{
2835 				nl_req_ncci(plci, req, 0);
2836 				return 1;
2837 			}
2838 		}
2839 	}
2840 	else Info = _WRONG_IDENTIFIER;
2841 
2842 	sendf(appl,
2843 	      _CONNECT_B3_R | CONFIRM,
2844 	      Id,
2845 	      Number,
2846 	      "w", Info);
2847 	return false;
2848 }
2849 
connect_b3_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)2850 static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2851 			   PLCI *plci, APPL *appl, API_PARSE *parms)
2852 {
2853 	word ncci;
2854 	API_PARSE *ncpi;
2855 	byte req;
2856 
2857 	word w;
2858 
2859 
2860 	API_PARSE fax_parms[9];
2861 	word i;
2862 	byte len;
2863 
2864 
2865 	dbug(1, dprintf("connect_b3_res"));
2866 
2867 	ncci = (word)(Id >> 16);
2868 	if (plci && ncci) {
2869 		if (a->ncci_state[ncci] == INC_CON_PENDING) {
2870 			if (GET_WORD(&parms[0].info[0]) != 0)
2871 			{
2872 				a->ncci_state[ncci] = OUTG_REJ_PENDING;
2873 				channel_request_xon(plci, a->ncci_ch[ncci]);
2874 				channel_xmit_xon(plci);
2875 				cleanup_ncci_data(plci, ncci);
2876 				nl_req_ncci(plci, N_DISC, (byte)ncci);
2877 				return 1;
2878 			}
2879 			a->ncci_state[ncci] = INC_ACT_PENDING;
2880 
2881 			req = N_CONNECT_ACK;
2882 			ncpi = &parms[1];
2883 			if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2884 			{
2885 
2886 				if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
2887 				    & (1L << PRIVATE_FAX_NONSTANDARD))
2888 				{
2889 					if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2890 					    && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2891 					    && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2892 					{
2893 						len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
2894 						if (plci->fax_connect_info_length < len)
2895 						{
2896 							((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2897 							((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2898 						}
2899 						if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2900 						{
2901 							dbug(1, dprintf("non-standard facilities info missing or wrong format"));
2902 						}
2903 						else
2904 						{
2905 							if (plci->fax_connect_info_length <= len)
2906 								plci->fax_connect_info_buffer[len] = 0;
2907 							len += 1 + plci->fax_connect_info_buffer[len];
2908 							if (plci->fax_connect_info_length <= len)
2909 								plci->fax_connect_info_buffer[len] = 0;
2910 							len += 1 + plci->fax_connect_info_buffer[len];
2911 							if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2912 								plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2913 							plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2914 							for (i = 0; i < fax_parms[7].length; i++)
2915 								plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
2916 						}
2917 						plci->fax_connect_info_length = len;
2918 						((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2919 						start_internal_command(Id, plci, fax_connect_ack_command);
2920 						return false;
2921 					}
2922 				}
2923 
2924 				nl_req_ncci(plci, req, (byte)ncci);
2925 				if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2926 				    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2927 				{
2928 					if (plci->B3_prot == 4)
2929 						sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2930 					else
2931 						sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
2932 					plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2933 				}
2934 			}
2935 
2936 			else if (plci->B3_prot == B3_RTP)
2937 			{
2938 				plci->internal_req_buffer[0] = ncpi->length + 1;
2939 				plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2940 				for (w = 0; w < ncpi->length; w++)
2941 					plci->internal_req_buffer[2 + w] = ncpi->info[1+w];
2942 				start_internal_command(Id, plci, rtp_connect_b3_res_command);
2943 				return false;
2944 			}
2945 
2946 			else
2947 			{
2948 				if (ncpi->length > 2) {
2949 					if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
2950 					add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
2951 				}
2952 				nl_req_ncci(plci, req, (byte)ncci);
2953 				sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
2954 				if (plci->adjust_b_restore)
2955 				{
2956 					plci->adjust_b_restore = false;
2957 					start_internal_command(Id, plci, adjust_b_restore);
2958 				}
2959 			}
2960 			return 1;
2961 		}
2962 	}
2963 	return false;
2964 }
2965 
connect_b3_a_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)2966 static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2967 			     PLCI *plci, APPL *appl, API_PARSE *parms)
2968 {
2969 	word ncci;
2970 
2971 	ncci = (word)(Id >> 16);
2972 	dbug(1, dprintf("connect_b3_a_res(ncci=0x%x)", ncci));
2973 
2974 	if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2975 	    && (plci->State != OUTG_DIS_PENDING))
2976 	{
2977 		if (a->ncci_state[ncci] == INC_ACT_PENDING) {
2978 			a->ncci_state[ncci] = CONNECTED;
2979 			if (plci->State != INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2980 			channel_request_xon(plci, a->ncci_ch[ncci]);
2981 			channel_xmit_xon(plci);
2982 		}
2983 	}
2984 	return false;
2985 }
2986 
disconnect_b3_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)2987 static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2988 			      PLCI *plci, APPL *appl, API_PARSE *parms)
2989 {
2990 	word Info;
2991 	word ncci;
2992 	API_PARSE *ncpi;
2993 
2994 	dbug(1, dprintf("disconnect_b3_req"));
2995 
2996 	Info = _WRONG_IDENTIFIER;
2997 	ncci = (word)(Id >> 16);
2998 	if (plci && ncci)
2999 	{
3000 		Info = _WRONG_STATE;
3001 		if ((a->ncci_state[ncci] == CONNECTED)
3002 		    || (a->ncci_state[ncci] == OUTG_CON_PENDING)
3003 		    || (a->ncci_state[ncci] == INC_CON_PENDING)
3004 		    || (a->ncci_state[ncci] == INC_ACT_PENDING))
3005 		{
3006 			a->ncci_state[ncci] = OUTG_DIS_PENDING;
3007 			channel_request_xon(plci, a->ncci_ch[ncci]);
3008 			channel_xmit_xon(plci);
3009 
3010 			if (a->ncci[ncci].data_pending
3011 			    && ((plci->B3_prot == B3_TRANSPARENT)
3012 				|| (plci->B3_prot == B3_T30)
3013 				|| (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3014 			{
3015 				plci->send_disc = (byte)ncci;
3016 				plci->command = 0;
3017 				return false;
3018 			}
3019 			else
3020 			{
3021 				cleanup_ncci_data(plci, ncci);
3022 
3023 				if (plci->B3_prot == 2 || plci->B3_prot == 3)
3024 				{
3025 					ncpi = &parms[0];
3026 					if (ncpi->length > 3)
3027 					{
3028 						add_d(plci, (word)(ncpi->length - 3), (byte *)&(ncpi->info[4]));
3029 					}
3030 				}
3031 				nl_req_ncci(plci, N_DISC, (byte)ncci);
3032 			}
3033 			return 1;
3034 		}
3035 	}
3036 	sendf(appl,
3037 	      _DISCONNECT_B3_R | CONFIRM,
3038 	      Id,
3039 	      Number,
3040 	      "w", Info);
3041 	return false;
3042 }
3043 
disconnect_b3_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)3044 static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3045 			      PLCI *plci, APPL *appl, API_PARSE *parms)
3046 {
3047 	word ncci;
3048 	word i;
3049 
3050 	ncci = (word)(Id >> 16);
3051 	dbug(1, dprintf("disconnect_b3_res(ncci=0x%x", ncci));
3052 	if (plci && ncci) {
3053 		plci->requested_options_conn = 0;
3054 		plci->fax_connect_info_length = 0;
3055 		plci->ncpi_state = 0x00;
3056 		if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3057 		    && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3058 		{
3059 			plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3060 		}
3061 		for (i = 0; i < MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i] != (byte)ncci; i++);
3062 		if (i < MAX_CHANNELS_PER_PLCI) {
3063 			if (plci->channels)plci->channels--;
3064 			for (; i < MAX_CHANNELS_PER_PLCI - 1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i + 1];
3065 			plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI - 1] = 0;
3066 
3067 			ncci_free_receive_buffers(plci, ncci);
3068 
3069 			if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
3070 				if (plci->State == SUSPENDING) {
3071 					sendf(plci->appl,
3072 					      _FACILITY_I,
3073 					      Id & 0xffffL,
3074 					      0,
3075 					      "ws", (word)3, "\x03\x04\x00\x00");
3076 					sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3077 				}
3078 				plci_remove(plci);
3079 				plci->State = IDLE;
3080 			}
3081 		}
3082 		else
3083 		{
3084 			if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3085 			    && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3086 			    && (a->ncci_state[ncci] == INC_DIS_PENDING))
3087 			{
3088 				ncci_free_receive_buffers(plci, ncci);
3089 
3090 				nl_req_ncci(plci, N_EDATA, (byte)ncci);
3091 
3092 				plci->adapter->ncci_state[ncci] = IDLE;
3093 				start_internal_command(Id, plci, fax_disconnect_command);
3094 				return 1;
3095 			}
3096 		}
3097 	}
3098 	return false;
3099 }
3100 
data_b3_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)3101 static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3102 			PLCI *plci, APPL *appl, API_PARSE *parms)
3103 {
3104 	NCCI *ncci_ptr;
3105 	DATA_B3_DESC *data;
3106 	word Info;
3107 	word ncci;
3108 	word i;
3109 
3110 	dbug(1, dprintf("data_b3_req"));
3111 
3112 	Info = _WRONG_IDENTIFIER;
3113 	ncci = (word)(Id >> 16);
3114 	dbug(1, dprintf("ncci=0x%x, plci=0x%x", ncci, plci));
3115 
3116 	if (plci && ncci)
3117 	{
3118 		Info = _WRONG_STATE;
3119 		if ((a->ncci_state[ncci] == CONNECTED)
3120 		    || (a->ncci_state[ncci] == INC_ACT_PENDING))
3121 		{
3122 			/* queue data */
3123 			ncci_ptr = &(a->ncci[ncci]);
3124 			i = ncci_ptr->data_out + ncci_ptr->data_pending;
3125 			if (i >= MAX_DATA_B3)
3126 				i -= MAX_DATA_B3;
3127 			data = &(ncci_ptr->DBuffer[i]);
3128 			data->Number = Number;
3129 			if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3130 			    && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3131 			{
3132 
3133 				data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3134 
3135 			}
3136 			else
3137 				data->P = TransmitBufferSet(appl, *(dword *)parms[0].info);
3138 			data->Length = GET_WORD(parms[1].info);
3139 			data->Handle = GET_WORD(parms[2].info);
3140 			data->Flags = GET_WORD(parms[3].info);
3141 			(ncci_ptr->data_pending)++;
3142 
3143 			/* check for delivery confirmation */
3144 			if (data->Flags & 0x0004)
3145 			{
3146 				i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3147 				if (i >= MAX_DATA_ACK)
3148 					i -= MAX_DATA_ACK;
3149 				ncci_ptr->DataAck[i].Number = data->Number;
3150 				ncci_ptr->DataAck[i].Handle = data->Handle;
3151 				(ncci_ptr->data_ack_pending)++;
3152 			}
3153 
3154 			send_data(plci);
3155 			return false;
3156 		}
3157 	}
3158 	if (appl)
3159 	{
3160 		if (plci)
3161 		{
3162 			if ((((byte *)(parms[0].info)) >= ((byte *)(plci->msg_in_queue)))
3163 			    && (((byte *)(parms[0].info)) < ((byte *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3164 			{
3165 
3166 				TransmitBufferFree(appl, (byte *)(long)(*((dword *)(parms[0].info))));
3167 
3168 			}
3169 		}
3170 		sendf(appl,
3171 		      _DATA_B3_R | CONFIRM,
3172 		      Id,
3173 		      Number,
3174 		      "ww", GET_WORD(parms[2].info), Info);
3175 	}
3176 	return false;
3177 }
3178 
data_b3_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)3179 static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3180 			PLCI *plci, APPL *appl, API_PARSE *parms)
3181 {
3182 	word n;
3183 	word ncci;
3184 	word NCCIcode;
3185 
3186 	dbug(1, dprintf("data_b3_res"));
3187 
3188 	ncci = (word)(Id >> 16);
3189 	if (plci && ncci) {
3190 		n = GET_WORD(parms[0].info);
3191 		dbug(1, dprintf("free(%d)", n));
3192 		NCCIcode = ncci | (((word) a->Id) << 8);
3193 		if (n < appl->MaxBuffer &&
3194 		    appl->DataNCCI[n] == NCCIcode &&
3195 		    (byte)(appl->DataFlags[n] >> 8) == plci->Id) {
3196 			dbug(1, dprintf("found"));
3197 			appl->DataNCCI[n] = 0;
3198 
3199 			if (channel_can_xon(plci, a->ncci_ch[ncci])) {
3200 				channel_request_xon(plci, a->ncci_ch[ncci]);
3201 			}
3202 			channel_xmit_xon(plci);
3203 
3204 			if (appl->DataFlags[n] & 4) {
3205 				nl_req_ncci(plci, N_DATA_ACK, (byte)ncci);
3206 				return 1;
3207 			}
3208 		}
3209 	}
3210 	return false;
3211 }
3212 
reset_b3_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)3213 static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3214 			 PLCI *plci, APPL *appl, API_PARSE *parms)
3215 {
3216 	word Info;
3217 	word ncci;
3218 
3219 	dbug(1, dprintf("reset_b3_req"));
3220 
3221 	Info = _WRONG_IDENTIFIER;
3222 	ncci = (word)(Id >> 16);
3223 	if (plci && ncci)
3224 	{
3225 		Info = _WRONG_STATE;
3226 		switch (plci->B3_prot)
3227 		{
3228 		case B3_ISO8208:
3229 		case B3_X25_DCE:
3230 			if (a->ncci_state[ncci] == CONNECTED)
3231 			{
3232 				nl_req_ncci(plci, N_RESET, (byte)ncci);
3233 				send_req(plci);
3234 				Info = GOOD;
3235 			}
3236 			break;
3237 		case B3_TRANSPARENT:
3238 			if (a->ncci_state[ncci] == CONNECTED)
3239 			{
3240 				start_internal_command(Id, plci, reset_b3_command);
3241 				Info = GOOD;
3242 			}
3243 			break;
3244 		}
3245 	}
3246 	/* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3247 	sendf(appl,
3248 	      _RESET_B3_R | CONFIRM,
3249 	      Id,
3250 	      Number,
3251 	      "w", Info);
3252 	return false;
3253 }
3254 
reset_b3_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)3255 static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3256 			 PLCI *plci, APPL *appl, API_PARSE *parms)
3257 {
3258 	word ncci;
3259 
3260 	dbug(1, dprintf("reset_b3_res"));
3261 
3262 	ncci = (word)(Id >> 16);
3263 	if (plci && ncci) {
3264 		switch (plci->B3_prot)
3265 		{
3266 		case B3_ISO8208:
3267 		case B3_X25_DCE:
3268 			if (a->ncci_state[ncci] == INC_RES_PENDING)
3269 			{
3270 				a->ncci_state[ncci] = CONNECTED;
3271 				nl_req_ncci(plci, N_RESET_ACK, (byte)ncci);
3272 				return true;
3273 			}
3274 			break;
3275 		}
3276 	}
3277 	return false;
3278 }
3279 
connect_b3_t90_a_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)3280 static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3281 				 PLCI *plci, APPL *appl, API_PARSE *parms)
3282 {
3283 	word ncci;
3284 	API_PARSE *ncpi;
3285 	byte req;
3286 
3287 	dbug(1, dprintf("connect_b3_t90_a_res"));
3288 
3289 	ncci = (word)(Id >> 16);
3290 	if (plci && ncci) {
3291 		if (a->ncci_state[ncci] == INC_ACT_PENDING) {
3292 			a->ncci_state[ncci] = CONNECTED;
3293 		}
3294 		else if (a->ncci_state[ncci] == INC_CON_PENDING) {
3295 			a->ncci_state[ncci] = CONNECTED;
3296 
3297 			req = N_CONNECT_ACK;
3298 
3299 			/* parms[0]==0 for CAPI original message definition! */
3300 			if (parms[0].info) {
3301 				ncpi = &parms[1];
3302 				if (ncpi->length > 2) {
3303 					if (ncpi->info[1] & 1) req = N_CONNECT_ACK | N_D_BIT;
3304 					add_d(plci, (word)(ncpi->length - 3), &ncpi->info[4]);
3305 				}
3306 			}
3307 			nl_req_ncci(plci, req, (byte)ncci);
3308 			return 1;
3309 		}
3310 	}
3311 	return false;
3312 }
3313 
3314 
select_b_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)3315 static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3316 			 PLCI *plci, APPL *appl, API_PARSE *msg)
3317 {
3318 	word Info = 0;
3319 	word i;
3320 	byte tel;
3321 	API_PARSE bp_parms[7];
3322 
3323 	if (!plci || !msg)
3324 	{
3325 		Info = _WRONG_IDENTIFIER;
3326 	}
3327 	else
3328 	{
3329 		dbug(1, dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3330 				msg->length, plci->Id, plci->tel, plci->NL.Id, plci->appl, plci->SuppState));
3331 		dbug(1, dprintf("PlciState=0x%x", plci->State));
3332 		for (i = 0; i < 7; i++) bp_parms[i].length = 0;
3333 
3334 		/* check if no channel is open, no B3 connected only */
3335 		if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3336 		    || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3337 		{
3338 			Info = _WRONG_STATE;
3339 		}
3340 		/* check message format and fill bp_parms pointer */
3341 		else if (msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3342 		{
3343 			Info = _WRONG_MESSAGE_FORMAT;
3344 		}
3345 		else
3346 		{
3347 			if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT)) /* send alert tone inband to the network, */
3348 			{                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3349 				if (Id & EXT_CONTROLLER)
3350 				{
3351 					sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3352 					return 0;
3353 				}
3354 				plci->State = INC_CON_CONNECTED_ALERT;
3355 				plci->appl = appl;
3356 				clear_c_ind_mask_bit(plci, (word)(appl->Id - 1));
3357 				dump_c_ind_mask(plci);
3358 				for (i = 0; i < max_appl; i++) /* disconnect the other appls */
3359 				{                         /* its quasi a connect        */
3360 					if (test_c_ind_mask_bit(plci, i))
3361 						sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3362 				}
3363 			}
3364 
3365 			api_save_msg(msg, "s", &plci->saved_msg);
3366 			tel = plci->tel;
3367 			if (Id & EXT_CONTROLLER)
3368 			{
3369 				if (tel) /* external controller in use by this PLCI */
3370 				{
3371 					if (a->AdvSignalAppl && a->AdvSignalAppl != appl)
3372 					{
3373 						dbug(1, dprintf("Ext_Ctrl in use 1"));
3374 						Info = _WRONG_STATE;
3375 					}
3376 				}
3377 				else  /* external controller NOT in use by this PLCI ? */
3378 				{
3379 					if (a->AdvSignalPLCI)
3380 					{
3381 						dbug(1, dprintf("Ext_Ctrl in use 2"));
3382 						Info = _WRONG_STATE;
3383 					}
3384 					else /* activate the codec */
3385 					{
3386 						dbug(1, dprintf("Ext_Ctrl start"));
3387 						if (AdvCodecSupport(a, plci, appl, 0))
3388 						{
3389 							dbug(1, dprintf("Error in codec procedures"));
3390 							Info = _WRONG_STATE;
3391 						}
3392 						else if (plci->spoofed_msg == SPOOFING_REQUIRED) /* wait until codec is active */
3393 						{
3394 							plci->spoofed_msg = AWAITING_SELECT_B;
3395 							plci->internal_command = BLOCK_PLCI; /* lock other commands */
3396 							plci->command = 0;
3397 							dbug(1, dprintf("continue if codec loaded"));
3398 							return false;
3399 						}
3400 					}
3401 				}
3402 			}
3403 			else /* external controller bit is OFF */
3404 			{
3405 				if (tel) /* external controller in use, need to switch off */
3406 				{
3407 					if (a->AdvSignalAppl == appl)
3408 					{
3409 						CodecIdCheck(a, plci);
3410 						plci->tel = 0;
3411 						plci->adv_nl = 0;
3412 						dbug(1, dprintf("Ext_Ctrl disable"));
3413 					}
3414 					else
3415 					{
3416 						dbug(1, dprintf("Ext_Ctrl not requested"));
3417 					}
3418 				}
3419 			}
3420 			if (!Info)
3421 			{
3422 				if (plci->call_dir & CALL_DIR_OUT)
3423 					plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3424 				else if (plci->call_dir & CALL_DIR_IN)
3425 					plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3426 				start_internal_command(Id, plci, select_b_command);
3427 				return false;
3428 			}
3429 		}
3430 	}
3431 	sendf(appl, _SELECT_B_REQ | CONFIRM, Id, Number, "w", Info);
3432 	return false;
3433 }
3434 
manufacturer_req(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * parms)3435 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3436 			     PLCI *plci, APPL *appl, API_PARSE *parms)
3437 {
3438 	word command;
3439 	word i;
3440 	word ncci;
3441 	API_PARSE *m;
3442 	API_PARSE m_parms[5];
3443 	word codec;
3444 	byte req;
3445 	byte ch;
3446 	byte dir;
3447 	static byte chi[2] = {0x01, 0x00};
3448 	static byte lli[2] = {0x01, 0x00};
3449 	static byte codec_cai[2] = {0x01, 0x01};
3450 	static byte null_msg = {0};
3451 	static API_PARSE null_parms = { 0, &null_msg };
3452 	PLCI *v_plci;
3453 	word Info = 0;
3454 
3455 	dbug(1, dprintf("manufacturer_req"));
3456 	for (i = 0; i < 5; i++) m_parms[i].length = 0;
3457 
3458 	if (GET_DWORD(parms[0].info) != _DI_MANU_ID) {
3459 		Info = _WRONG_MESSAGE_FORMAT;
3460 	}
3461 	command = GET_WORD(parms[1].info);
3462 	m = &parms[2];
3463 	if (!Info)
3464 	{
3465 		switch (command) {
3466 		case _DI_ASSIGN_PLCI:
3467 			if (api_parse(&m->info[1], (word)m->length, "wbbs", m_parms)) {
3468 				Info = _WRONG_MESSAGE_FORMAT;
3469 				break;
3470 			}
3471 			codec = GET_WORD(m_parms[0].info);
3472 			ch = m_parms[1].info[0];
3473 			dir = m_parms[2].info[0];
3474 			if ((i = get_plci(a))) {
3475 				plci = &a->plci[i - 1];
3476 				plci->appl = appl;
3477 				plci->command = _MANUFACTURER_R;
3478 				plci->m_command = command;
3479 				plci->number = Number;
3480 				plci->State = LOCAL_CONNECT;
3481 				Id = (((word)plci->Id << 8) | plci->adapter->Id | 0x80);
3482 				dbug(1, dprintf("ManCMD,plci=0x%x", Id));
3483 
3484 				if ((ch == 1 || ch == 2) && (dir <= 2)) {
3485 					chi[1] = (byte)(0x80 | ch);
3486 					lli[1] = 0;
3487 					plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3488 					switch (codec)
3489 					{
3490 					case 0:
3491 						Info = add_b1(plci, &m_parms[3], 0, 0);
3492 						break;
3493 					case 1:
3494 						add_p(plci, CAI, codec_cai);
3495 						break;
3496 						/* manual 'swich on' to the codec support without signalling */
3497 						/* first 'assign plci' with this function, then use */
3498 					case 2:
3499 						if (AdvCodecSupport(a, plci, appl, 0)) {
3500 							Info = _RESOURCE_ERROR;
3501 						}
3502 						else {
3503 							Info = add_b1(plci, &null_parms, 0, B1_FACILITY_LOCAL);
3504 							lli[1] = 0x10; /* local call codec stream */
3505 						}
3506 						break;
3507 					}
3508 
3509 					plci->State = LOCAL_CONNECT;
3510 					plci->manufacturer = true;
3511 					plci->command = _MANUFACTURER_R;
3512 					plci->m_command = command;
3513 					plci->number = Number;
3514 
3515 					if (!Info)
3516 					{
3517 						add_p(plci, LLI, lli);
3518 						add_p(plci, CHI, chi);
3519 						add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
3520 						sig_req(plci, ASSIGN, DSIG_ID);
3521 
3522 						if (!codec)
3523 						{
3524 							Info = add_b23(plci, &m_parms[3]);
3525 							if (!Info)
3526 							{
3527 								nl_req_ncci(plci, ASSIGN, 0);
3528 								send_req(plci);
3529 							}
3530 						}
3531 						if (!Info)
3532 						{
3533 							dbug(1, dprintf("dir=0x%x,spoof=0x%x", dir, plci->spoofed_msg));
3534 							if (plci->spoofed_msg == SPOOFING_REQUIRED)
3535 							{
3536 								api_save_msg(m_parms, "wbbs", &plci->saved_msg);
3537 								plci->spoofed_msg = AWAITING_MANUF_CON;
3538 								plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3539 								plci->command = 0;
3540 								send_req(plci);
3541 								return false;
3542 							}
3543 							if (dir == 1) {
3544 								sig_req(plci, CALL_REQ, 0);
3545 							}
3546 							else if (!dir) {
3547 								sig_req(plci, LISTEN_REQ, 0);
3548 							}
3549 							send_req(plci);
3550 						}
3551 						else
3552 						{
3553 							sendf(appl,
3554 							      _MANUFACTURER_R | CONFIRM,
3555 							      Id,
3556 							      Number,
3557 							      "dww", _DI_MANU_ID, command, Info);
3558 							return 2;
3559 						}
3560 					}
3561 				}
3562 			}
3563 			else  Info = _OUT_OF_PLCI;
3564 			break;
3565 
3566 		case _DI_IDI_CTRL:
3567 			if (!plci)
3568 			{
3569 				Info = _WRONG_IDENTIFIER;
3570 				break;
3571 			}
3572 			if (api_parse(&m->info[1], (word)m->length, "bs", m_parms)) {
3573 				Info = _WRONG_MESSAGE_FORMAT;
3574 				break;
3575 			}
3576 			req = m_parms[0].info[0];
3577 			plci->command = _MANUFACTURER_R;
3578 			plci->m_command = command;
3579 			plci->number = Number;
3580 			if (req == CALL_REQ)
3581 			{
3582 				plci->b_channel = getChannel(&m_parms[1]);
3583 				mixer_set_bchannel_id_esc(plci, plci->b_channel);
3584 				if (plci->spoofed_msg == SPOOFING_REQUIRED)
3585 				{
3586 					plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3587 					plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3588 					plci->command = 0;
3589 					break;
3590 				}
3591 			}
3592 			else if (req == LAW_REQ)
3593 			{
3594 				plci->cr_enquiry = true;
3595 			}
3596 			add_ss(plci, FTY, &m_parms[1]);
3597 			sig_req(plci, req, 0);
3598 			send_req(plci);
3599 			if (req == HANGUP)
3600 			{
3601 				if (plci->NL.Id && !plci->nl_remove_id)
3602 				{
3603 					if (plci->channels)
3604 					{
3605 						for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
3606 						{
3607 							if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3608 							{
3609 								a->ncci_state[ncci] = OUTG_DIS_PENDING;
3610 								cleanup_ncci_data(plci, ncci);
3611 								nl_req_ncci(plci, N_DISC, (byte)ncci);
3612 							}
3613 						}
3614 					}
3615 					mixer_remove(plci);
3616 					nl_req_ncci(plci, REMOVE, 0);
3617 					send_req(plci);
3618 				}
3619 			}
3620 			break;
3621 
3622 		case _DI_SIG_CTRL:
3623 			/* signalling control for loop activation B-channel */
3624 			if (!plci)
3625 			{
3626 				Info = _WRONG_IDENTIFIER;
3627 				break;
3628 			}
3629 			if (m->length) {
3630 				plci->command = _MANUFACTURER_R;
3631 				plci->number = Number;
3632 				add_ss(plci, FTY, m);
3633 				sig_req(plci, SIG_CTRL, 0);
3634 				send_req(plci);
3635 			}
3636 			else Info = _WRONG_MESSAGE_FORMAT;
3637 			break;
3638 
3639 		case _DI_RXT_CTRL:
3640 			/* activation control for receiver/transmitter B-channel */
3641 			if (!plci)
3642 			{
3643 				Info = _WRONG_IDENTIFIER;
3644 				break;
3645 			}
3646 			if (m->length) {
3647 				plci->command = _MANUFACTURER_R;
3648 				plci->number = Number;
3649 				add_ss(plci, FTY, m);
3650 				sig_req(plci, DSP_CTRL, 0);
3651 				send_req(plci);
3652 			}
3653 			else Info = _WRONG_MESSAGE_FORMAT;
3654 			break;
3655 
3656 		case _DI_ADV_CODEC:
3657 		case _DI_DSP_CTRL:
3658 			/* TEL_CTRL commands to support non standard adjustments: */
3659 			/* Ring on/off, Handset micro volume, external micro vol. */
3660 			/* handset+external speaker volume, receiver+transm. gain,*/
3661 			/* handsfree on (hookinfo off), set mixer command         */
3662 
3663 			if (command == _DI_ADV_CODEC)
3664 			{
3665 				if (!a->AdvCodecPLCI) {
3666 					Info = _WRONG_STATE;
3667 					break;
3668 				}
3669 				v_plci = a->AdvCodecPLCI;
3670 			}
3671 			else
3672 			{
3673 				if (plci
3674 				    && (m->length >= 3)
3675 				    && (m->info[1] == 0x1c)
3676 				    && (m->info[2] >= 1))
3677 				{
3678 					if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3679 					{
3680 						if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3681 						{
3682 							Info = _WRONG_STATE;
3683 							break;
3684 						}
3685 						a->adv_voice_coef_length = m->info[2] - 1;
3686 						if (a->adv_voice_coef_length > m->length - 3)
3687 							a->adv_voice_coef_length = (byte)(m->length - 3);
3688 						if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3689 							a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3690 						for (i = 0; i < a->adv_voice_coef_length; i++)
3691 							a->adv_voice_coef_buffer[i] = m->info[4 + i];
3692 						if (plci->B1_facilities & B1_FACILITY_VOICE)
3693 							adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
3694 						break;
3695 					}
3696 					else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3697 					{
3698 						if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3699 						{
3700 							Info = _FACILITY_NOT_SUPPORTED;
3701 							break;
3702 						}
3703 
3704 						plci->dtmf_parameter_length = m->info[2] - 1;
3705 						if (plci->dtmf_parameter_length > m->length - 3)
3706 							plci->dtmf_parameter_length = (byte)(m->length - 3);
3707 						if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3708 							plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3709 						for (i = 0; i < plci->dtmf_parameter_length; i++)
3710 							plci->dtmf_parameter_buffer[i] = m->info[4 + i];
3711 						if (plci->B1_facilities & B1_FACILITY_DTMFR)
3712 							dtmf_parameter_write(plci);
3713 						break;
3714 
3715 					}
3716 				}
3717 				v_plci = plci;
3718 			}
3719 
3720 			if (!v_plci)
3721 			{
3722 				Info = _WRONG_IDENTIFIER;
3723 				break;
3724 			}
3725 			if (m->length) {
3726 				add_ss(v_plci, FTY, m);
3727 				sig_req(v_plci, TEL_CTRL, 0);
3728 				send_req(v_plci);
3729 			}
3730 			else Info = _WRONG_MESSAGE_FORMAT;
3731 
3732 			break;
3733 
3734 		case _DI_OPTIONS_REQUEST:
3735 			if (api_parse(&m->info[1], (word)m->length, "d", m_parms)) {
3736 				Info = _WRONG_MESSAGE_FORMAT;
3737 				break;
3738 			}
3739 			if (GET_DWORD(m_parms[0].info) & ~a->man_profile.private_options)
3740 			{
3741 				Info = _FACILITY_NOT_SUPPORTED;
3742 				break;
3743 			}
3744 			a->requested_options_table[appl->Id - 1] = GET_DWORD(m_parms[0].info);
3745 			break;
3746 
3747 
3748 
3749 		default:
3750 			Info = _WRONG_MESSAGE_FORMAT;
3751 			break;
3752 		}
3753 	}
3754 
3755 	sendf(appl,
3756 	      _MANUFACTURER_R | CONFIRM,
3757 	      Id,
3758 	      Number,
3759 	      "dww", _DI_MANU_ID, command, Info);
3760 	return false;
3761 }
3762 
3763 
manufacturer_res(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)3764 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3765 			     PLCI *plci, APPL *appl, API_PARSE *msg)
3766 {
3767 	word indication;
3768 
3769 	API_PARSE m_parms[3];
3770 	API_PARSE *ncpi;
3771 	API_PARSE fax_parms[9];
3772 	word i;
3773 	byte len;
3774 
3775 
3776 	dbug(1, dprintf("manufacturer_res"));
3777 
3778 	if ((msg[0].length == 0)
3779 	    || (msg[1].length == 0)
3780 	    || (GET_DWORD(msg[0].info) != _DI_MANU_ID))
3781 	{
3782 		return false;
3783 	}
3784 	indication = GET_WORD(msg[1].info);
3785 	switch (indication)
3786 	{
3787 
3788 	case _DI_NEGOTIATE_B3:
3789 		if (!plci)
3790 			break;
3791 		if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3792 		    || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3793 		{
3794 			dbug(1, dprintf("wrong state for NEGOTIATE_B3 parameters"));
3795 			break;
3796 		}
3797 		if (api_parse(&msg[2].info[1], msg[2].length, "ws", m_parms))
3798 		{
3799 			dbug(1, dprintf("wrong format in NEGOTIATE_B3 parameters"));
3800 			break;
3801 		}
3802 		ncpi = &m_parms[1];
3803 		len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
3804 		if (plci->fax_connect_info_length < len)
3805 		{
3806 			((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3807 			((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3808 		}
3809 		if (api_parse(&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3810 		{
3811 			dbug(1, dprintf("non-standard facilities info missing or wrong format"));
3812 		}
3813 		else
3814 		{
3815 			if (plci->fax_connect_info_length <= len)
3816 				plci->fax_connect_info_buffer[len] = 0;
3817 			len += 1 + plci->fax_connect_info_buffer[len];
3818 			if (plci->fax_connect_info_length <= len)
3819 				plci->fax_connect_info_buffer[len] = 0;
3820 			len += 1 + plci->fax_connect_info_buffer[len];
3821 			if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3822 				plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3823 			plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3824 			for (i = 0; i < fax_parms[7].length; i++)
3825 				plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1 + i];
3826 		}
3827 		plci->fax_connect_info_length = len;
3828 		plci->fax_edata_ack_length = plci->fax_connect_info_length;
3829 		start_internal_command(Id, plci, fax_edata_ack_command);
3830 		break;
3831 
3832 	}
3833 	return false;
3834 }
3835 
3836 /*------------------------------------------------------------------*/
3837 /* IDI callback function                                            */
3838 /*------------------------------------------------------------------*/
3839 
callback(ENTITY * e)3840 void callback(ENTITY *e)
3841 {
3842 	DIVA_CAPI_ADAPTER *a;
3843 	APPL *appl;
3844 	PLCI *plci;
3845 	CAPI_MSG *m;
3846 	word i, j;
3847 	byte rc;
3848 	byte ch;
3849 	byte req;
3850 	byte global_req;
3851 	int no_cancel_rc;
3852 
3853 	dbug(1, dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3854 			(e->user[0] + 1) & 0x7fff, e->Id, e->Req, e->Rc, e->Ind));
3855 
3856 	a = &(adapter[(byte)e->user[0]]);
3857 	plci = &(a->plci[e->user[1]]);
3858 	no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3859 
3860 	/*
3861 	  If new protocol code and new XDI is used then CAPI should work
3862 	  fully in accordance with IDI cpec an look on callback field instead
3863 	  of Rc field for return codes.
3864 	*/
3865 	if (((e->complete == 0xff) && no_cancel_rc) ||
3866 	    (e->Rc && !no_cancel_rc)) {
3867 		rc = e->Rc;
3868 		ch = e->RcCh;
3869 		req = e->Req;
3870 		e->Rc = 0;
3871 
3872 		if (e->user[0] & 0x8000)
3873 		{
3874 			/*
3875 			  If REMOVE request was sent then we have to wait until
3876 			  return code with Id set to zero arrives.
3877 			  All other return codes should be ignored.
3878 			*/
3879 			if (req == REMOVE)
3880 			{
3881 				if (e->Id)
3882 				{
3883 					dbug(1, dprintf("cancel RC in REMOVE state"));
3884 					return;
3885 				}
3886 				channel_flow_control_remove(plci);
3887 				for (i = 0; i < 256; i++)
3888 				{
3889 					if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3890 						a->FlowControlIdTable[i] = 0;
3891 				}
3892 				plci->nl_remove_id = 0;
3893 				if (plci->rx_dma_descriptor > 0) {
3894 					diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3895 					plci->rx_dma_descriptor = 0;
3896 				}
3897 			}
3898 			if (rc == OK_FC)
3899 			{
3900 				a->FlowControlIdTable[ch] = e->Id;
3901 				a->FlowControlSkipTable[ch] = 0;
3902 
3903 				a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3904 				a->ch_flow_plci[ch] = plci->Id;
3905 				plci->nl_req = 0;
3906 			}
3907 			else
3908 			{
3909 				/*
3910 				  Cancel return codes self, if feature was requested
3911 				*/
3912 				if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3913 					a->FlowControlIdTable[ch] = 0;
3914 					if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3915 						dbug(3, dprintf("XDI CAPI: RC cancelled Id:0x02, Ch:%02x", e->Id, ch));
3916 						return;
3917 					}
3918 				}
3919 
3920 				if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3921 				{
3922 					a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3923 					if (ch == e->ReqCh)
3924 						plci->nl_req = 0;
3925 				}
3926 				else
3927 					plci->nl_req = 0;
3928 			}
3929 			if (plci->nl_req)
3930 				control_rc(plci, 0, rc, ch, 0, true);
3931 			else
3932 			{
3933 				if (req == N_XON)
3934 				{
3935 					channel_x_on(plci, ch);
3936 					if (plci->internal_command)
3937 						control_rc(plci, req, rc, ch, 0, true);
3938 				}
3939 				else
3940 				{
3941 					if (plci->nl_global_req)
3942 					{
3943 						global_req = plci->nl_global_req;
3944 						plci->nl_global_req = 0;
3945 						if (rc != ASSIGN_OK) {
3946 							e->Id = 0;
3947 							if (plci->rx_dma_descriptor > 0) {
3948 								diva_free_dma_descriptor(plci, plci->rx_dma_descriptor - 1);
3949 								plci->rx_dma_descriptor = 0;
3950 							}
3951 						}
3952 						channel_xmit_xon(plci);
3953 						control_rc(plci, 0, rc, ch, global_req, true);
3954 					}
3955 					else if (plci->data_sent)
3956 					{
3957 						channel_xmit_xon(plci);
3958 						plci->data_sent = false;
3959 						plci->NL.XNum = 1;
3960 						data_rc(plci, ch);
3961 						if (plci->internal_command)
3962 							control_rc(plci, req, rc, ch, 0, true);
3963 					}
3964 					else
3965 					{
3966 						channel_xmit_xon(plci);
3967 						control_rc(plci, req, rc, ch, 0, true);
3968 					}
3969 				}
3970 			}
3971 		}
3972 		else
3973 		{
3974 			/*
3975 			  If REMOVE request was sent then we have to wait until
3976 			  return code with Id set to zero arrives.
3977 			  All other return codes should be ignored.
3978 			*/
3979 			if (req == REMOVE)
3980 			{
3981 				if (e->Id)
3982 				{
3983 					dbug(1, dprintf("cancel RC in REMOVE state"));
3984 					return;
3985 				}
3986 				plci->sig_remove_id = 0;
3987 			}
3988 			plci->sig_req = 0;
3989 			if (plci->sig_global_req)
3990 			{
3991 				global_req = plci->sig_global_req;
3992 				plci->sig_global_req = 0;
3993 				if (rc != ASSIGN_OK)
3994 					e->Id = 0;
3995 				channel_xmit_xon(plci);
3996 				control_rc(plci, 0, rc, ch, global_req, false);
3997 			}
3998 			else
3999 			{
4000 				channel_xmit_xon(plci);
4001 				control_rc(plci, req, rc, ch, 0, false);
4002 			}
4003 		}
4004 		/*
4005 		  Again: in accordance with IDI spec Rc and Ind can't be delivered in the
4006 		  same callback. Also if new XDI and protocol code used then jump
4007 		  direct to finish.
4008 		*/
4009 		if (no_cancel_rc) {
4010 			channel_xmit_xon(plci);
4011 			goto capi_callback_suffix;
4012 		}
4013 	}
4014 
4015 	channel_xmit_xon(plci);
4016 
4017 	if (e->Ind) {
4018 		if (e->user[0] & 0x8000) {
4019 			byte Ind = e->Ind & 0x0f;
4020 			byte Ch = e->IndCh;
4021 			if (((Ind == N_DISC) || (Ind == N_DISC_ACK)) &&
4022 			    (a->ch_flow_plci[Ch] == plci->Id)) {
4023 				if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4024 					dbug(3, dprintf("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4025 				}
4026 				a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4027 			}
4028 			nl_ind(plci);
4029 			if ((e->RNR != 1) &&
4030 			    (a->ch_flow_plci[Ch] == plci->Id) &&
4031 			    (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4032 				a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4033 				dbug(3, dprintf("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4034 			}
4035 		} else {
4036 			sig_ind(plci);
4037 		}
4038 		e->Ind = 0;
4039 	}
4040 
4041 capi_callback_suffix:
4042 
4043 	while (!plci->req_in
4044 	       && !plci->internal_command
4045 	       && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4046 	{
4047 		j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4048 
4049 		i = (((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4050 
4051 		m = (CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[j]);
4052 		appl = *((APPL **)(&((byte *)(plci->msg_in_queue))[j + i]));
4053 		dbug(1, dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4054 				m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4055 		if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4056 		{
4057 			plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4058 			plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4059 		}
4060 		else
4061 		{
4062 			plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4063 		}
4064 		if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4065 		{
4066 			plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4067 			plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4068 		}
4069 		else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4070 		{
4071 			plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4072 			plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4073 		}
4074 		i = api_put(appl, m);
4075 		if (i != 0)
4076 		{
4077 			if (m->header.command == _DATA_B3_R)
4078 
4079 				TransmitBufferFree(appl, (byte *)(long)(m->info.data_b3_req.Data));
4080 
4081 			dbug(1, dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4082 			break;
4083 		}
4084 
4085 		if (plci->li_notify_update)
4086 		{
4087 			plci->li_notify_update = false;
4088 			mixer_notify_update(plci, false);
4089 		}
4090 
4091 	}
4092 	send_data(plci);
4093 	send_req(plci);
4094 }
4095 
4096 
control_rc(PLCI * plci,byte req,byte rc,byte ch,byte global_req,byte nl_rc)4097 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4098 		       byte nl_rc)
4099 {
4100 	dword Id;
4101 	dword rId;
4102 	word Number;
4103 	word Info = 0;
4104 	word i;
4105 	word ncci;
4106 	DIVA_CAPI_ADAPTER *a;
4107 	APPL *appl;
4108 	PLCI *rplci;
4109 	byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
4110 	byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4111 
4112 	if (!plci) {
4113 		dbug(0, dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4114 		return;
4115 	}
4116 	dbug(1, dprintf("req0_in/out=%d/%d", plci->req_in, plci->req_out));
4117 	if (plci->req_in != plci->req_out)
4118 	{
4119 		if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4120 		{
4121 			dbug(1, dprintf("req_1return"));
4122 			return;
4123 		}
4124 		/* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4125 	}
4126 	plci->req_in = plci->req_in_start = plci->req_out = 0;
4127 	dbug(1, dprintf("control_rc"));
4128 
4129 	appl = plci->appl;
4130 	a = plci->adapter;
4131 	ncci = a->ch_ncci[ch];
4132 	if (appl)
4133 	{
4134 		Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4135 		if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4136 		Number = plci->number;
4137 		dbug(1, dprintf("Contr_RC-Id=%08lx,plci=%x,tel=%x, entity=0x%x, command=0x%x, int_command=0x%x", Id, plci->Id, plci->tel, plci->Sig.Id, plci->command, plci->internal_command));
4138 		dbug(1, dprintf("channels=0x%x", plci->channels));
4139 		if (plci_remove_check(plci))
4140 			return;
4141 		if (req == REMOVE && rc == ASSIGN_OK)
4142 		{
4143 			sig_req(plci, HANGUP, 0);
4144 			sig_req(plci, REMOVE, 0);
4145 			send_req(plci);
4146 		}
4147 		if (plci->command)
4148 		{
4149 			switch (plci->command)
4150 			{
4151 			case C_HOLD_REQ:
4152 				dbug(1, dprintf("HoldRC=0x%x", rc));
4153 				SSparms[1] = (byte)S_HOLD;
4154 				if (rc != OK)
4155 				{
4156 					plci->SuppState = IDLE;
4157 					Info = 0x2001;
4158 				}
4159 				sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4160 				break;
4161 
4162 			case C_RETRIEVE_REQ:
4163 				dbug(1, dprintf("RetrieveRC=0x%x", rc));
4164 				SSparms[1] = (byte)S_RETRIEVE;
4165 				if (rc != OK)
4166 				{
4167 					plci->SuppState = CALL_HELD;
4168 					Info = 0x2001;
4169 				}
4170 				sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", Info, 3, SSparms);
4171 				break;
4172 
4173 			case _INFO_R:
4174 				dbug(1, dprintf("InfoRC=0x%x", rc));
4175 				if (rc != OK) Info = _WRONG_STATE;
4176 				sendf(appl, _INFO_R | CONFIRM, Id, Number, "w", Info);
4177 				break;
4178 
4179 			case _CONNECT_R:
4180 				dbug(1, dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x", req, rc, global_req, nl_rc));
4181 				if (plci->State == INC_DIS_PENDING)
4182 					break;
4183 				if (plci->Sig.Id != 0xff)
4184 				{
4185 					if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4186 					    || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4187 					{
4188 						dbug(1, dprintf("No more IDs/Call_Req failed"));
4189 						sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4190 						plci_remove(plci);
4191 						plci->State = IDLE;
4192 						break;
4193 					}
4194 					if (plci->State != LOCAL_CONNECT) plci->State = OUTG_CON_PENDING;
4195 					sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4196 				}
4197 				else /* D-ch activation */
4198 				{
4199 					if (rc != ASSIGN_OK)
4200 					{
4201 						dbug(1, dprintf("No more IDs/X.25 Call_Req failed"));
4202 						sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4203 						plci_remove(plci);
4204 						plci->State = IDLE;
4205 						break;
4206 					}
4207 					sendf(appl, _CONNECT_R | CONFIRM, Id, Number, "w", 0);
4208 					sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "sss", "", "", "");
4209 					plci->State = INC_ACT_PENDING;
4210 				}
4211 				break;
4212 
4213 			case _CONNECT_I | RESPONSE:
4214 				if (plci->State != INC_DIS_PENDING)
4215 					plci->State = INC_CON_ACCEPT;
4216 				break;
4217 
4218 			case _DISCONNECT_R:
4219 				if (plci->State == INC_DIS_PENDING)
4220 					break;
4221 				if (plci->Sig.Id != 0xff)
4222 				{
4223 					plci->State = OUTG_DIS_PENDING;
4224 					sendf(appl, _DISCONNECT_R | CONFIRM, Id, Number, "w", 0);
4225 				}
4226 				break;
4227 
4228 			case SUSPEND_REQ:
4229 				break;
4230 
4231 			case RESUME_REQ:
4232 				break;
4233 
4234 			case _CONNECT_B3_R:
4235 				if (rc != OK)
4236 				{
4237 					sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
4238 					break;
4239 				}
4240 				ncci = get_ncci(plci, ch, 0);
4241 				Id = (Id & 0xffff) | (((dword) ncci) << 16);
4242 				plci->channels++;
4243 				if (req == N_RESET)
4244 				{
4245 					a->ncci_state[ncci] = INC_ACT_PENDING;
4246 					sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4247 					sendf(appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
4248 				}
4249 				else
4250 				{
4251 					a->ncci_state[ncci] = OUTG_CON_PENDING;
4252 					sendf(appl, _CONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4253 				}
4254 				break;
4255 
4256 			case _CONNECT_B3_I | RESPONSE:
4257 				break;
4258 
4259 			case _RESET_B3_R:
4260 /*        sendf(appl, _RESET_B3_R | CONFIRM, Id, Number, "w", 0);*/
4261 				break;
4262 
4263 			case _DISCONNECT_B3_R:
4264 				sendf(appl, _DISCONNECT_B3_R | CONFIRM, Id, Number, "w", 0);
4265 				break;
4266 
4267 			case _MANUFACTURER_R:
4268 				break;
4269 
4270 			case PERM_LIST_REQ:
4271 				if (rc != OK)
4272 				{
4273 					Info = _WRONG_IDENTIFIER;
4274 					sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4275 					plci_remove(plci);
4276 				}
4277 				else
4278 					sendf(plci->appl, _CONNECT_R | CONFIRM, Id, Number, "w", Info);
4279 				break;
4280 
4281 			default:
4282 				break;
4283 			}
4284 			plci->command = 0;
4285 		}
4286 		else if (plci->internal_command)
4287 		{
4288 			switch (plci->internal_command)
4289 			{
4290 			case BLOCK_PLCI:
4291 				return;
4292 
4293 			case GET_MWI_STATE:
4294 				if (rc == OK) /* command supported, wait for indication */
4295 				{
4296 					return;
4297 				}
4298 				plci_remove(plci);
4299 				break;
4300 
4301 				/* Get Supported Services */
4302 			case GETSERV_REQ_PEND:
4303 				if (rc == OK) /* command supported, wait for indication */
4304 				{
4305 					break;
4306 				}
4307 				PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4308 				sendf(appl, _FACILITY_R | CONFIRM, Id, Number, "wws", 0, 3, SSstruct);
4309 				plci_remove(plci);
4310 				break;
4311 
4312 			case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
4313 			case INTERR_NUMBERS_REQ_PEND:
4314 			case CF_START_PEND:                  /* Call Forwarding Start pending */
4315 			case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
4316 			case CCBS_REQUEST_REQ_PEND:
4317 			case CCBS_DEACTIVATE_REQ_PEND:
4318 			case CCBS_INTERROGATE_REQ_PEND:
4319 				switch (plci->internal_command)
4320 				{
4321 				case INTERR_DIVERSION_REQ_PEND:
4322 					SSparms[1] = S_INTERROGATE_DIVERSION;
4323 					break;
4324 				case INTERR_NUMBERS_REQ_PEND:
4325 					SSparms[1] = S_INTERROGATE_NUMBERS;
4326 					break;
4327 				case CF_START_PEND:
4328 					SSparms[1] = S_CALL_FORWARDING_START;
4329 					break;
4330 				case CF_STOP_PEND:
4331 					SSparms[1] = S_CALL_FORWARDING_STOP;
4332 					break;
4333 				case CCBS_REQUEST_REQ_PEND:
4334 					SSparms[1] = S_CCBS_REQUEST;
4335 					break;
4336 				case CCBS_DEACTIVATE_REQ_PEND:
4337 					SSparms[1] = S_CCBS_DEACTIVATE;
4338 					break;
4339 				case CCBS_INTERROGATE_REQ_PEND:
4340 					SSparms[1] = S_CCBS_INTERROGATE;
4341 					break;
4342 				}
4343 				if (global_req == ASSIGN)
4344 				{
4345 					dbug(1, dprintf("AssignDiversion_RC=0x%x/0x%x", req, rc));
4346 					return;
4347 				}
4348 				if (!plci->appl) break;
4349 				if (rc == ISDN_GUARD_REJ)
4350 				{
4351 					Info = _CAPI_GUARD_ERROR;
4352 				}
4353 				else if (rc != OK)
4354 				{
4355 					Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4356 				}
4357 				sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7,
4358 				      plci->number, "wws", Info, (word)3, SSparms);
4359 				if (Info) plci_remove(plci);
4360 				break;
4361 
4362 				/* 3pty conference pending */
4363 			case PTY_REQ_PEND:
4364 				if (!plci->relatedPTYPLCI) break;
4365 				rplci = plci->relatedPTYPLCI;
4366 				SSparms[1] = plci->ptyState;
4367 				rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4368 				if (rplci->tel) rId |= EXT_CONTROLLER;
4369 				if (rc != OK)
4370 				{
4371 					Info = 0x300E; /* not supported */
4372 					plci->relatedPTYPLCI = NULL;
4373 					plci->ptyState = 0;
4374 				}
4375 				sendf(rplci->appl,
4376 				      _FACILITY_R | CONFIRM,
4377 				      rId,
4378 				      plci->number,
4379 				      "wws", Info, (word)3, SSparms);
4380 				break;
4381 
4382 				/* Explicit Call Transfer pending */
4383 			case ECT_REQ_PEND:
4384 				dbug(1, dprintf("ECT_RC=0x%x/0x%x", req, rc));
4385 				if (!plci->relatedPTYPLCI) break;
4386 				rplci = plci->relatedPTYPLCI;
4387 				SSparms[1] = S_ECT;
4388 				rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4389 				if (rplci->tel) rId |= EXT_CONTROLLER;
4390 				if (rc != OK)
4391 				{
4392 					Info = 0x300E; /* not supported */
4393 					plci->relatedPTYPLCI = NULL;
4394 					plci->ptyState = 0;
4395 				}
4396 				sendf(rplci->appl,
4397 				      _FACILITY_R | CONFIRM,
4398 				      rId,
4399 				      plci->number,
4400 				      "wws", Info, (word)3, SSparms);
4401 				break;
4402 
4403 			case _MANUFACTURER_R:
4404 				dbug(1, dprintf("_Manufacturer_R=0x%x/0x%x", req, rc));
4405 				if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4406 				{
4407 					dbug(1, dprintf("No more IDs"));
4408 					sendf(appl, _MANUFACTURER_R | CONFIRM, Id, Number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
4409 					plci_remove(plci);  /* after codec init, internal codec commands pending */
4410 				}
4411 				break;
4412 
4413 			case _CONNECT_R:
4414 				dbug(1, dprintf("_Connect_R=0x%x/0x%x", req, rc));
4415 				if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4416 				{
4417 					dbug(1, dprintf("No more IDs"));
4418 					sendf(appl, _CONNECT_R | CONFIRM, Id & 0xffL, Number, "w", _OUT_OF_PLCI);
4419 					plci_remove(plci);  /* after codec init, internal codec commands pending */
4420 				}
4421 				break;
4422 
4423 			case PERM_COD_HOOK:                     /* finished with Hook_Ind */
4424 				return;
4425 
4426 			case PERM_COD_CALL:
4427 				dbug(1, dprintf("***Codec Connect_Pending A, Rc = 0x%x", rc));
4428 				plci->internal_command = PERM_COD_CONN_PEND;
4429 				return;
4430 
4431 			case PERM_COD_ASSIGN:
4432 				dbug(1, dprintf("***Codec Assign A, Rc = 0x%x", rc));
4433 				if (rc != ASSIGN_OK) break;
4434 				sig_req(plci, CALL_REQ, 0);
4435 				send_req(plci);
4436 				plci->internal_command = PERM_COD_CALL;
4437 				return;
4438 
4439 				/* Null Call Reference Request pending */
4440 			case C_NCR_FAC_REQ:
4441 				dbug(1, dprintf("NCR_FAC=0x%x/0x%x", req, rc));
4442 				if (global_req == ASSIGN)
4443 				{
4444 					if (rc == ASSIGN_OK)
4445 					{
4446 						return;
4447 					}
4448 					else
4449 					{
4450 						sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4451 						appl->NullCREnable = false;
4452 						plci_remove(plci);
4453 					}
4454 				}
4455 				else if (req == NCR_FACILITY)
4456 				{
4457 					if (rc == OK)
4458 					{
4459 						sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", 0);
4460 					}
4461 					else
4462 					{
4463 						sendf(appl, _INFO_R | CONFIRM, Id & 0xf, Number, "w", _WRONG_STATE);
4464 						appl->NullCREnable = false;
4465 					}
4466 					plci_remove(plci);
4467 				}
4468 				break;
4469 
4470 			case HOOK_ON_REQ:
4471 				if (plci->channels)
4472 				{
4473 					if (a->ncci_state[ncci] == CONNECTED)
4474 					{
4475 						a->ncci_state[ncci] = OUTG_DIS_PENDING;
4476 						cleanup_ncci_data(plci, ncci);
4477 						nl_req_ncci(plci, N_DISC, (byte)ncci);
4478 					}
4479 					break;
4480 				}
4481 				break;
4482 
4483 			case HOOK_OFF_REQ:
4484 				if (plci->State == INC_DIS_PENDING)
4485 					break;
4486 				sig_req(plci, CALL_REQ, 0);
4487 				send_req(plci);
4488 				plci->State = OUTG_CON_PENDING;
4489 				break;
4490 
4491 
4492 			case MWI_ACTIVATE_REQ_PEND:
4493 			case MWI_DEACTIVATE_REQ_PEND:
4494 				if (global_req == ASSIGN && rc == ASSIGN_OK)
4495 				{
4496 					dbug(1, dprintf("MWI_REQ assigned"));
4497 					return;
4498 				}
4499 				else if (rc != OK)
4500 				{
4501 					if (rc == WRONG_IE)
4502 					{
4503 						Info = 0x2007; /* Illegal message parameter coding */
4504 						dbug(1, dprintf("MWI_REQ invalid parameter"));
4505 					}
4506 					else
4507 					{
4508 						Info = 0x300B; /* not supported */
4509 						dbug(1, dprintf("MWI_REQ not supported"));
4510 					}
4511 					/* 0x3010: Request not allowed in this state */
4512 					PUT_WORD(&SSparms[4], 0x300E); /* SS not supported */
4513 
4514 				}
4515 				if (plci->internal_command == MWI_ACTIVATE_REQ_PEND)
4516 				{
4517 					PUT_WORD(&SSparms[1], S_MWI_ACTIVATE);
4518 				}
4519 				else PUT_WORD(&SSparms[1], S_MWI_DEACTIVATE);
4520 
4521 				if (plci->cr_enquiry)
4522 				{
4523 					sendf(plci->appl,
4524 					      _FACILITY_R | CONFIRM,
4525 					      Id & 0xf,
4526 					      plci->number,
4527 					      "wws", Info, (word)3, SSparms);
4528 					if (rc != OK) plci_remove(plci);
4529 				}
4530 				else
4531 				{
4532 					sendf(plci->appl,
4533 					      _FACILITY_R | CONFIRM,
4534 					      Id,
4535 					      plci->number,
4536 					      "wws", Info, (word)3, SSparms);
4537 				}
4538 				break;
4539 
4540 			case CONF_BEGIN_REQ_PEND:
4541 			case CONF_ADD_REQ_PEND:
4542 			case CONF_SPLIT_REQ_PEND:
4543 			case CONF_DROP_REQ_PEND:
4544 			case CONF_ISOLATE_REQ_PEND:
4545 			case CONF_REATTACH_REQ_PEND:
4546 				dbug(1, dprintf("CONF_RC=0x%x/0x%x", req, rc));
4547 				if ((plci->internal_command == CONF_ADD_REQ_PEND) && (!plci->relatedPTYPLCI)) break;
4548 				rplci = plci;
4549 				rId = Id;
4550 				switch (plci->internal_command)
4551 				{
4552 				case CONF_BEGIN_REQ_PEND:
4553 					SSparms[1] = S_CONF_BEGIN;
4554 					break;
4555 				case CONF_ADD_REQ_PEND:
4556 					SSparms[1] = S_CONF_ADD;
4557 					rplci = plci->relatedPTYPLCI;
4558 					rId = ((word)rplci->Id << 8) | rplci->adapter->Id;
4559 					break;
4560 				case CONF_SPLIT_REQ_PEND:
4561 					SSparms[1] = S_CONF_SPLIT;
4562 					break;
4563 				case CONF_DROP_REQ_PEND:
4564 					SSparms[1] = S_CONF_DROP;
4565 					break;
4566 				case CONF_ISOLATE_REQ_PEND:
4567 					SSparms[1] = S_CONF_ISOLATE;
4568 					break;
4569 				case CONF_REATTACH_REQ_PEND:
4570 					SSparms[1] = S_CONF_REATTACH;
4571 					break;
4572 				}
4573 
4574 				if (rc != OK)
4575 				{
4576 					Info = 0x300E; /* not supported */
4577 					plci->relatedPTYPLCI = NULL;
4578 					plci->ptyState = 0;
4579 				}
4580 				sendf(rplci->appl,
4581 				      _FACILITY_R | CONFIRM,
4582 				      rId,
4583 				      plci->number,
4584 				      "wws", Info, (word)3, SSparms);
4585 				break;
4586 
4587 			case VSWITCH_REQ_PEND:
4588 				if (rc != OK)
4589 				{
4590 					if (plci->relatedPTYPLCI)
4591 					{
4592 						plci->relatedPTYPLCI->vswitchstate = 0;
4593 						plci->relatedPTYPLCI->vsprot = 0;
4594 						plci->relatedPTYPLCI->vsprotdialect = 0;
4595 					}
4596 					plci->vswitchstate = 0;
4597 					plci->vsprot = 0;
4598 					plci->vsprotdialect = 0;
4599 				}
4600 				else
4601 				{
4602 					if (plci->relatedPTYPLCI &&
4603 					    plci->vswitchstate == 1 &&
4604 					    plci->relatedPTYPLCI->vswitchstate == 3) /* join complete */
4605 						plci->vswitchstate = 3;
4606 				}
4607 				break;
4608 
4609 				/* Call Deflection Request pending (SSCT) */
4610 			case CD_REQ_PEND:
4611 				SSparms[1] = S_CALL_DEFLECTION;
4612 				if (rc != OK)
4613 				{
4614 					Info = 0x300E; /* not supported */
4615 					plci->appl->CDEnable = 0;
4616 				}
4617 				sendf(plci->appl, _FACILITY_R | CONFIRM, Id,
4618 				      plci->number, "wws", Info, (word)3, SSparms);
4619 				break;
4620 
4621 			case RTP_CONNECT_B3_REQ_COMMAND_2:
4622 				if (rc == OK)
4623 				{
4624 					ncci = get_ncci(plci, ch, 0);
4625 					Id = (Id & 0xffff) | (((dword) ncci) << 16);
4626 					plci->channels++;
4627 					a->ncci_state[ncci] = OUTG_CON_PENDING;
4628 				}
4629 
4630 			default:
4631 				if (plci->internal_command_queue[0])
4632 				{
4633 					(*(plci->internal_command_queue[0]))(Id, plci, rc);
4634 					if (plci->internal_command)
4635 						return;
4636 				}
4637 				break;
4638 			}
4639 			next_internal_command(Id, plci);
4640 		}
4641 	}
4642 	else /* appl==0 */
4643 	{
4644 		Id = ((word)plci->Id << 8) | plci->adapter->Id;
4645 		if (plci->tel) Id |= EXT_CONTROLLER;
4646 
4647 		switch (plci->internal_command)
4648 		{
4649 		case BLOCK_PLCI:
4650 			return;
4651 
4652 		case START_L1_SIG_ASSIGN_PEND:
4653 		case REM_L1_SIG_ASSIGN_PEND:
4654 			if (global_req == ASSIGN)
4655 			{
4656 				break;
4657 			}
4658 			else
4659 			{
4660 				dbug(1, dprintf("***L1 Req rem PLCI"));
4661 				plci->internal_command = 0;
4662 				sig_req(plci, REMOVE, 0);
4663 				send_req(plci);
4664 			}
4665 			break;
4666 
4667 			/* Call Deflection Request pending, just no appl ptr assigned */
4668 		case CD_REQ_PEND:
4669 			SSparms[1] = S_CALL_DEFLECTION;
4670 			if (rc != OK)
4671 			{
4672 				Info = 0x300E; /* not supported */
4673 			}
4674 			for (i = 0; i < max_appl; i++)
4675 			{
4676 				if (application[i].CDEnable)
4677 				{
4678 					if (!application[i].Id) application[i].CDEnable = 0;
4679 					else
4680 					{
4681 						sendf(&application[i], _FACILITY_R | CONFIRM, Id,
4682 						      plci->number, "wws", Info, (word)3, SSparms);
4683 						if (Info) application[i].CDEnable = 0;
4684 					}
4685 				}
4686 			}
4687 			plci->internal_command = 0;
4688 			break;
4689 
4690 		case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4691 			return;
4692 
4693 		case PERM_COD_CALL:
4694 			plci->internal_command = PERM_COD_CONN_PEND;
4695 			dbug(1, dprintf("***Codec Connect_Pending, Rc = 0x%x", rc));
4696 			return;
4697 
4698 		case PERM_COD_ASSIGN:
4699 			dbug(1, dprintf("***Codec Assign, Rc = 0x%x", rc));
4700 			plci->internal_command = 0;
4701 			if (rc != ASSIGN_OK) break;
4702 			plci->internal_command = PERM_COD_CALL;
4703 			sig_req(plci, CALL_REQ, 0);
4704 			send_req(plci);
4705 			return;
4706 
4707 		case LISTEN_SIG_ASSIGN_PEND:
4708 			if (rc == ASSIGN_OK)
4709 			{
4710 				plci->internal_command = 0;
4711 				dbug(1, dprintf("ListenCheck, new SIG_ID = 0x%x", plci->Sig.Id));
4712 				add_p(plci, ESC, "\x02\x18\x00");             /* support call waiting */
4713 				sig_req(plci, INDICATE_REQ, 0);
4714 				send_req(plci);
4715 			}
4716 			else
4717 			{
4718 				dbug(1, dprintf("ListenCheck failed (assignRc=0x%x)", rc));
4719 				a->listen_active--;
4720 				plci_remove(plci);
4721 				plci->State = IDLE;
4722 			}
4723 			break;
4724 
4725 		case USELAW_REQ:
4726 			if (global_req == ASSIGN)
4727 			{
4728 				if (rc == ASSIGN_OK)
4729 				{
4730 					sig_req(plci, LAW_REQ, 0);
4731 					send_req(plci);
4732 					dbug(1, dprintf("Auto-Law assigned"));
4733 				}
4734 				else
4735 				{
4736 					dbug(1, dprintf("Auto-Law assign failed"));
4737 					a->automatic_law = 3;
4738 					plci->internal_command = 0;
4739 					a->automatic_lawPLCI = NULL;
4740 				}
4741 				break;
4742 			}
4743 			else if (req == LAW_REQ && rc == OK)
4744 			{
4745 				dbug(1, dprintf("Auto-Law initiated"));
4746 				a->automatic_law = 2;
4747 				plci->internal_command = 0;
4748 			}
4749 			else
4750 			{
4751 				dbug(1, dprintf("Auto-Law not supported"));
4752 				a->automatic_law = 3;
4753 				plci->internal_command = 0;
4754 				sig_req(plci, REMOVE, 0);
4755 				send_req(plci);
4756 				a->automatic_lawPLCI = NULL;
4757 			}
4758 			break;
4759 		}
4760 		plci_remove_check(plci);
4761 	}
4762 }
4763 
data_rc(PLCI * plci,byte ch)4764 static void data_rc(PLCI *plci, byte ch)
4765 {
4766 	dword Id;
4767 	DIVA_CAPI_ADAPTER *a;
4768 	NCCI *ncci_ptr;
4769 	DATA_B3_DESC *data;
4770 	word ncci;
4771 
4772 	if (plci->appl)
4773 	{
4774 		TransmitBufferFree(plci->appl, plci->data_sent_ptr);
4775 		a = plci->adapter;
4776 		ncci = a->ch_ncci[ch];
4777 		if (ncci && (a->ncci_plci[ncci] == plci->Id))
4778 		{
4779 			ncci_ptr = &(a->ncci[ncci]);
4780 			dbug(1, dprintf("data_out=%d, data_pending=%d", ncci_ptr->data_out, ncci_ptr->data_pending));
4781 			if (ncci_ptr->data_pending)
4782 			{
4783 				data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4784 				if (!(data->Flags & 4) && a->ncci_state[ncci])
4785 				{
4786 					Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4787 					if (plci->tel) Id |= EXT_CONTROLLER;
4788 					sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, data->Number,
4789 					      "ww", data->Handle, 0);
4790 				}
4791 				(ncci_ptr->data_out)++;
4792 				if (ncci_ptr->data_out == MAX_DATA_B3)
4793 					ncci_ptr->data_out = 0;
4794 				(ncci_ptr->data_pending)--;
4795 			}
4796 		}
4797 	}
4798 }
4799 
data_ack(PLCI * plci,byte ch)4800 static void data_ack(PLCI *plci, byte ch)
4801 {
4802 	dword Id;
4803 	DIVA_CAPI_ADAPTER *a;
4804 	NCCI *ncci_ptr;
4805 	word ncci;
4806 
4807 	a = plci->adapter;
4808 	ncci = a->ch_ncci[ch];
4809 	ncci_ptr = &(a->ncci[ncci]);
4810 	if (ncci_ptr->data_ack_pending)
4811 	{
4812 		if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4813 		{
4814 			Id = (((dword)ncci) << 16) | ((word)plci->Id << 8) | a->Id;
4815 			if (plci->tel) Id |= EXT_CONTROLLER;
4816 			sendf(plci->appl, _DATA_B3_R | CONFIRM, Id, ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4817 			      "ww", ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle, 0);
4818 		}
4819 		(ncci_ptr->data_ack_out)++;
4820 		if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4821 			ncci_ptr->data_ack_out = 0;
4822 		(ncci_ptr->data_ack_pending)--;
4823 	}
4824 }
4825 
sig_ind(PLCI * plci)4826 static void sig_ind(PLCI *plci)
4827 {
4828 	dword x_Id;
4829 	dword Id;
4830 	dword rId;
4831 	word i;
4832 	word cip;
4833 	dword cip_mask;
4834 	byte *ie;
4835 	DIVA_CAPI_ADAPTER *a;
4836 	API_PARSE saved_parms[MAX_MSG_PARMS + 1];
4837 #define MAXPARMSIDS 31
4838 	byte *parms[MAXPARMSIDS];
4839 	byte *add_i[4];
4840 	byte *multi_fac_parms[MAX_MULTI_IE];
4841 	byte *multi_pi_parms[MAX_MULTI_IE];
4842 	byte *multi_ssext_parms[MAX_MULTI_IE];
4843 	byte *multi_CiPN_parms[MAX_MULTI_IE];
4844 
4845 	byte *multi_vswitch_parms[MAX_MULTI_IE];
4846 
4847 	byte ai_len;
4848 	byte *esc_chi = "";
4849 	byte *esc_law = "";
4850 	byte *pty_cai = "";
4851 	byte *esc_cr  = "";
4852 	byte *esc_profile = "";
4853 
4854 	byte facility[256];
4855 	PLCI *tplci = NULL;
4856 	byte chi[] = "\x02\x18\x01";
4857 	byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4858 	byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4859 	/* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4860 	/* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4861 	/* SMSG is situated at the end because its 0 (for compatibility reasons */
4862 	/* (see Info_Mask Bit 4, first IE. then the message type)           */
4863 	word parms_id[] =
4864 		{MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4865 		 UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4866 		 RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4867 		 CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4868 	/* 14 FTY repl by ESC_CHI */
4869 	/* 18 PI  repl by ESC_LAW */
4870 	/* removed OAD changed to 0xff for future use, OAD is multiIE now */
4871 	word multi_fac_id[] = {1, FTY};
4872 	word multi_pi_id[]  = {1, PI};
4873 	word multi_CiPN_id[]  = {1, OAD};
4874 	word multi_ssext_id[]  = {1, ESC_SSEXT};
4875 
4876 	word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4877 
4878 	byte *cau;
4879 	word ncci;
4880 	byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4881 	byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4882 	byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4883 	byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
4884 	byte force_mt_info = false;
4885 	byte dir;
4886 	dword d;
4887 	word w;
4888 
4889 	a = plci->adapter;
4890 	Id = ((word)plci->Id << 8) | a->Id;
4891 	PUT_WORD(&SS_Ind[4], 0x0000);
4892 
4893 	if (plci->sig_remove_id)
4894 	{
4895 		plci->Sig.RNR = 2; /* discard */
4896 		dbug(1, dprintf("SIG discard while remove pending"));
4897 		return;
4898 	}
4899 	if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4900 	dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4901 			Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4902 	if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4903 	{
4904 		plci->Sig.RNR = 1;
4905 		return;
4906 	}
4907 	if (plci->Sig.Ind == HANGUP && plci->channels)
4908 	{
4909 		plci->Sig.RNR = 1;
4910 		plci->hangup_flow_ctrl_timer++;
4911 		/* recover the network layer after timeout */
4912 		if (plci->hangup_flow_ctrl_timer == 100)
4913 		{
4914 			dbug(1, dprintf("Exceptional disc"));
4915 			plci->Sig.RNR = 0;
4916 			plci->hangup_flow_ctrl_timer = 0;
4917 			for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4918 			{
4919 				if (a->ncci_plci[ncci] == plci->Id)
4920 				{
4921 					cleanup_ncci_data(plci, ncci);
4922 					if (plci->channels)plci->channels--;
4923 					if (plci->appl)
4924 						sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4925 				}
4926 			}
4927 			if (plci->appl)
4928 				sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4929 			plci_remove(plci);
4930 			plci->State = IDLE;
4931 		}
4932 		return;
4933 	}
4934 
4935 	/* do first parse the info with no OAD in, because OAD will be converted */
4936 	/* first the multiple facility IE, then mult. progress ind.              */
4937 	/* then the parameters for the info_ind + conn_ind                       */
4938 	IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4939 	IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4940 	IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4941 
4942 	IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4943 
4944 	IndParse(plci, parms_id, parms, 0);
4945 	IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4946 	esc_chi  = parms[14];
4947 	esc_law  = parms[18];
4948 	pty_cai  = parms[24];
4949 	esc_cr   = parms[25];
4950 	esc_profile = parms[27];
4951 	if (esc_cr[0] && plci)
4952 	{
4953 		if (plci->cr_enquiry && plci->appl)
4954 		{
4955 			plci->cr_enquiry = false;
4956 			/* d = MANU_ID            */
4957 			/* w = m_command          */
4958 			/* b = total length       */
4959 			/* b = indication type    */
4960 			/* b = length of all IEs  */
4961 			/* b = IE1                */
4962 			/* S = IE1 length + cont. */
4963 			/* b = IE2                */
4964 			/* S = IE2 length + cont. */
4965 			sendf(plci->appl,
4966 			      _MANUFACTURER_I,
4967 			      Id,
4968 			      0,
4969 			      "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4970 			      2 + 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], plci->Sig.Ind, 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], ESC, esc_cr, ESC, esc_law);
4971 		}
4972 	}
4973 	/* create the additional info structure                                  */
4974 	add_i[1] = parms[15]; /* KEY of additional info */
4975 	add_i[2] = parms[11]; /* UUI of additional info */
4976 	ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4977 
4978 	/* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4979 	/* indication returns by the card if requested by the function           */
4980 	/* AutomaticLaw() after driver init                                      */
4981 	if (a->automatic_law < 4)
4982 	{
4983 		if (esc_law[0]) {
4984 			if (esc_law[2]) {
4985 				dbug(0, dprintf("u-Law selected"));
4986 				a->u_law = 1;
4987 			}
4988 			else {
4989 				dbug(0, dprintf("a-Law selected"));
4990 				a->u_law = 0;
4991 			}
4992 			a->automatic_law = 4;
4993 			if (plci == a->automatic_lawPLCI) {
4994 				plci->internal_command = 0;
4995 				sig_req(plci, REMOVE, 0);
4996 				send_req(plci);
4997 				a->automatic_lawPLCI = NULL;
4998 			}
4999 		}
5000 		if (esc_profile[0])
5001 		{
5002 			dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
5003 					UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
5004 					GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
5005 					GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
5006 
5007 			a->profile.Global_Options &= 0x000000ffL;
5008 			a->profile.B1_Protocols &= 0x000003ffL;
5009 			a->profile.B2_Protocols &= 0x00001fdfL;
5010 			a->profile.B3_Protocols &= 0x000000b7L;
5011 
5012 			a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
5013 				GL_BCHANNEL_OPERATION_SUPPORTED;
5014 			a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
5015 			a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
5016 			a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
5017 			a->manufacturer_features = GET_DWORD(&esc_profile[46]);
5018 			a->man_profile.private_options = 0;
5019 
5020 			if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5021 			{
5022 				a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5023 				a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5024 			}
5025 
5026 
5027 			if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5028 				a->man_profile.private_options |= 1L << PRIVATE_RTP;
5029 			a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
5030 			a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
5031 
5032 
5033 			if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5034 				a->man_profile.private_options |= 1L << PRIVATE_T38;
5035 
5036 
5037 			if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5038 				a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5039 
5040 
5041 			if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5042 				a->man_profile.private_options |= 1L << PRIVATE_V18;
5043 
5044 
5045 			if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5046 				a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5047 
5048 
5049 			if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5050 				a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5051 
5052 
5053 			if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5054 				a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5055 
5056 
5057 			if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5058 				a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5059 
5060 
5061 			if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5062 				a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5063 
5064 		}
5065 		else
5066 		{
5067 			a->profile.Global_Options &= 0x0000007fL;
5068 			a->profile.B1_Protocols &= 0x000003dfL;
5069 			a->profile.B2_Protocols &= 0x00001adfL;
5070 			a->profile.B3_Protocols &= 0x000000b7L;
5071 			a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5072 		}
5073 		if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5074 						MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5075 		{
5076 			a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5077 		}
5078 		a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5079 		dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
5080 				UnMapController(a->Id), a->profile.Global_Options,
5081 				a->profile.B1_Protocols, a->profile.B2_Protocols,
5082 				a->profile.B3_Protocols, a->manufacturer_features));
5083 	}
5084 	/* codec plci for the handset/hook state support is just an internal id  */
5085 	if (plci != a->AdvCodecPLCI)
5086 	{
5087 		force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
5088 		force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
5089 		SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5090 		SendInfo(plci, Id, parms, force_mt_info);
5091 
5092 		VSwitchReqInd(plci, Id, multi_vswitch_parms);
5093 
5094 	}
5095 
5096 	/* switch the codec to the b-channel                                     */
5097 	if (esc_chi[0] && plci && !plci->SuppState) {
5098 		plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5099 		mixer_set_bchannel_id_esc(plci, plci->b_channel);
5100 		dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
5101 		if (plci->tel == ADV_VOICE && plci->appl) {
5102 			SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5103 		}
5104 	}
5105 
5106 	if (plci->appl) plci->appl->Number++;
5107 
5108 	switch (plci->Sig.Ind) {
5109 		/* Response to Get_Supported_Services request */
5110 	case S_SUPPORTED:
5111 		dbug(1, dprintf("S_Supported"));
5112 		if (!plci->appl) break;
5113 		if (pty_cai[0] == 4)
5114 		{
5115 			PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
5116 		}
5117 		else
5118 		{
5119 			PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5120 		}
5121 		PUT_WORD(&CF_Ind[1], 0);
5122 		PUT_WORD(&CF_Ind[4], 0);
5123 		sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
5124 		plci_remove(plci);
5125 		break;
5126 
5127 		/* Supplementary Service rejected */
5128 	case S_SERVICE_REJ:
5129 		dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5130 		if (!pty_cai[0]) break;
5131 		switch (pty_cai[5])
5132 		{
5133 		case ECT_EXECUTE:
5134 		case THREE_PTY_END:
5135 		case THREE_PTY_BEGIN:
5136 			if (!plci->relatedPTYPLCI) break;
5137 			tplci = plci->relatedPTYPLCI;
5138 			rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5139 			if (tplci->tel) rId |= EXT_CONTROLLER;
5140 			if (pty_cai[5] == ECT_EXECUTE)
5141 			{
5142 				PUT_WORD(&SS_Ind[1], S_ECT);
5143 
5144 				plci->vswitchstate = 0;
5145 				plci->relatedPTYPLCI->vswitchstate = 0;
5146 
5147 			}
5148 			else
5149 			{
5150 				PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5151 			}
5152 			if (pty_cai[2] != 0xff)
5153 			{
5154 				PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5155 			}
5156 			else
5157 			{
5158 				PUT_WORD(&SS_Ind[4], 0x300E);
5159 			}
5160 			plci->relatedPTYPLCI = NULL;
5161 			plci->ptyState = 0;
5162 			sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5163 			break;
5164 
5165 		case CALL_DEFLECTION:
5166 			if (pty_cai[2] != 0xff)
5167 			{
5168 				PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5169 			}
5170 			else
5171 			{
5172 				PUT_WORD(&SS_Ind[4], 0x300E);
5173 			}
5174 			PUT_WORD(&SS_Ind[1], pty_cai[5]);
5175 			for (i = 0; i < max_appl; i++)
5176 			{
5177 				if (application[i].CDEnable)
5178 				{
5179 					if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5180 					application[i].CDEnable = false;
5181 				}
5182 			}
5183 			break;
5184 
5185 		case DEACTIVATION_DIVERSION:
5186 		case ACTIVATION_DIVERSION:
5187 		case DIVERSION_INTERROGATE_CFU:
5188 		case DIVERSION_INTERROGATE_CFB:
5189 		case DIVERSION_INTERROGATE_CFNR:
5190 		case DIVERSION_INTERROGATE_NUM:
5191 		case CCBS_REQUEST:
5192 		case CCBS_DEACTIVATE:
5193 		case CCBS_INTERROGATE:
5194 			if (!plci->appl) break;
5195 			if (pty_cai[2] != 0xff)
5196 			{
5197 				PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5198 			}
5199 			else
5200 			{
5201 				PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5202 			}
5203 			switch (pty_cai[5])
5204 			{
5205 			case DEACTIVATION_DIVERSION:
5206 				dbug(1, dprintf("Deact_Div"));
5207 				Interr_Err_Ind[0] = 0x9;
5208 				Interr_Err_Ind[3] = 0x6;
5209 				PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5210 				break;
5211 			case ACTIVATION_DIVERSION:
5212 				dbug(1, dprintf("Act_Div"));
5213 				Interr_Err_Ind[0] = 0x9;
5214 				Interr_Err_Ind[3] = 0x6;
5215 				PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5216 				break;
5217 			case DIVERSION_INTERROGATE_CFU:
5218 			case DIVERSION_INTERROGATE_CFB:
5219 			case DIVERSION_INTERROGATE_CFNR:
5220 				dbug(1, dprintf("Interr_Div"));
5221 				Interr_Err_Ind[0] = 0xa;
5222 				Interr_Err_Ind[3] = 0x7;
5223 				PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5224 				break;
5225 			case DIVERSION_INTERROGATE_NUM:
5226 				dbug(1, dprintf("Interr_Num"));
5227 				Interr_Err_Ind[0] = 0xa;
5228 				Interr_Err_Ind[3] = 0x7;
5229 				PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5230 				break;
5231 			case CCBS_REQUEST:
5232 				dbug(1, dprintf("CCBS Request"));
5233 				Interr_Err_Ind[0] = 0xd;
5234 				Interr_Err_Ind[3] = 0xa;
5235 				PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5236 				break;
5237 			case CCBS_DEACTIVATE:
5238 				dbug(1, dprintf("CCBS Deactivate"));
5239 				Interr_Err_Ind[0] = 0x9;
5240 				Interr_Err_Ind[3] = 0x6;
5241 				PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5242 				break;
5243 			case CCBS_INTERROGATE:
5244 				dbug(1, dprintf("CCBS Interrogate"));
5245 				Interr_Err_Ind[0] = 0xb;
5246 				Interr_Err_Ind[3] = 0x8;
5247 				PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5248 				break;
5249 			}
5250 			PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5251 			sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5252 			plci_remove(plci);
5253 			break;
5254 		case ACTIVATION_MWI:
5255 		case DEACTIVATION_MWI:
5256 			if (pty_cai[5] == ACTIVATION_MWI)
5257 			{
5258 				PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5259 			}
5260 			else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5261 
5262 			if (pty_cai[2] != 0xff)
5263 			{
5264 				PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5265 			}
5266 			else
5267 			{
5268 				PUT_WORD(&SS_Ind[4], 0x300E);
5269 			}
5270 
5271 			if (plci->cr_enquiry)
5272 			{
5273 				sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5274 				plci_remove(plci);
5275 			}
5276 			else
5277 			{
5278 				sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5279 			}
5280 			break;
5281 		case CONF_ADD: /* ERROR */
5282 		case CONF_BEGIN:
5283 		case CONF_DROP:
5284 		case CONF_ISOLATE:
5285 		case CONF_REATTACH:
5286 			CONF_Ind[0] = 9;
5287 			CONF_Ind[3] = 6;
5288 			switch (pty_cai[5])
5289 			{
5290 			case CONF_BEGIN:
5291 				PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5292 				plci->ptyState = 0;
5293 				break;
5294 			case CONF_DROP:
5295 				CONF_Ind[0] = 5;
5296 				CONF_Ind[3] = 2;
5297 				PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5298 				plci->ptyState = CONNECTED;
5299 				break;
5300 			case CONF_ISOLATE:
5301 				CONF_Ind[0] = 5;
5302 				CONF_Ind[3] = 2;
5303 				PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5304 				plci->ptyState = CONNECTED;
5305 				break;
5306 			case CONF_REATTACH:
5307 				CONF_Ind[0] = 5;
5308 				CONF_Ind[3] = 2;
5309 				PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5310 				plci->ptyState = CONNECTED;
5311 				break;
5312 			case CONF_ADD:
5313 				PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5314 				plci->relatedPTYPLCI = NULL;
5315 				tplci = plci->relatedPTYPLCI;
5316 				if (tplci) tplci->ptyState = CONNECTED;
5317 				plci->ptyState = CONNECTED;
5318 				break;
5319 			}
5320 
5321 			if (pty_cai[2] != 0xff)
5322 			{
5323 				PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5324 			}
5325 			else
5326 			{
5327 				PUT_WORD(&CONF_Ind[4], 0x3303); /* Time-out: network did not respond
5328 								  within the required time */
5329 			}
5330 
5331 			PUT_DWORD(&CONF_Ind[6], 0x0);
5332 			sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5333 			break;
5334 		}
5335 		break;
5336 
5337 		/* Supplementary Service indicates success */
5338 	case S_SERVICE:
5339 		dbug(1, dprintf("Service_Ind"));
5340 		PUT_WORD(&CF_Ind[4], 0);
5341 		switch (pty_cai[5])
5342 		{
5343 		case THREE_PTY_END:
5344 		case THREE_PTY_BEGIN:
5345 		case ECT_EXECUTE:
5346 			if (!plci->relatedPTYPLCI) break;
5347 			tplci = plci->relatedPTYPLCI;
5348 			rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5349 			if (tplci->tel) rId |= EXT_CONTROLLER;
5350 			if (pty_cai[5] == ECT_EXECUTE)
5351 			{
5352 				PUT_WORD(&SS_Ind[1], S_ECT);
5353 
5354 				if (plci->vswitchstate != 3)
5355 				{
5356 
5357 					plci->ptyState = IDLE;
5358 					plci->relatedPTYPLCI = NULL;
5359 					plci->ptyState = 0;
5360 
5361 				}
5362 
5363 				dbug(1, dprintf("ECT OK"));
5364 				sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5365 
5366 
5367 
5368 			}
5369 			else
5370 			{
5371 				switch (plci->ptyState)
5372 				{
5373 				case S_3PTY_BEGIN:
5374 					plci->ptyState = CONNECTED;
5375 					dbug(1, dprintf("3PTY ON"));
5376 					break;
5377 
5378 				case S_3PTY_END:
5379 					plci->ptyState = IDLE;
5380 					plci->relatedPTYPLCI = NULL;
5381 					plci->ptyState = 0;
5382 					dbug(1, dprintf("3PTY OFF"));
5383 					break;
5384 				}
5385 				PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5386 				sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5387 			}
5388 			break;
5389 
5390 		case CALL_DEFLECTION:
5391 			PUT_WORD(&SS_Ind[1], pty_cai[5]);
5392 			for (i = 0; i < max_appl; i++)
5393 			{
5394 				if (application[i].CDEnable)
5395 				{
5396 					if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5397 					application[i].CDEnable = false;
5398 				}
5399 			}
5400 			break;
5401 
5402 		case DEACTIVATION_DIVERSION:
5403 		case ACTIVATION_DIVERSION:
5404 			if (!plci->appl) break;
5405 			PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5406 			PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5407 			sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5408 			plci_remove(plci);
5409 			break;
5410 
5411 		case DIVERSION_INTERROGATE_CFU:
5412 		case DIVERSION_INTERROGATE_CFB:
5413 		case DIVERSION_INTERROGATE_CFNR:
5414 		case DIVERSION_INTERROGATE_NUM:
5415 		case CCBS_REQUEST:
5416 		case CCBS_DEACTIVATE:
5417 		case CCBS_INTERROGATE:
5418 			if (!plci->appl) break;
5419 			switch (pty_cai[5])
5420 			{
5421 			case DIVERSION_INTERROGATE_CFU:
5422 			case DIVERSION_INTERROGATE_CFB:
5423 			case DIVERSION_INTERROGATE_CFNR:
5424 				dbug(1, dprintf("Interr_Div"));
5425 				PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5426 				pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5427 				break;
5428 			case DIVERSION_INTERROGATE_NUM:
5429 				dbug(1, dprintf("Interr_Num"));
5430 				PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5431 				pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5432 				break;
5433 			case CCBS_REQUEST:
5434 				dbug(1, dprintf("CCBS Request"));
5435 				PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5436 				pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5437 				break;
5438 			case CCBS_DEACTIVATE:
5439 				dbug(1, dprintf("CCBS Deactivate"));
5440 				PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5441 				pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5442 				break;
5443 			case CCBS_INTERROGATE:
5444 				dbug(1, dprintf("CCBS Interrogate"));
5445 				PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5446 				pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5447 				break;
5448 			}
5449 			PUT_WORD(&pty_cai[4], 0); /* Supplementary Service Reason */
5450 			PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5451 			sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5452 			plci_remove(plci);
5453 			break;
5454 
5455 		case ACTIVATION_MWI:
5456 		case DEACTIVATION_MWI:
5457 			if (pty_cai[5] == ACTIVATION_MWI)
5458 			{
5459 				PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5460 			}
5461 			else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5462 			if (plci->cr_enquiry)
5463 			{
5464 				sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5465 				plci_remove(plci);
5466 			}
5467 			else
5468 			{
5469 				sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5470 			}
5471 			break;
5472 		case MWI_INDICATION:
5473 			if (pty_cai[0] >= 0x12)
5474 			{
5475 				PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5476 				pty_cai[2] = pty_cai[0] - 2; /* len Parameter */
5477 				pty_cai[5] = pty_cai[0] - 5; /* Supplementary Service-specific parameter len */
5478 				if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5479 				{
5480 					if (plci->internal_command == GET_MWI_STATE) /* result on Message Waiting Listen */
5481 					{
5482 						sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5483 						plci_remove(plci);
5484 						return;
5485 					}
5486 					else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5487 					pty_cai[0] = 0;
5488 				}
5489 				else
5490 				{
5491 					for (i = 0; i < max_appl; i++)
5492 					{
5493 						if (a->Notification_Mask[i]&SMASK_MWI)
5494 						{
5495 							sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5496 							pty_cai[0] = 0;
5497 						}
5498 					}
5499 				}
5500 
5501 				if (!pty_cai[0])
5502 				{ /* acknowledge */
5503 					facility[2] = 0; /* returncode */
5504 				}
5505 				else facility[2] = 0xff;
5506 			}
5507 			else
5508 			{
5509 				/* reject */
5510 				facility[2] = 0xff; /* returncode */
5511 			}
5512 			facility[0] = 2;
5513 			facility[1] = MWI_RESPONSE; /* Function */
5514 			add_p(plci, CAI, facility);
5515 			add_p(plci, ESC, multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5516 			sig_req(plci, S_SERVICE, 0);
5517 			send_req(plci);
5518 			plci->command = 0;
5519 			next_internal_command(Id, plci);
5520 			break;
5521 		case CONF_ADD: /* OK */
5522 		case CONF_BEGIN:
5523 		case CONF_DROP:
5524 		case CONF_ISOLATE:
5525 		case CONF_REATTACH:
5526 		case CONF_PARTYDISC:
5527 			CONF_Ind[0] = 9;
5528 			CONF_Ind[3] = 6;
5529 			switch (pty_cai[5])
5530 			{
5531 			case CONF_BEGIN:
5532 				PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5533 				if (pty_cai[0] == 6)
5534 				{
5535 					d = pty_cai[6];
5536 					PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5537 				}
5538 				else
5539 				{
5540 					PUT_DWORD(&CONF_Ind[6], 0x0);
5541 				}
5542 				break;
5543 			case CONF_ISOLATE:
5544 				PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5545 				CONF_Ind[0] = 5;
5546 				CONF_Ind[3] = 2;
5547 				break;
5548 			case CONF_REATTACH:
5549 				PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5550 				CONF_Ind[0] = 5;
5551 				CONF_Ind[3] = 2;
5552 				break;
5553 			case CONF_DROP:
5554 				PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5555 				CONF_Ind[0] = 5;
5556 				CONF_Ind[3] = 2;
5557 				break;
5558 			case CONF_ADD:
5559 				PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5560 				d = pty_cai[6];
5561 				PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5562 				tplci = plci->relatedPTYPLCI;
5563 				if (tplci) tplci->ptyState = CONNECTED;
5564 				break;
5565 			case CONF_PARTYDISC:
5566 				CONF_Ind[0] = 7;
5567 				CONF_Ind[3] = 4;
5568 				PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5569 				d = pty_cai[6];
5570 				PUT_DWORD(&CONF_Ind[4], d); /* PartyID */
5571 				break;
5572 			}
5573 			plci->ptyState = CONNECTED;
5574 			sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5575 			break;
5576 		case CCBS_INFO_RETAIN:
5577 		case CCBS_ERASECALLLINKAGEID:
5578 		case CCBS_STOP_ALERTING:
5579 			CONF_Ind[0] = 5;
5580 			CONF_Ind[3] = 2;
5581 			switch (pty_cai[5])
5582 			{
5583 			case CCBS_INFO_RETAIN:
5584 				PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5585 				break;
5586 			case CCBS_STOP_ALERTING:
5587 				PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5588 				break;
5589 			case CCBS_ERASECALLLINKAGEID:
5590 				PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5591 				CONF_Ind[0] = 7;
5592 				CONF_Ind[3] = 4;
5593 				CONF_Ind[6] = 0;
5594 				CONF_Ind[7] = 0;
5595 				break;
5596 			}
5597 			w = pty_cai[6];
5598 			PUT_WORD(&CONF_Ind[4], w); /* PartyID */
5599 
5600 			if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5601 			{
5602 				sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5603 			}
5604 			else
5605 			{
5606 				for (i = 0; i < max_appl; i++)
5607 					if (a->Notification_Mask[i] & SMASK_CCBS)
5608 						sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5609 			}
5610 			break;
5611 		}
5612 		break;
5613 	case CALL_HOLD_REJ:
5614 		cau = parms[7];
5615 		if (cau)
5616 		{
5617 			i = _L3_CAUSE | cau[2];
5618 			if (cau[2] == 0) i = 0x3603;
5619 		}
5620 		else
5621 		{
5622 			i = 0x3603;
5623 		}
5624 		PUT_WORD(&SS_Ind[1], S_HOLD);
5625 		PUT_WORD(&SS_Ind[4], i);
5626 		if (plci->SuppState == HOLD_REQUEST)
5627 		{
5628 			plci->SuppState = IDLE;
5629 			sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5630 		}
5631 		break;
5632 
5633 	case CALL_HOLD_ACK:
5634 		if (plci->SuppState == HOLD_REQUEST)
5635 		{
5636 			plci->SuppState = CALL_HELD;
5637 			CodecIdCheck(a, plci);
5638 			start_internal_command(Id, plci, hold_save_command);
5639 		}
5640 		break;
5641 
5642 	case CALL_RETRIEVE_REJ:
5643 		cau = parms[7];
5644 		if (cau)
5645 		{
5646 			i = _L3_CAUSE | cau[2];
5647 			if (cau[2] == 0) i = 0x3603;
5648 		}
5649 		else
5650 		{
5651 			i = 0x3603;
5652 		}
5653 		PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5654 		PUT_WORD(&SS_Ind[4], i);
5655 		if (plci->SuppState == RETRIEVE_REQUEST)
5656 		{
5657 			plci->SuppState = CALL_HELD;
5658 			CodecIdCheck(a, plci);
5659 			sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5660 		}
5661 		break;
5662 
5663 	case CALL_RETRIEVE_ACK:
5664 		PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5665 		if (plci->SuppState == RETRIEVE_REQUEST)
5666 		{
5667 			plci->SuppState = IDLE;
5668 			plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5669 			plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5670 			if (plci->tel)
5671 			{
5672 				mixer_set_bchannel_id_esc(plci, plci->b_channel);
5673 				dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5674 				SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5675 				if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5676 				{
5677 					dbug(1, dprintf("Get B-ch"));
5678 					start_internal_command(Id, plci, retrieve_restore_command);
5679 				}
5680 				else
5681 					sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5682 			}
5683 			else
5684 				start_internal_command(Id, plci, retrieve_restore_command);
5685 		}
5686 		break;
5687 
5688 	case INDICATE_IND:
5689 		if (plci->State != LISTENING) {
5690 			sig_req(plci, HANGUP, 0);
5691 			send_req(plci);
5692 			break;
5693 		}
5694 		cip = find_cip(a, parms[4], parms[6]);
5695 		cip_mask = 1L << cip;
5696 		dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5697 		clear_c_ind_mask(plci);
5698 		if (!remove_started && !a->adapter_disabled)
5699 		{
5700 			set_c_ind_mask_bit(plci, MAX_APPL);
5701 			group_optimization(a, plci);
5702 			for (i = 0; i < max_appl; i++) {
5703 				if (application[i].Id
5704 				    && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5705 				    && CPN_filter_ok(parms[0], a, i)
5706 				    && test_group_ind_mask_bit(plci, i)) {
5707 					dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5708 					set_c_ind_mask_bit(plci, i);
5709 					dump_c_ind_mask(plci);
5710 					plci->State = INC_CON_PENDING;
5711 					plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5712 						CALL_DIR_IN | CALL_DIR_ANSWER;
5713 					if (esc_chi[0]) {
5714 						plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5715 						mixer_set_bchannel_id_esc(plci, plci->b_channel);
5716 					}
5717 					/* if a listen on the ext controller is done, check if hook states */
5718 					/* are supported or if just a on board codec must be activated     */
5719 					if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5720 						if (a->profile.Global_Options & HANDSET)
5721 							plci->tel = ADV_VOICE;
5722 						else if (a->profile.Global_Options & ON_BOARD_CODEC)
5723 							plci->tel = CODEC;
5724 						if (plci->tel) Id |= EXT_CONTROLLER;
5725 						a->codec_listen[i] = plci;
5726 					}
5727 
5728 					sendf(&application[i], _CONNECT_I, Id, 0,
5729 					      "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5730 					      parms[0],    /* CalledPartyNumber   */
5731 					      multi_CiPN_parms[0],    /* CallingPartyNumber  */
5732 					      parms[2],    /* CalledPartySubad    */
5733 					      parms[3],    /* CallingPartySubad   */
5734 					      parms[4],    /* BearerCapability    */
5735 					      parms[5],    /* LowLC               */
5736 					      parms[6],    /* HighLC              */
5737 					      ai_len,      /* nested struct add_i */
5738 					      add_i[0],    /* B channel info    */
5739 					      add_i[1],    /* keypad facility   */
5740 					      add_i[2],    /* user user data    */
5741 					      add_i[3],    /* nested facility   */
5742 					      multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5743 						);
5744 					SendSSExtInd(&application[i],
5745 						     plci,
5746 						     Id,
5747 						     multi_ssext_parms);
5748 					SendSetupInfo(&application[i],
5749 						      plci,
5750 						      Id,
5751 						      parms,
5752 						      SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5753 				}
5754 			}
5755 			clear_c_ind_mask_bit(plci, MAX_APPL);
5756 			dump_c_ind_mask(plci);
5757 		}
5758 		if (c_ind_mask_empty(plci)) {
5759 			sig_req(plci, HANGUP, 0);
5760 			send_req(plci);
5761 			plci->State = IDLE;
5762 		}
5763 		plci->notifiedcall = 0;
5764 		a->listen_active--;
5765 		listen_check(a);
5766 		break;
5767 
5768 	case CALL_PEND_NOTIFY:
5769 		plci->notifiedcall = 1;
5770 		listen_check(a);
5771 		break;
5772 
5773 	case CALL_IND:
5774 	case CALL_CON:
5775 		if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5776 		{
5777 			if (plci->internal_command == PERM_COD_CONN_PEND)
5778 			{
5779 				if (plci->State == ADVANCED_VOICE_NOSIG)
5780 				{
5781 					dbug(1, dprintf("***Codec OK"));
5782 					if (a->AdvSignalPLCI)
5783 					{
5784 						tplci = a->AdvSignalPLCI;
5785 						if (tplci->spoofed_msg)
5786 						{
5787 							dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5788 							tplci->command = 0;
5789 							tplci->internal_command = 0;
5790 							x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5791 							switch (tplci->spoofed_msg)
5792 							{
5793 							case CALL_RES:
5794 								tplci->command = _CONNECT_I | RESPONSE;
5795 								api_load_msg(&tplci->saved_msg, saved_parms);
5796 								add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5797 								if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5798 								{
5799 									/* early B3 connect (CIP mask bit 9) no release after a disc */
5800 									add_p(tplci, LLI, "\x01\x01");
5801 								}
5802 								add_s(tplci, CONN_NR, &saved_parms[2]);
5803 								add_s(tplci, LLC, &saved_parms[4]);
5804 								add_ai(tplci, &saved_parms[5]);
5805 								tplci->State = INC_CON_ACCEPT;
5806 								sig_req(tplci, CALL_RES, 0);
5807 								send_req(tplci);
5808 								break;
5809 
5810 							case AWAITING_SELECT_B:
5811 								dbug(1, dprintf("Select_B continue"));
5812 								start_internal_command(x_Id, tplci, select_b_command);
5813 								break;
5814 
5815 							case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5816 								if (!tplci->Sig.Id)
5817 								{
5818 									dbug(1, dprintf("No SigID!"));
5819 									sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5820 									plci_remove(tplci);
5821 									break;
5822 								}
5823 								tplci->command = _MANUFACTURER_R;
5824 								api_load_msg(&tplci->saved_msg, saved_parms);
5825 								dir = saved_parms[2].info[0];
5826 								if (dir == 1) {
5827 									sig_req(tplci, CALL_REQ, 0);
5828 								}
5829 								else if (!dir) {
5830 									sig_req(tplci, LISTEN_REQ, 0);
5831 								}
5832 								send_req(tplci);
5833 								sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5834 								break;
5835 
5836 							case (CALL_REQ | AWAITING_MANUF_CON):
5837 								sig_req(tplci, CALL_REQ, 0);
5838 								send_req(tplci);
5839 								break;
5840 
5841 							case CALL_REQ:
5842 								if (!tplci->Sig.Id)
5843 								{
5844 									dbug(1, dprintf("No SigID!"));
5845 									sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5846 									plci_remove(tplci);
5847 									break;
5848 								}
5849 								tplci->command = _CONNECT_R;
5850 								api_load_msg(&tplci->saved_msg, saved_parms);
5851 								add_s(tplci, CPN, &saved_parms[1]);
5852 								add_s(tplci, DSA, &saved_parms[3]);
5853 								add_ai(tplci, &saved_parms[9]);
5854 								sig_req(tplci, CALL_REQ, 0);
5855 								send_req(tplci);
5856 								break;
5857 
5858 							case CALL_RETRIEVE:
5859 								tplci->command = C_RETRIEVE_REQ;
5860 								sig_req(tplci, CALL_RETRIEVE, 0);
5861 								send_req(tplci);
5862 								break;
5863 							}
5864 							tplci->spoofed_msg = 0;
5865 							if (tplci->internal_command == 0)
5866 								next_internal_command(x_Id, tplci);
5867 						}
5868 					}
5869 					next_internal_command(Id, plci);
5870 					break;
5871 				}
5872 				dbug(1, dprintf("***Codec Hook Init Req"));
5873 				plci->internal_command = PERM_COD_HOOK;
5874 				add_p(plci, FTY, "\x01\x09");             /* Get Hook State*/
5875 				sig_req(plci, TEL_CTRL, 0);
5876 				send_req(plci);
5877 			}
5878 		}
5879 		else if (plci->command != _MANUFACTURER_R  /* old style permanent connect */
5880 			 && plci->State != INC_ACT_PENDING)
5881 		{
5882 			mixer_set_bchannel_id_esc(plci, plci->b_channel);
5883 			if (plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5884 			{
5885 				chi[2] = plci->b_channel;
5886 				SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5887 			}
5888 			sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5889 			plci->State = INC_ACT_PENDING;
5890 		}
5891 		break;
5892 
5893 	case TEL_CTRL:
5894 		ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5895 		if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5896 			switch (ie[1] & 0x91) {
5897 			case 0x80:   /* hook off */
5898 			case 0x81:
5899 				if (plci->internal_command == PERM_COD_HOOK)
5900 				{
5901 					dbug(1, dprintf("init:hook_off"));
5902 					plci->hook_state = ie[1];
5903 					next_internal_command(Id, plci);
5904 					break;
5905 				}
5906 				else /* ignore doubled hook indications */
5907 				{
5908 					if (((plci->hook_state) & 0xf0) == 0x80)
5909 					{
5910 						dbug(1, dprintf("ignore hook"));
5911 						break;
5912 					}
5913 					plci->hook_state = ie[1]&0x91;
5914 				}
5915 				/* check for incoming call pending */
5916 				/* and signal '+'.Appl must decide */
5917 				/* with connect_res if call must   */
5918 				/* accepted or not                 */
5919 				for (i = 0, tplci = NULL; i < max_appl; i++) {
5920 					if (a->codec_listen[i]
5921 					    && (a->codec_listen[i]->State == INC_CON_PENDING
5922 						|| a->codec_listen[i]->State == INC_CON_ALERT)) {
5923 						tplci = a->codec_listen[i];
5924 						tplci->appl = &application[i];
5925 					}
5926 				}
5927 				/* no incoming call, do outgoing call */
5928 				/* and signal '+' if outg. setup   */
5929 				if (!a->AdvSignalPLCI && !tplci) {
5930 					if ((i = get_plci(a))) {
5931 						a->AdvSignalPLCI = &a->plci[i - 1];
5932 						tplci = a->AdvSignalPLCI;
5933 						tplci->tel  = ADV_VOICE;
5934 						PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5935 						if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5936 							/* early B3 connect (CIP mask bit 9) no release after a disc */
5937 							add_p(tplci, LLI, "\x01\x01");
5938 						}
5939 						add_p(tplci, CAI, voice_cai);
5940 						add_p(tplci, OAD, a->TelOAD);
5941 						add_p(tplci, OSA, a->TelOSA);
5942 						add_p(tplci, SHIFT | 6, NULL);
5943 						add_p(tplci, SIN, "\x02\x01\x00");
5944 						add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5945 						sig_req(tplci, ASSIGN, DSIG_ID);
5946 						a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5947 						a->AdvSignalPLCI->command = 0;
5948 						tplci->appl = a->AdvSignalAppl;
5949 						tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5950 						send_req(tplci);
5951 					}
5952 
5953 				}
5954 
5955 				if (!tplci) break;
5956 				Id = ((word)tplci->Id << 8) | a->Id;
5957 				Id |= EXT_CONTROLLER;
5958 				sendf(tplci->appl,
5959 				      _FACILITY_I,
5960 				      Id,
5961 				      0,
5962 				      "ws", (word)0, "\x01+");
5963 				break;
5964 
5965 			case 0x90:   /* hook on  */
5966 			case 0x91:
5967 				if (plci->internal_command == PERM_COD_HOOK)
5968 				{
5969 					dbug(1, dprintf("init:hook_on"));
5970 					plci->hook_state = ie[1] & 0x91;
5971 					next_internal_command(Id, plci);
5972 					break;
5973 				}
5974 				else /* ignore doubled hook indications */
5975 				{
5976 					if (((plci->hook_state) & 0xf0) == 0x90) break;
5977 					plci->hook_state = ie[1] & 0x91;
5978 				}
5979 				/* hangup the adv. voice call and signal '-' to the appl */
5980 				if (a->AdvSignalPLCI) {
5981 					Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5982 					if (plci->tel) Id |= EXT_CONTROLLER;
5983 					sendf(a->AdvSignalAppl,
5984 					      _FACILITY_I,
5985 					      Id,
5986 					      0,
5987 					      "ws", (word)0, "\x01-");
5988 					a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5989 					a->AdvSignalPLCI->command = 0;
5990 					sig_req(a->AdvSignalPLCI, HANGUP, 0);
5991 					send_req(a->AdvSignalPLCI);
5992 				}
5993 				break;
5994 			}
5995 		}
5996 		break;
5997 
5998 	case RESUME:
5999 		clear_c_ind_mask_bit(plci, (word)(plci->appl->Id - 1));
6000 		PUT_WORD(&resume_cau[4], GOOD);
6001 		sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6002 		break;
6003 
6004 	case SUSPEND:
6005 		clear_c_ind_mask(plci);
6006 
6007 		if (plci->NL.Id && !plci->nl_remove_id) {
6008 			mixer_remove(plci);
6009 			nl_req_ncci(plci, REMOVE, 0);
6010 		}
6011 		if (!plci->sig_remove_id) {
6012 			plci->internal_command = 0;
6013 			sig_req(plci, REMOVE, 0);
6014 		}
6015 		send_req(plci);
6016 		if (!plci->channels) {
6017 			sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6018 			sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6019 		}
6020 		break;
6021 
6022 	case SUSPEND_REJ:
6023 		break;
6024 
6025 	case HANGUP:
6026 		plci->hangup_flow_ctrl_timer = 0;
6027 		if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
6028 		cau = parms[7];
6029 		if (cau) {
6030 			i = _L3_CAUSE | cau[2];
6031 			if (cau[2] == 0) i = 0;
6032 			else if (cau[2] == 8) i = _L1_ERROR;
6033 			else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
6034 			else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
6035 		}
6036 		else {
6037 			i = _L3_ERROR;
6038 		}
6039 
6040 		if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
6041 		{
6042 			for (i = 0; i < max_appl; i++)
6043 			{
6044 				if (test_c_ind_mask_bit(plci, i))
6045 					sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6046 			}
6047 		}
6048 		else
6049 		{
6050 			clear_c_ind_mask(plci);
6051 		}
6052 		if (!plci->appl)
6053 		{
6054 			if (plci->State == LISTENING)
6055 			{
6056 				plci->notifiedcall = 0;
6057 				a->listen_active--;
6058 			}
6059 			plci->State = INC_DIS_PENDING;
6060 			if (c_ind_mask_empty(plci))
6061 			{
6062 				plci->State = IDLE;
6063 				if (plci->NL.Id && !plci->nl_remove_id)
6064 				{
6065 					mixer_remove(plci);
6066 					nl_req_ncci(plci, REMOVE, 0);
6067 				}
6068 				if (!plci->sig_remove_id)
6069 				{
6070 					plci->internal_command = 0;
6071 					sig_req(plci, REMOVE, 0);
6072 				}
6073 				send_req(plci);
6074 			}
6075 		}
6076 		else
6077 		{
6078 			/* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
6079 			/* result in a second HANGUP! Don't generate another        */
6080 			/* DISCONNECT                                               */
6081 			if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
6082 			{
6083 				if (plci->State == RESUMING)
6084 				{
6085 					PUT_WORD(&resume_cau[4], i);
6086 					sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6087 				}
6088 				plci->State = INC_DIS_PENDING;
6089 				sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
6090 			}
6091 		}
6092 		break;
6093 
6094 	case SSEXT_IND:
6095 		SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
6096 		break;
6097 
6098 	case VSWITCH_REQ:
6099 		VSwitchReqInd(plci, Id, multi_vswitch_parms);
6100 		break;
6101 	case VSWITCH_IND:
6102 		if (plci->relatedPTYPLCI &&
6103 		    plci->vswitchstate == 3 &&
6104 		    plci->relatedPTYPLCI->vswitchstate == 3 &&
6105 		    parms[MAXPARMSIDS - 1][0])
6106 		{
6107 			add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
6108 			sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
6109 			send_req(plci->relatedPTYPLCI);
6110 		}
6111 		else VSwitchReqInd(plci, Id, multi_vswitch_parms);
6112 		break;
6113 
6114 	}
6115 }
6116 
6117 
SendSetupInfo(APPL * appl,PLCI * plci,dword Id,byte ** parms,byte Info_Sent_Flag)6118 static void SendSetupInfo(APPL *appl, PLCI *plci, dword Id, byte **parms, byte Info_Sent_Flag)
6119 {
6120 	word i;
6121 	byte *ie;
6122 	word Info_Number;
6123 	byte *Info_Element;
6124 	word Info_Mask = 0;
6125 
6126 	dbug(1, dprintf("SetupInfo"));
6127 
6128 	for (i = 0; i < MAXPARMSIDS; i++) {
6129 		ie = parms[i];
6130 		Info_Number = 0;
6131 		Info_Element = ie;
6132 		if (ie[0]) {
6133 			switch (i) {
6134 			case 0:
6135 				dbug(1, dprintf("CPN "));
6136 				Info_Number = 0x0070;
6137 				Info_Mask = 0x80;
6138 				Info_Sent_Flag = true;
6139 				break;
6140 			case 8:  /* display      */
6141 				dbug(1, dprintf("display(%d)", i));
6142 				Info_Number = 0x0028;
6143 				Info_Mask = 0x04;
6144 				Info_Sent_Flag = true;
6145 				break;
6146 			case 16: /* Channel Id */
6147 				dbug(1, dprintf("CHI"));
6148 				Info_Number = 0x0018;
6149 				Info_Mask = 0x100;
6150 				Info_Sent_Flag = true;
6151 				mixer_set_bchannel_id(plci, Info_Element);
6152 				break;
6153 			case 19: /* Redirected Number */
6154 				dbug(1, dprintf("RDN"));
6155 				Info_Number = 0x0074;
6156 				Info_Mask = 0x400;
6157 				Info_Sent_Flag = true;
6158 				break;
6159 			case 20: /* Redirected Number extended */
6160 				dbug(1, dprintf("RDX"));
6161 				Info_Number = 0x0073;
6162 				Info_Mask = 0x400;
6163 				Info_Sent_Flag = true;
6164 				break;
6165 			case 22: /* Redirecing Number  */
6166 				dbug(1, dprintf("RIN"));
6167 				Info_Number = 0x0076;
6168 				Info_Mask = 0x400;
6169 				Info_Sent_Flag = true;
6170 				break;
6171 			default:
6172 				Info_Number = 0;
6173 				break;
6174 			}
6175 		}
6176 
6177 		if (i == MAXPARMSIDS - 2) { /* to indicate the message type "Setup" */
6178 			Info_Number = 0x8000 | 5;
6179 			Info_Mask = 0x10;
6180 			Info_Element = "";
6181 		}
6182 
6183 		if (Info_Sent_Flag && Info_Number) {
6184 			if (plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask) {
6185 				sendf(appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6186 			}
6187 		}
6188 	}
6189 }
6190 
6191 
SendInfo(PLCI * plci,dword Id,byte ** parms,byte iesent)6192 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6193 {
6194 	word i;
6195 	word j;
6196 	word k;
6197 	byte *ie;
6198 	word Info_Number;
6199 	byte *Info_Element;
6200 	word Info_Mask = 0;
6201 	static byte charges[5] = {4, 0, 0, 0, 0};
6202 	static byte cause[] = {0x02, 0x80, 0x00};
6203 	APPL *appl;
6204 
6205 	dbug(1, dprintf("InfoParse "));
6206 
6207 	if (
6208 		!plci->appl
6209 		&& !plci->State
6210 		&& plci->Sig.Ind != NCR_FACILITY
6211 		)
6212 	{
6213 		dbug(1, dprintf("NoParse "));
6214 		return;
6215 	}
6216 	cause[2] = 0;
6217 	for (i = 0; i < MAXPARMSIDS; i++) {
6218 		ie = parms[i];
6219 		Info_Number = 0;
6220 		Info_Element = ie;
6221 		if (ie[0]) {
6222 			switch (i) {
6223 			case 0:
6224 				dbug(1, dprintf("CPN "));
6225 				Info_Number = 0x0070;
6226 				Info_Mask   = 0x80;
6227 				break;
6228 			case 7: /* ESC_CAU */
6229 				dbug(1, dprintf("cau(0x%x)", ie[2]));
6230 				Info_Number = 0x0008;
6231 				Info_Mask = 0x00;
6232 				cause[2] = ie[2];
6233 				Info_Element = NULL;
6234 				break;
6235 			case 8:  /* display      */
6236 				dbug(1, dprintf("display(%d)", i));
6237 				Info_Number = 0x0028;
6238 				Info_Mask = 0x04;
6239 				break;
6240 			case 9:  /* Date display */
6241 				dbug(1, dprintf("date(%d)", i));
6242 				Info_Number = 0x0029;
6243 				Info_Mask = 0x02;
6244 				break;
6245 			case 10: /* charges */
6246 				for (j = 0; j < 4; j++) charges[1 + j] = 0;
6247 				for (j = 0; j < ie[0] && !(ie[1 + j] & 0x80); j++);
6248 				for (k = 1, j++; j < ie[0] && k <= 4; j++, k++) charges[k] = ie[1 + j];
6249 				Info_Number = 0x4000;
6250 				Info_Mask = 0x40;
6251 				Info_Element = charges;
6252 				break;
6253 			case 11: /* user user info */
6254 				dbug(1, dprintf("uui"));
6255 				Info_Number = 0x007E;
6256 				Info_Mask = 0x08;
6257 				break;
6258 			case 12: /* congestion receiver ready */
6259 				dbug(1, dprintf("clRDY"));
6260 				Info_Number = 0x00B0;
6261 				Info_Mask = 0x08;
6262 				Info_Element = "";
6263 				break;
6264 			case 13: /* congestion receiver not ready */
6265 				dbug(1, dprintf("clNRDY"));
6266 				Info_Number = 0x00BF;
6267 				Info_Mask = 0x08;
6268 				Info_Element = "";
6269 				break;
6270 			case 15: /* Keypad Facility */
6271 				dbug(1, dprintf("KEY"));
6272 				Info_Number = 0x002C;
6273 				Info_Mask = 0x20;
6274 				break;
6275 			case 16: /* Channel Id */
6276 				dbug(1, dprintf("CHI"));
6277 				Info_Number = 0x0018;
6278 				Info_Mask = 0x100;
6279 				mixer_set_bchannel_id(plci, Info_Element);
6280 				break;
6281 			case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6282 				dbug(1, dprintf("q9cau(0x%x)", ie[2]));
6283 				if (!cause[2] || cause[2] < 0x80) break;  /* eg. layer 1 error */
6284 				Info_Number = 0x0008;
6285 				Info_Mask = 0x01;
6286 				if (cause[2] != ie[2]) Info_Element = cause;
6287 				break;
6288 			case 19: /* Redirected Number */
6289 				dbug(1, dprintf("RDN"));
6290 				Info_Number = 0x0074;
6291 				Info_Mask = 0x400;
6292 				break;
6293 			case 22: /* Redirecing Number  */
6294 				dbug(1, dprintf("RIN"));
6295 				Info_Number = 0x0076;
6296 				Info_Mask = 0x400;
6297 				break;
6298 			case 23: /* Notification Indicator  */
6299 				dbug(1, dprintf("NI"));
6300 				Info_Number = (word)NI;
6301 				Info_Mask = 0x210;
6302 				break;
6303 			case 26: /* Call State  */
6304 				dbug(1, dprintf("CST"));
6305 				Info_Number = (word)CST;
6306 				Info_Mask = 0x01; /* do with cause i.e. for now */
6307 				break;
6308 			case MAXPARMSIDS - 2:  /* Escape Message Type, must be the last indication */
6309 				dbug(1, dprintf("ESC/MT[0x%x]", ie[3]));
6310 				Info_Number = 0x8000 | ie[3];
6311 				if (iesent) Info_Mask = 0xffff;
6312 				else  Info_Mask = 0x10;
6313 				Info_Element = "";
6314 				break;
6315 			default:
6316 				Info_Number  = 0;
6317 				Info_Mask    = 0;
6318 				Info_Element = "";
6319 				break;
6320 			}
6321 		}
6322 
6323 		if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6324 		{
6325 			for (j = 0; j < max_appl; j++)
6326 			{
6327 				appl = &application[j];
6328 				if (Info_Number
6329 				    && appl->Id
6330 				    && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6331 				{
6332 					dbug(1, dprintf("NCR_Ind"));
6333 					iesent = true;
6334 					sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6335 				}
6336 			}
6337 		}
6338 		else if (!plci->appl)
6339 		{ /* overlap receiving broadcast */
6340 			if (Info_Number == CPN
6341 			    || Info_Number == KEY
6342 			    || Info_Number == NI
6343 			    || Info_Number == DSP
6344 			    || Info_Number == UUI)
6345 			{
6346 				for (j = 0; j < max_appl; j++)
6347 				{
6348 					if (test_c_ind_mask_bit(plci, j))
6349 					{
6350 						dbug(1, dprintf("Ovl_Ind"));
6351 						iesent = true;
6352 						sendf(&application[j], _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6353 					}
6354 				}
6355 			}
6356 		}               /* all other signalling states */
6357 		else if (Info_Number
6358 			 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6359 		{
6360 			dbug(1, dprintf("Std_Ind"));
6361 			iesent = true;
6362 			sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6363 		}
6364 	}
6365 }
6366 
6367 
SendMultiIE(PLCI * plci,dword Id,byte ** parms,byte ie_type,dword info_mask,byte setupParse)6368 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6369 			dword info_mask, byte setupParse)
6370 {
6371 	word i;
6372 	word j;
6373 	byte *ie;
6374 	word Info_Number;
6375 	byte *Info_Element;
6376 	APPL *appl;
6377 	word Info_Mask = 0;
6378 	byte iesent = 0;
6379 
6380 	if (
6381 		!plci->appl
6382 		&& !plci->State
6383 		&& plci->Sig.Ind != NCR_FACILITY
6384 		&& !setupParse
6385 		)
6386 	{
6387 		dbug(1, dprintf("NoM-IEParse "));
6388 		return 0;
6389 	}
6390 	dbug(1, dprintf("M-IEParse "));
6391 
6392 	for (i = 0; i < MAX_MULTI_IE; i++)
6393 	{
6394 		ie = parms[i];
6395 		Info_Number = 0;
6396 		Info_Element = ie;
6397 		if (ie[0])
6398 		{
6399 			dbug(1, dprintf("[Ind0x%x]:IE=0x%x", plci->Sig.Ind, ie_type));
6400 			Info_Number = (word)ie_type;
6401 			Info_Mask = (word)info_mask;
6402 		}
6403 
6404 		if (plci->Sig.Ind == NCR_FACILITY)           /* check controller broadcast */
6405 		{
6406 			for (j = 0; j < max_appl; j++)
6407 			{
6408 				appl = &application[j];
6409 				if (Info_Number
6410 				    && appl->Id
6411 				    && plci->adapter->Info_Mask[appl->Id - 1] & Info_Mask)
6412 				{
6413 					iesent = true;
6414 					dbug(1, dprintf("Mlt_NCR_Ind"));
6415 					sendf(&application[j], _INFO_I, Id & 0x0f, 0, "wS", Info_Number, Info_Element);
6416 				}
6417 			}
6418 		}
6419 		else if (!plci->appl && Info_Number)
6420 		{                                        /* overlap receiving broadcast */
6421 			for (j = 0; j < max_appl; j++)
6422 			{
6423 				if (test_c_ind_mask_bit(plci, j))
6424 				{
6425 					iesent = true;
6426 					dbug(1, dprintf("Mlt_Ovl_Ind"));
6427 					sendf(&application[j] , _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6428 				}
6429 			}
6430 		}                                        /* all other signalling states */
6431 		else if (Info_Number
6432 			 && plci->adapter->Info_Mask[plci->appl->Id - 1] & Info_Mask)
6433 		{
6434 			iesent = true;
6435 			dbug(1, dprintf("Mlt_Std_Ind"));
6436 			sendf(plci->appl, _INFO_I, Id, 0, "wS", Info_Number, Info_Element);
6437 		}
6438 	}
6439 	return iesent;
6440 }
6441 
SendSSExtInd(APPL * appl,PLCI * plci,dword Id,byte ** parms)6442 static void SendSSExtInd(APPL *appl, PLCI *plci, dword Id, byte **parms)
6443 {
6444 	word i;
6445 	/* Format of multi_ssext_parms[i][]:
6446 	   0 byte length
6447 	   1 byte SSEXTIE
6448 	   2 byte SSEXT_REQ/SSEXT_IND
6449 	   3 byte length
6450 	   4 word SSExtCommand
6451 	   6... Params
6452 	*/
6453 	if (
6454 		plci
6455 		&& plci->State
6456 		&& plci->Sig.Ind != NCR_FACILITY
6457 		)
6458 		for (i = 0; i < MAX_MULTI_IE; i++)
6459 		{
6460 			if (parms[i][0] < 6) continue;
6461 			if (parms[i][2] == SSEXT_REQ) continue;
6462 
6463 			if (appl)
6464 			{
6465 				parms[i][0] = 0; /* kill it */
6466 				sendf(appl, _MANUFACTURER_I,
6467 				      Id,
6468 				      0,
6469 				      "dwS",
6470 				      _DI_MANU_ID,
6471 				      _DI_SSEXT_CTRL,
6472 				      &parms[i][3]);
6473 			}
6474 			else if (plci->appl)
6475 			{
6476 				parms[i][0] = 0; /* kill it */
6477 				sendf(plci->appl, _MANUFACTURER_I,
6478 				      Id,
6479 				      0,
6480 				      "dwS",
6481 				      _DI_MANU_ID,
6482 				      _DI_SSEXT_CTRL,
6483 				      &parms[i][3]);
6484 			}
6485 		}
6486 };
6487 
nl_ind(PLCI * plci)6488 static void nl_ind(PLCI *plci)
6489 {
6490 	byte ch;
6491 	word ncci;
6492 	dword Id;
6493 	DIVA_CAPI_ADAPTER *a;
6494 	word NCCIcode;
6495 	APPL *APPLptr;
6496 	word count;
6497 	word Num;
6498 	word i, ncpi_state;
6499 	byte len, ncci_state;
6500 	word msg;
6501 	word info = 0;
6502 	word fax_feature_bits;
6503 	byte fax_send_edata_ack;
6504 	static byte v120_header_buffer[2 + 3];
6505 	static word fax_info[] = {
6506 		0,                     /* T30_SUCCESS                        */
6507 		_FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
6508 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
6509 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
6510 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
6511 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
6512 		_FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
6513 		_FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
6514 		_FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
6515 		_FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
6516 		_FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
6517 		_FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
6518 		_FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
6519 		_FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
6520 		_FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
6521 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
6522 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
6523 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
6524 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
6525 		_FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
6526 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
6527 		_FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
6528 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
6529 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
6530 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
6531 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
6532 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
6533 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
6534 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
6535 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
6536 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
6537 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
6538 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
6539 		0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
6540 		0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
6541 		0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
6542 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
6543 		_FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
6544 		_FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
6545 		_FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
6546 		_FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
6547 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6548 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
6549 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
6550 		_FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
6551 		_FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
6552 		_FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
6553 	};
6554 
6555 	byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6556 
6557 
6558 	static word rtp_info[] = {
6559 		GOOD,                  /* RTP_SUCCESS                       */
6560 		0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
6561 	};
6562 
6563 	static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6564 		{
6565 			0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6566 			0x00000000, 0x00000000, 0x00000000, 0x00000000
6567 		};
6568 
6569 	ch = plci->NL.IndCh;
6570 	a = plci->adapter;
6571 	ncci = a->ch_ncci[ch];
6572 	Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6573 	if (plci->tel) Id |= EXT_CONTROLLER;
6574 	APPLptr = plci->appl;
6575 	dbug(1, dprintf("NL_IND-Id(NL:0x%x)=0x%08lx,plci=%x,tel=%x,state=0x%x,ch=0x%x,chs=%d,Ind=%x",
6576 			plci->NL.Id, Id, plci->Id, plci->tel, plci->State, ch, plci->channels, plci->NL.Ind & 0x0f));
6577 
6578 	/* in the case if no connect_active_Ind was sent to the appl we wait for */
6579 
6580 	if (plci->nl_remove_id)
6581 	{
6582 		plci->NL.RNR = 2; /* discard */
6583 		dbug(1, dprintf("NL discard while remove pending"));
6584 		return;
6585 	}
6586 	if ((plci->NL.Ind & 0x0f) == N_CONNECT)
6587 	{
6588 		if (plci->State == INC_DIS_PENDING
6589 		    || plci->State == OUTG_DIS_PENDING
6590 		    || plci->State == IDLE)
6591 		{
6592 			plci->NL.RNR = 2; /* discard */
6593 			dbug(1, dprintf("discard n_connect"));
6594 			return;
6595 		}
6596 		if (plci->State < INC_ACT_PENDING)
6597 		{
6598 			plci->NL.RNR = 1; /* flow control */
6599 			channel_x_off(plci, ch, N_XON_CONNECT_IND);
6600 			return;
6601 		}
6602 	}
6603 
6604 	if (!APPLptr)                         /* no application or invalid data */
6605 	{                                    /* while reloading the DSP        */
6606 		dbug(1, dprintf("discard1"));
6607 		plci->NL.RNR = 2;
6608 		return;
6609 	}
6610 
6611 	if (((plci->NL.Ind & 0x0f) == N_UDATA)
6612 	    && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6613 		|| (plci->B2_prot == 7)
6614 		|| (plci->B3_prot == 7)))
6615 	{
6616 		plci->ncpi_buffer[0] = 0;
6617 
6618 		ncpi_state = plci->ncpi_state;
6619 		if (plci->NL.complete == 1)
6620 		{
6621 			byte *data = &plci->NL.RBuffer->P[0];
6622 
6623 			if ((plci->NL.RBuffer->length >= 12)
6624 			    && ((*data == DSP_UDATA_INDICATION_DCD_ON)
6625 				|| (*data == DSP_UDATA_INDICATION_CTS_ON)))
6626 			{
6627 				word conn_opt, ncpi_opt = 0x00;
6628 /*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6629 
6630 				if (*data == DSP_UDATA_INDICATION_DCD_ON)
6631 					plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6632 				if (*data == DSP_UDATA_INDICATION_CTS_ON)
6633 					plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6634 
6635 				data++;    /* indication code */
6636 				data += 2; /* timestamp */
6637 				if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6638 					ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6639 				data++;    /* connected norm */
6640 				conn_opt = GET_WORD(data);
6641 				data += 2; /* connected options */
6642 
6643 				PUT_WORD(&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6644 
6645 				if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6646 				{
6647 					ncpi_opt |= MDM_NCPI_ECM_V42;
6648 				}
6649 				else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6650 				{
6651 					ncpi_opt |= MDM_NCPI_ECM_MNP;
6652 				}
6653 				else
6654 				{
6655 					ncpi_opt |= MDM_NCPI_TRANSPARENT;
6656 				}
6657 				if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6658 				{
6659 					ncpi_opt |= MDM_NCPI_COMPRESSED;
6660 				}
6661 				PUT_WORD(&(plci->ncpi_buffer[3]), ncpi_opt);
6662 				plci->ncpi_buffer[0] = 4;
6663 
6664 				plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6665 			}
6666 		}
6667 		if (plci->B3_prot == 7)
6668 		{
6669 			if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6670 			    && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6671 			    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6672 			{
6673 				a->ncci_state[ncci] = INC_ACT_PENDING;
6674 				sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6675 				plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6676 			}
6677 		}
6678 
6679 		if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
6680 		      & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6681 		    || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6682 		    || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6683 
6684 		{
6685 			plci->NL.RNR = 2;
6686 			return;
6687 		}
6688 	}
6689 
6690 	if (plci->NL.complete == 2)
6691 	{
6692 		if (((plci->NL.Ind & 0x0f) == N_UDATA)
6693 		    && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6694 		{
6695 			switch (plci->RData[0].P[0])
6696 			{
6697 
6698 			case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6699 				if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6700 					sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01X");
6701 				break;
6702 			case DTMF_UDATA_INDICATION_ANSWER_TONE:
6703 				if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6704 					sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", SELECTOR_DTMF, "\x01Y");
6705 				break;
6706 			case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6707 				dtmf_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6708 				break;
6709 			case DTMF_UDATA_INDICATION_DIGITS_SENT:
6710 				dtmf_confirmation(Id, plci);
6711 				break;
6712 
6713 
6714 			case UDATA_INDICATION_MIXER_TAP_DATA:
6715 				capidtmf_recv_process_block(&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6716 				i = capidtmf_indication(&(plci->capidtmf_state), dtmf_code_buffer + 1);
6717 				if (i != 0)
6718 				{
6719 					dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6720 					dtmf_indication(Id, plci, dtmf_code_buffer, (word)(i + 1));
6721 				}
6722 				break;
6723 
6724 
6725 			case UDATA_INDICATION_MIXER_COEFS_SET:
6726 				mixer_indication_coefs_set(Id, plci);
6727 				break;
6728 			case UDATA_INDICATION_XCONNECT_FROM:
6729 				mixer_indication_xconnect_from(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6730 				break;
6731 			case UDATA_INDICATION_XCONNECT_TO:
6732 				mixer_indication_xconnect_to(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6733 				break;
6734 
6735 
6736 			case LEC_UDATA_INDICATION_DISABLE_DETECT:
6737 				ec_indication(Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6738 				break;
6739 
6740 
6741 
6742 			default:
6743 				break;
6744 			}
6745 		}
6746 		else
6747 		{
6748 			if ((plci->RData[0].PLength != 0)
6749 			    && ((plci->B2_prot == B2_V120_ASYNC)
6750 				|| (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6751 				|| (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6752 			{
6753 
6754 				sendf(plci->appl, _DATA_B3_I, Id, 0,
6755 				      "dwww",
6756 				      plci->RData[1].P,
6757 				      (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6758 				      plci->RNum,
6759 				      plci->RFlags);
6760 
6761 			}
6762 			else
6763 			{
6764 
6765 				sendf(plci->appl, _DATA_B3_I, Id, 0,
6766 				      "dwww",
6767 				      plci->RData[0].P,
6768 				      plci->RData[0].PLength,
6769 				      plci->RNum,
6770 				      plci->RFlags);
6771 
6772 			}
6773 		}
6774 		return;
6775 	}
6776 
6777 	fax_feature_bits = 0;
6778 	if ((plci->NL.Ind & 0x0f) == N_CONNECT ||
6779 	    (plci->NL.Ind & 0x0f) == N_CONNECT_ACK ||
6780 	    (plci->NL.Ind & 0x0f) == N_DISC ||
6781 	    (plci->NL.Ind & 0x0f) == N_EDATA ||
6782 	    (plci->NL.Ind & 0x0f) == N_DISC_ACK)
6783 	{
6784 		info = 0;
6785 		plci->ncpi_buffer[0] = 0;
6786 		switch (plci->B3_prot) {
6787 		case  0: /*XPARENT*/
6788 		case  1: /*T.90 NL*/
6789 			break;    /* no network control protocol info - jfr */
6790 		case  2: /*ISO8202*/
6791 		case  3: /*X25 DCE*/
6792 			for (i = 0; i < plci->NL.RLength; i++) plci->ncpi_buffer[4 + i] = plci->NL.RBuffer->P[i];
6793 			plci->ncpi_buffer[0] = (byte)(i + 3);
6794 			plci->ncpi_buffer[1] = (byte)(plci->NL.Ind & N_D_BIT ? 1 : 0);
6795 			plci->ncpi_buffer[2] = 0;
6796 			plci->ncpi_buffer[3] = 0;
6797 			break;
6798 		case  4: /*T.30 - FAX*/
6799 		case  5: /*T.30 - FAX*/
6800 			if (plci->NL.RLength >= sizeof(T30_INFO))
6801 			{
6802 				dbug(1, dprintf("FaxStatus %04x", ((T30_INFO *)plci->NL.RBuffer->P)->code));
6803 				len = 9;
6804 				PUT_WORD(&(plci->ncpi_buffer[1]), ((T30_INFO *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6805 				fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6806 				i = (((T30_INFO *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6807 				if (plci->B3_prot == 5)
6808 				{
6809 					if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6810 						i |= 0x8000; /* This is not an ECM connection */
6811 					if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6812 						i |= 0x4000; /* This is a connection with MMR compression */
6813 					if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6814 						i |= 0x2000; /* This is a connection with MR compression */
6815 					if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6816 						i |= 0x0004; /* More documents */
6817 					if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6818 						i |= 0x0002; /* Fax-polling indication */
6819 				}
6820 				dbug(1, dprintf("FAX Options %04x %04x", fax_feature_bits, i));
6821 				PUT_WORD(&(plci->ncpi_buffer[3]), i);
6822 				PUT_WORD(&(plci->ncpi_buffer[5]), ((T30_INFO *)plci->NL.RBuffer->P)->data_format);
6823 				plci->ncpi_buffer[7] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_low;
6824 				plci->ncpi_buffer[8] = ((T30_INFO *)plci->NL.RBuffer->P)->pages_high;
6825 				plci->ncpi_buffer[len] = 0;
6826 				if (((T30_INFO *)plci->NL.RBuffer->P)->station_id_len)
6827 				{
6828 					plci->ncpi_buffer[len] = 20;
6829 					for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
6830 						plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i];
6831 				}
6832 				if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6833 				{
6834 					if (((T30_INFO *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6835 						info = fax_info[((T30_INFO *)plci->NL.RBuffer->P)->code];
6836 					else
6837 						info = _FAX_PROTOCOL_ERROR;
6838 				}
6839 
6840 				if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
6841 				    & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6842 				{
6843 					i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len;
6844 					while (i < plci->NL.RBuffer->length)
6845 						plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6846 				}
6847 
6848 				plci->ncpi_buffer[0] = len;
6849 				fax_feature_bits = GET_WORD(&((T30_INFO *)plci->NL.RBuffer->P)->feature_bits_low);
6850 				PUT_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6851 
6852 				plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6853 				if (((plci->NL.Ind & 0x0f) == N_CONNECT_ACK)
6854 				    || (((plci->NL.Ind & 0x0f) == N_CONNECT)
6855 					&& (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6856 				    || (((plci->NL.Ind & 0x0f) == N_EDATA)
6857 					&& ((((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6858 					    || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6859 					    || (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6860 				{
6861 					plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6862 				}
6863 				if (((plci->NL.Ind & 0x0f) == N_DISC)
6864 				    || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)
6865 				    || (((plci->NL.Ind & 0x0f) == N_EDATA)
6866 					&& (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6867 				{
6868 					plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6869 				}
6870 			}
6871 			break;
6872 
6873 		case B3_RTP:
6874 			if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6875 			{
6876 				if (plci->NL.RLength != 0)
6877 				{
6878 					info = rtp_info[plci->NL.RBuffer->P[0]];
6879 					plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6880 					for (i = 1; i < plci->NL.RLength; i++)
6881 						plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6882 				}
6883 			}
6884 			break;
6885 
6886 		}
6887 		plci->NL.RNR = 2;
6888 	}
6889 	switch (plci->NL.Ind & 0x0f) {
6890 	case N_EDATA:
6891 		if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6892 		{
6893 			dbug(1, dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6894 					((T30_INFO *)plci->NL.RBuffer->P)->code));
6895 			fax_send_edata_ack = (((T30_INFO *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6896 
6897 			if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6898 			    && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6899 			    && (((T30_INFO *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6900 			    && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6901 			    && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6902 			    && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6903 			{
6904 				((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6905 				sendf(plci->appl, _MANUFACTURER_I, Id, 0, "dwbS", _DI_MANU_ID, _DI_NEGOTIATE_B3,
6906 				      (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6907 				plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6908 				if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6909 					fax_send_edata_ack = false;
6910 			}
6911 
6912 			if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6913 			{
6914 				switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6915 				{
6916 				case EDATA_T30_DIS:
6917 					if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6918 					    && !(GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6919 					    && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6920 					    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6921 					{
6922 						a->ncci_state[ncci] = INC_ACT_PENDING;
6923 						if (plci->B3_prot == 4)
6924 							sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6925 						else
6926 							sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6927 						plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6928 					}
6929 					break;
6930 
6931 				case EDATA_T30_TRAIN_OK:
6932 					if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6933 					    && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6934 					    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6935 					{
6936 						if (plci->B3_prot == 4)
6937 							sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6938 						else
6939 							sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6940 						plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6941 					}
6942 					break;
6943 
6944 				case EDATA_T30_EOP_CAPI:
6945 					if (a->ncci_state[ncci] == CONNECTED)
6946 					{
6947 						sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", GOOD, plci->ncpi_buffer);
6948 						a->ncci_state[ncci] = INC_DIS_PENDING;
6949 						plci->ncpi_state = 0;
6950 						fax_send_edata_ack = false;
6951 					}
6952 					break;
6953 				}
6954 			}
6955 			else
6956 			{
6957 				switch (((T30_INFO *)plci->NL.RBuffer->P)->code)
6958 				{
6959 				case EDATA_T30_TRAIN_OK:
6960 					if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6961 					    && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6962 					    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6963 					{
6964 						if (plci->B3_prot == 4)
6965 							sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
6966 						else
6967 							sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
6968 						plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6969 					}
6970 					break;
6971 				}
6972 			}
6973 			if (fax_send_edata_ack)
6974 			{
6975 				((T30_INFO *)(plci->fax_connect_info_buffer))->code = ((T30_INFO *)plci->NL.RBuffer->P)->code;
6976 				plci->fax_edata_ack_length = 1;
6977 				start_internal_command(Id, plci, fax_edata_ack_command);
6978 			}
6979 		}
6980 		else
6981 		{
6982 			dbug(1, dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6983 		}
6984 		break;
6985 	case N_CONNECT:
6986 		if (!a->ch_ncci[ch])
6987 		{
6988 			ncci = get_ncci(plci, ch, 0);
6989 			Id = (Id & 0xffff) | (((dword) ncci) << 16);
6990 		}
6991 		dbug(1, dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6992 				ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6993 
6994 		msg = _CONNECT_B3_I;
6995 		if (a->ncci_state[ncci] == IDLE)
6996 			plci->channels++;
6997 		else if (plci->B3_prot == 1)
6998 			msg = _CONNECT_B3_T90_ACTIVE_I;
6999 
7000 		a->ncci_state[ncci] = INC_CON_PENDING;
7001 		if (plci->B3_prot == 4)
7002 			sendf(plci->appl, msg, Id, 0, "s", "");
7003 		else
7004 			sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7005 		break;
7006 	case N_CONNECT_ACK:
7007 		dbug(1, dprintf("N_connect_Ack"));
7008 		if (plci->internal_command_queue[0]
7009 		    && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
7010 			|| (plci->adjust_b_state == ADJUST_B_CONNECT_3)
7011 			|| (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
7012 		{
7013 			(*(plci->internal_command_queue[0]))(Id, plci, 0);
7014 			if (!plci->internal_command)
7015 				next_internal_command(Id, plci);
7016 			break;
7017 		}
7018 		msg = _CONNECT_B3_ACTIVE_I;
7019 		if (plci->B3_prot == 1)
7020 		{
7021 			if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7022 				msg = _CONNECT_B3_T90_ACTIVE_I;
7023 			a->ncci_state[ncci] = INC_ACT_PENDING;
7024 			sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7025 		}
7026 		else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7027 		{
7028 			if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7029 			    && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7030 			    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7031 			{
7032 				a->ncci_state[ncci] = INC_ACT_PENDING;
7033 				if (plci->B3_prot == 4)
7034 					sendf(plci->appl, msg, Id, 0, "s", "");
7035 				else
7036 					sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7037 				plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7038 			}
7039 		}
7040 		else
7041 		{
7042 			a->ncci_state[ncci] = INC_ACT_PENDING;
7043 			sendf(plci->appl, msg, Id, 0, "S", plci->ncpi_buffer);
7044 		}
7045 		if (plci->adjust_b_restore)
7046 		{
7047 			plci->adjust_b_restore = false;
7048 			start_internal_command(Id, plci, adjust_b_restore);
7049 		}
7050 		break;
7051 	case N_DISC:
7052 	case N_DISC_ACK:
7053 		if (plci->internal_command_queue[0]
7054 		    && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7055 			|| (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7056 			|| (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7057 		{
7058 			(*(plci->internal_command_queue[0]))(Id, plci, 0);
7059 			if (!plci->internal_command)
7060 				next_internal_command(Id, plci);
7061 		}
7062 		ncci_state = a->ncci_state[ncci];
7063 		ncci_remove(plci, ncci, false);
7064 
7065 		/* with N_DISC or N_DISC_ACK the IDI frees the respective   */
7066 		/* channel, so we cannot store the state in ncci_state! The */
7067 		/* information which channel we received a N_DISC is thus   */
7068 		/* stored in the inc_dis_ncci_table buffer.                 */
7069 		for (i = 0; plci->inc_dis_ncci_table[i]; i++);
7070 		plci->inc_dis_ncci_table[i] = (byte) ncci;
7071 
7072 		/* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7073 		if (!plci->channels
7074 		    && (plci->B1_resource == 16)
7075 		    && (plci->State <= CONNECTED))
7076 		{
7077 			len = 9;
7078 			i = ((T30_INFO *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7079 			PUT_WORD(&plci->ncpi_buffer[1], i);
7080 			PUT_WORD(&plci->ncpi_buffer[3], 0);
7081 			i = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
7082 			PUT_WORD(&plci->ncpi_buffer[5], i);
7083 			PUT_WORD(&plci->ncpi_buffer[7], 0);
7084 			plci->ncpi_buffer[len] = 0;
7085 			plci->ncpi_buffer[0] = len;
7086 			if (plci->B3_prot == 4)
7087 				sendf(plci->appl, _CONNECT_B3_I, Id, 0, "s", "");
7088 			else
7089 			{
7090 
7091 				if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id - 1])
7092 				    & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7093 				{
7094 					plci->ncpi_buffer[++len] = 0;
7095 					plci->ncpi_buffer[++len] = 0;
7096 					plci->ncpi_buffer[++len] = 0;
7097 					plci->ncpi_buffer[0] = len;
7098 				}
7099 
7100 				sendf(plci->appl, _CONNECT_B3_I, Id, 0, "S", plci->ncpi_buffer);
7101 			}
7102 			sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7103 			plci->ncpi_state = 0;
7104 			sig_req(plci, HANGUP, 0);
7105 			send_req(plci);
7106 			plci->State = OUTG_DIS_PENDING;
7107 			/* disc here */
7108 		}
7109 		else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7110 			 && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7111 			 && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7112 		{
7113 			if (ncci_state == IDLE)
7114 			{
7115 				if (plci->channels)
7116 					plci->channels--;
7117 				if ((plci->State == IDLE || plci->State == SUSPENDING) && !plci->channels) {
7118 					if (plci->State == SUSPENDING) {
7119 						sendf(plci->appl,
7120 						      _FACILITY_I,
7121 						      Id & 0xffffL,
7122 						      0,
7123 						      "ws", (word)3, "\x03\x04\x00\x00");
7124 						sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7125 					}
7126 					plci_remove(plci);
7127 					plci->State = IDLE;
7128 				}
7129 			}
7130 		}
7131 		else if (plci->channels)
7132 		{
7133 			sendf(plci->appl, _DISCONNECT_B3_I, Id, 0, "wS", info, plci->ncpi_buffer);
7134 			plci->ncpi_state = 0;
7135 			if ((ncci_state == OUTG_REJ_PENDING)
7136 			    && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7137 			{
7138 				sig_req(plci, HANGUP, 0);
7139 				send_req(plci);
7140 				plci->State = OUTG_DIS_PENDING;
7141 			}
7142 		}
7143 		break;
7144 	case N_RESET:
7145 		a->ncci_state[ncci] = INC_RES_PENDING;
7146 		sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7147 		break;
7148 	case N_RESET_ACK:
7149 		a->ncci_state[ncci] = CONNECTED;
7150 		sendf(plci->appl, _RESET_B3_I, Id, 0, "S", plci->ncpi_buffer);
7151 		break;
7152 
7153 	case N_UDATA:
7154 		if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7155 		{
7156 			plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7157 			plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7158 			plci->NL.R = plci->RData;
7159 			plci->NL.RNum = 1;
7160 			return;
7161 		}
7162 	case N_BDATA:
7163 	case N_DATA:
7164 		if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7165 		    || (a->ncci_state[ncci] == IDLE)
7166 		    || (a->ncci_state[ncci] == INC_DIS_PENDING))
7167 		{
7168 			plci->NL.RNR = 2;
7169 			break;
7170 		}
7171 		if ((a->ncci_state[ncci] != CONNECTED)
7172 		    && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7173 		    && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7174 		{
7175 			dbug(1, dprintf("flow control"));
7176 			plci->NL.RNR = 1; /* flow control  */
7177 			channel_x_off(plci, ch, 0);
7178 			break;
7179 		}
7180 
7181 		NCCIcode = ncci | (((word)a->Id) << 8);
7182 
7183 		/* count all buffers within the Application pool    */
7184 		/* belonging to the same NCCI. If this is below the */
7185 		/* number of buffers available per NCCI we accept   */
7186 		/* this packet, otherwise we reject it              */
7187 		count = 0;
7188 		Num = 0xffff;
7189 		for (i = 0; i < APPLptr->MaxBuffer; i++) {
7190 			if (NCCIcode == APPLptr->DataNCCI[i]) count++;
7191 			if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
7192 		}
7193 
7194 		if (count >= APPLptr->MaxNCCIData || Num == 0xffff)
7195 		{
7196 			dbug(3, dprintf("Flow-Control"));
7197 			plci->NL.RNR = 1;
7198 			if (++(APPLptr->NCCIDataFlowCtrlTimer) >=
7199 			    (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7200 			{
7201 				plci->NL.RNR = 2;
7202 				dbug(3, dprintf("DiscardData"));
7203 			} else {
7204 				channel_x_off(plci, ch, 0);
7205 			}
7206 			break;
7207 		}
7208 		else
7209 		{
7210 			APPLptr->NCCIDataFlowCtrlTimer = 0;
7211 		}
7212 
7213 		plci->RData[0].P = ReceiveBufferGet(APPLptr, Num);
7214 		if (!plci->RData[0].P) {
7215 			plci->NL.RNR = 1;
7216 			channel_x_off(plci, ch, 0);
7217 			break;
7218 		}
7219 
7220 		APPLptr->DataNCCI[Num] = NCCIcode;
7221 		APPLptr->DataFlags[Num] = (plci->Id << 8) | (plci->NL.Ind >> 4);
7222 		dbug(3, dprintf("Buffer(%d), Max = %d", Num, APPLptr->MaxBuffer));
7223 
7224 		plci->RNum = Num;
7225 		plci->RFlags = plci->NL.Ind >> 4;
7226 		plci->RData[0].PLength = APPLptr->MaxDataLength;
7227 		plci->NL.R = plci->RData;
7228 		if ((plci->NL.RLength != 0)
7229 		    && ((plci->B2_prot == B2_V120_ASYNC)
7230 			|| (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7231 			|| (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7232 		{
7233 			plci->RData[1].P = plci->RData[0].P;
7234 			plci->RData[1].PLength = plci->RData[0].PLength;
7235 			plci->RData[0].P = v120_header_buffer + (-((unsigned long)v120_header_buffer) & 3);
7236 			if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7237 				plci->RData[0].PLength = 1;
7238 			else
7239 				plci->RData[0].PLength = 2;
7240 			if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7241 				plci->RFlags |= 0x0010;
7242 			if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7243 				plci->RFlags |= 0x8000;
7244 			plci->NL.RNum = 2;
7245 		}
7246 		else
7247 		{
7248 			if ((plci->NL.Ind & 0x0f) == N_UDATA)
7249 				plci->RFlags |= 0x0010;
7250 
7251 			else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7252 				plci->RFlags |= 0x0001;
7253 
7254 			plci->NL.RNum = 1;
7255 		}
7256 		break;
7257 	case N_DATA_ACK:
7258 		data_ack(plci, ch);
7259 		break;
7260 	default:
7261 		plci->NL.RNR = 2;
7262 		break;
7263 	}
7264 }
7265 
7266 /*------------------------------------------------------------------*/
7267 /* find a free PLCI */
7268 /*------------------------------------------------------------------*/
7269 
get_plci(DIVA_CAPI_ADAPTER * a)7270 static word get_plci(DIVA_CAPI_ADAPTER *a)
7271 {
7272 	word i, j;
7273 	PLCI *plci;
7274 
7275 	dump_plcis(a);
7276 	for (i = 0; i < a->max_plci && a->plci[i].Id; i++);
7277 	if (i == a->max_plci) {
7278 		dbug(1, dprintf("get_plci: out of PLCIs"));
7279 		return 0;
7280 	}
7281 	plci = &a->plci[i];
7282 	plci->Id = (byte)(i + 1);
7283 
7284 	plci->Sig.Id = 0;
7285 	plci->NL.Id = 0;
7286 	plci->sig_req = 0;
7287 	plci->nl_req = 0;
7288 
7289 	plci->appl = NULL;
7290 	plci->relatedPTYPLCI = NULL;
7291 	plci->State = IDLE;
7292 	plci->SuppState = IDLE;
7293 	plci->channels = 0;
7294 	plci->tel = 0;
7295 	plci->B1_resource = 0;
7296 	plci->B2_prot = 0;
7297 	plci->B3_prot = 0;
7298 
7299 	plci->command = 0;
7300 	plci->m_command = 0;
7301 	init_internal_command_queue(plci);
7302 	plci->number = 0;
7303 	plci->req_in_start = 0;
7304 	plci->req_in = 0;
7305 	plci->req_out = 0;
7306 	plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7307 	plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7308 	plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7309 
7310 	plci->data_sent = false;
7311 	plci->send_disc = 0;
7312 	plci->sig_global_req = 0;
7313 	plci->sig_remove_id = 0;
7314 	plci->nl_global_req = 0;
7315 	plci->nl_remove_id = 0;
7316 	plci->adv_nl = 0;
7317 	plci->manufacturer = false;
7318 	plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7319 	plci->spoofed_msg = 0;
7320 	plci->ptyState = 0;
7321 	plci->cr_enquiry = false;
7322 	plci->hangup_flow_ctrl_timer = 0;
7323 
7324 	plci->ncci_ring_list = 0;
7325 	for (j = 0; j < MAX_CHANNELS_PER_PLCI; j++) plci->inc_dis_ncci_table[j] = 0;
7326 	clear_c_ind_mask(plci);
7327 	set_group_ind_mask(plci);
7328 	plci->fax_connect_info_length = 0;
7329 	plci->nsf_control_bits = 0;
7330 	plci->ncpi_state = 0x00;
7331 	plci->ncpi_buffer[0] = 0;
7332 
7333 	plci->requested_options_conn = 0;
7334 	plci->requested_options = 0;
7335 	plci->notifiedcall = 0;
7336 	plci->vswitchstate = 0;
7337 	plci->vsprot = 0;
7338 	plci->vsprotdialect = 0;
7339 	init_b1_config(plci);
7340 	dbug(1, dprintf("get_plci(%x)", plci->Id));
7341 	return i + 1;
7342 }
7343 
7344 /*------------------------------------------------------------------*/
7345 /* put a parameter in the parameter buffer                          */
7346 /*------------------------------------------------------------------*/
7347 
add_p(PLCI * plci,byte code,byte * p)7348 static void add_p(PLCI *plci, byte code, byte *p)
7349 {
7350 	word p_length;
7351 
7352 	p_length = 0;
7353 	if (p) p_length = p[0];
7354 	add_ie(plci, code, p, p_length);
7355 }
7356 
7357 /*------------------------------------------------------------------*/
7358 /* put a structure in the parameter buffer                          */
7359 /*------------------------------------------------------------------*/
add_s(PLCI * plci,byte code,API_PARSE * p)7360 static void add_s(PLCI *plci, byte code, API_PARSE *p)
7361 {
7362 	if (p) add_ie(plci, code, p->info, (word)p->length);
7363 }
7364 
7365 /*------------------------------------------------------------------*/
7366 /* put multiple structures in the parameter buffer                  */
7367 /*------------------------------------------------------------------*/
add_ss(PLCI * plci,byte code,API_PARSE * p)7368 static void add_ss(PLCI *plci, byte code, API_PARSE *p)
7369 {
7370 	byte i;
7371 
7372 	if (p) {
7373 		dbug(1, dprintf("add_ss(%x,len=%d)", code, p->length));
7374 		for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7375 			dbug(1, dprintf("add_ss_ie(%x,len=%d)", p->info[i - 1], p->info[i]));
7376 			add_ie(plci, p->info[i - 1], (byte *)&(p->info[i]), (word)p->info[i]);
7377 		}
7378 	}
7379 }
7380 
7381 /*------------------------------------------------------------------*/
7382 /* return the channel number sent by the application in a esc_chi   */
7383 /*------------------------------------------------------------------*/
getChannel(API_PARSE * p)7384 static byte getChannel(API_PARSE *p)
7385 {
7386 	byte i;
7387 
7388 	if (p) {
7389 		for (i = 2; i < (byte)p->length; i += p->info[i] + 2) {
7390 			if (p->info[i] == 2) {
7391 				if (p->info[i - 1] == ESC && p->info[i + 1] == CHI) return (p->info[i + 2]);
7392 			}
7393 		}
7394 	}
7395 	return 0;
7396 }
7397 
7398 
7399 /*------------------------------------------------------------------*/
7400 /* put an information element in the parameter buffer               */
7401 /*------------------------------------------------------------------*/
7402 
add_ie(PLCI * plci,byte code,byte * p,word p_length)7403 static void add_ie(PLCI *plci, byte code, byte *p, word p_length)
7404 {
7405 	word i;
7406 
7407 	if (!(code & 0x80) && !p_length) return;
7408 
7409 	if (plci->req_in == plci->req_in_start) {
7410 		plci->req_in += 2;
7411 	}
7412 	else {
7413 		plci->req_in--;
7414 	}
7415 	plci->RBuffer[plci->req_in++] = code;
7416 
7417 	if (p) {
7418 		plci->RBuffer[plci->req_in++] = (byte)p_length;
7419 		for (i = 0; i < p_length; i++) plci->RBuffer[plci->req_in++] = p[1 + i];
7420 	}
7421 
7422 	plci->RBuffer[plci->req_in++] = 0;
7423 }
7424 
7425 /*------------------------------------------------------------------*/
7426 /* put a unstructured data into the buffer                          */
7427 /*------------------------------------------------------------------*/
7428 
add_d(PLCI * plci,word length,byte * p)7429 static void add_d(PLCI *plci, word length, byte *p)
7430 {
7431 	word i;
7432 
7433 	if (plci->req_in == plci->req_in_start) {
7434 		plci->req_in += 2;
7435 	}
7436 	else {
7437 		plci->req_in--;
7438 	}
7439 	for (i = 0; i < length; i++) plci->RBuffer[plci->req_in++] = p[i];
7440 }
7441 
7442 /*------------------------------------------------------------------*/
7443 /* put parameters from the Additional Info parameter in the         */
7444 /* parameter buffer                                                 */
7445 /*------------------------------------------------------------------*/
7446 
add_ai(PLCI * plci,API_PARSE * ai)7447 static void add_ai(PLCI *plci, API_PARSE *ai)
7448 {
7449 	word i;
7450 	API_PARSE ai_parms[5];
7451 
7452 	for (i = 0; i < 5; i++) ai_parms[i].length = 0;
7453 
7454 	if (!ai->length)
7455 		return;
7456 	if (api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7457 		return;
7458 
7459 	add_s(plci, KEY, &ai_parms[1]);
7460 	add_s(plci, UUI, &ai_parms[2]);
7461 	add_ss(plci, FTY, &ai_parms[3]);
7462 }
7463 
7464 /*------------------------------------------------------------------*/
7465 /* put parameter for b1 protocol in the parameter buffer            */
7466 /*------------------------------------------------------------------*/
7467 
add_b1(PLCI * plci,API_PARSE * bp,word b_channel_info,word b1_facilities)7468 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7469 		   word b1_facilities)
7470 {
7471 	API_PARSE bp_parms[8];
7472 	API_PARSE mdm_cfg[9];
7473 	API_PARSE global_config[2];
7474 	byte cai[256];
7475 	byte resource[] = {5, 9, 13, 12, 16, 39, 9, 17, 17, 18};
7476 	byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7477 	word i;
7478 
7479 	API_PARSE mdm_cfg_v18[4];
7480 	word j, n, w;
7481 	dword d;
7482 
7483 
7484 	for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7485 	for (i = 0; i < 2; i++) global_config[i].length = 0;
7486 
7487 	dbug(1, dprintf("add_b1"));
7488 	api_save_msg(bp, "s", &plci->B_protocol);
7489 
7490 	if (b_channel_info == 2) {
7491 		plci->B1_resource = 0;
7492 		adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7493 		add_p(plci, CAI, "\x01\x00");
7494 		dbug(1, dprintf("Cai=1,0 (no resource)"));
7495 		return 0;
7496 	}
7497 
7498 	if (plci->tel == CODEC_PERMANENT) return 0;
7499 	else if (plci->tel == CODEC) {
7500 		plci->B1_resource = 1;
7501 		adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7502 		add_p(plci, CAI, "\x01\x01");
7503 		dbug(1, dprintf("Cai=1,1 (Codec)"));
7504 		return 0;
7505 	}
7506 	else if (plci->tel == ADV_VOICE) {
7507 		plci->B1_resource = add_b1_facilities(plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7508 		adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7509 		voice_cai[1] = plci->B1_resource;
7510 		PUT_WORD(&voice_cai[5], plci->appl->MaxDataLength);
7511 		add_p(plci, CAI, voice_cai);
7512 		dbug(1, dprintf("Cai=1,0x%x (AdvVoice)", voice_cai[1]));
7513 		return 0;
7514 	}
7515 	plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7516 	if (plci->call_dir & CALL_DIR_OUT)
7517 		plci->call_dir |= CALL_DIR_ORIGINATE;
7518 	else if (plci->call_dir & CALL_DIR_IN)
7519 		plci->call_dir |= CALL_DIR_ANSWER;
7520 
7521 	if (!bp->length) {
7522 		plci->B1_resource = 0x5;
7523 		adjust_b1_facilities(plci, plci->B1_resource, b1_facilities);
7524 		add_p(plci, CAI, "\x01\x05");
7525 		return 0;
7526 	}
7527 
7528 	dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
7529 	if (bp->length > 256) return _WRONG_MESSAGE_FORMAT;
7530 	if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7531 	{
7532 		bp_parms[6].length = 0;
7533 		if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7534 		{
7535 			dbug(1, dprintf("b-form.!"));
7536 			return _WRONG_MESSAGE_FORMAT;
7537 		}
7538 	}
7539 	else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7540 	{
7541 		dbug(1, dprintf("b-form.!"));
7542 		return _WRONG_MESSAGE_FORMAT;
7543 	}
7544 
7545 	if (bp_parms[6].length)
7546 	{
7547 		if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7548 		{
7549 			return _WRONG_MESSAGE_FORMAT;
7550 		}
7551 		switch (GET_WORD(global_config[0].info))
7552 		{
7553 		case 1:
7554 			plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7555 			break;
7556 		case 2:
7557 			plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7558 			break;
7559 		}
7560 	}
7561 	dbug(1, dprintf("call_dir=%04x", plci->call_dir));
7562 
7563 
7564 	if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7565 	    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7566 	{
7567 		plci->B1_resource = add_b1_facilities(plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7568 		adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7569 		cai[1] = plci->B1_resource;
7570 		cai[2] = 0;
7571 		cai[3] = 0;
7572 		cai[4] = 0;
7573 		PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7574 		for (i = 0; i < bp_parms[3].length; i++)
7575 			cai[7 + i] = bp_parms[3].info[1 + i];
7576 		cai[0] = 6 + bp_parms[3].length;
7577 		add_p(plci, CAI, cai);
7578 		return 0;
7579 	}
7580 
7581 
7582 	if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7583 	    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7584 	{
7585 		plci->B1_resource = add_b1_facilities(plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7586 		adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7587 		cai[1] = plci->B1_resource;
7588 		cai[2] = 0;
7589 		cai[3] = 0;
7590 		cai[4] = 0;
7591 		PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7592 		cai[0] = 6;
7593 		add_p(plci, CAI, cai);
7594 		return 0;
7595 	}
7596 
7597 
7598 	if ((GET_WORD(bp_parms[0].info) >= 32)
7599 	    || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7600 		&& ((GET_WORD(bp_parms[0].info) != 3)
7601 		    || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7602 		    || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7603 	{
7604 		return _B1_NOT_SUPPORTED;
7605 	}
7606 	plci->B1_resource = add_b1_facilities(plci, resource[GET_WORD(bp_parms[0].info)],
7607 					      (word)(b1_facilities & ~B1_FACILITY_VOICE));
7608 	adjust_b1_facilities(plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7609 	cai[0] = 6;
7610 	cai[1] = plci->B1_resource;
7611 	for (i = 2; i < sizeof(cai); i++) cai[i] = 0;
7612 
7613 	if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7614 	    || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7615 	    || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7616 	{ /* B1 - modem */
7617 		for (i = 0; i < 7; i++) mdm_cfg[i].length = 0;
7618 
7619 		if (bp_parms[3].length)
7620 		{
7621 			if (api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwww", mdm_cfg))
7622 			{
7623 				return (_WRONG_MESSAGE_FORMAT);
7624 			}
7625 
7626 			cai[2] = 0; /* Bit rate for adaptation */
7627 
7628 			dbug(1, dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7629 
7630 			PUT_WORD(&cai[13], 0);                          /* Min Tx speed */
7631 			PUT_WORD(&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7632 			PUT_WORD(&cai[17], 0);                          /* Min Rx speed */
7633 			PUT_WORD(&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7634 
7635 			cai[3] = 0; /* Async framing parameters */
7636 			switch (GET_WORD(mdm_cfg[2].info))
7637 			{       /* Parity     */
7638 			case 1: /* odd parity */
7639 				cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7640 				dbug(1, dprintf("MDM: odd parity"));
7641 				break;
7642 
7643 			case 2: /* even parity */
7644 				cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7645 				dbug(1, dprintf("MDM: even parity"));
7646 				break;
7647 
7648 			default:
7649 				dbug(1, dprintf("MDM: no parity"));
7650 				break;
7651 			}
7652 
7653 			switch (GET_WORD(mdm_cfg[3].info))
7654 			{       /* stop bits   */
7655 			case 1: /* 2 stop bits */
7656 				cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7657 				dbug(1, dprintf("MDM: 2 stop bits"));
7658 				break;
7659 
7660 			default:
7661 				dbug(1, dprintf("MDM: 1 stop bit"));
7662 				break;
7663 			}
7664 
7665 			switch (GET_WORD(mdm_cfg[1].info))
7666 			{     /* char length */
7667 			case 5:
7668 				cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7669 				dbug(1, dprintf("MDM: 5 bits"));
7670 				break;
7671 
7672 			case 6:
7673 				cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7674 				dbug(1, dprintf("MDM: 6 bits"));
7675 				break;
7676 
7677 			case 7:
7678 				cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7679 				dbug(1, dprintf("MDM: 7 bits"));
7680 				break;
7681 
7682 			default:
7683 				dbug(1, dprintf("MDM: 8 bits"));
7684 				break;
7685 			}
7686 
7687 			cai[7] = 0; /* Line taking options */
7688 			cai[8] = 0; /* Modulation negotiation options */
7689 			cai[9] = 0; /* Modulation options */
7690 
7691 			if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7692 			{
7693 				cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7694 				dbug(1, dprintf("MDM: Reverse direction"));
7695 			}
7696 
7697 			if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7698 			{
7699 				cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7700 				dbug(1, dprintf("MDM: Disable retrain"));
7701 			}
7702 
7703 			if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7704 			{
7705 				cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7706 				dbug(1, dprintf("MDM: Disable ring tone"));
7707 			}
7708 
7709 			if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7710 			{
7711 				cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7712 				dbug(1, dprintf("MDM: 1800 guard tone"));
7713 			}
7714 			else if (GET_WORD(mdm_cfg[4].info) & MDM_CAPI_GUARD_550)
7715 			{
7716 				cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7717 				dbug(1, dprintf("MDM: 550 guard tone"));
7718 			}
7719 
7720 			if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7721 			{
7722 				cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7723 				dbug(1, dprintf("MDM: V100"));
7724 			}
7725 			else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7726 			{
7727 				cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7728 				dbug(1, dprintf("MDM: IN CLASS"));
7729 			}
7730 			else if ((GET_WORD(mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7731 			{
7732 				cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7733 				dbug(1, dprintf("MDM: DISABLED"));
7734 			}
7735 			cai[0] = 20;
7736 
7737 			if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7738 			    && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7739 			{
7740 				plci->requested_options |= 1L << PRIVATE_V18;
7741 			}
7742 			if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7743 				plci->requested_options |= 1L << PRIVATE_VOWN;
7744 
7745 			if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
7746 			    & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7747 			{
7748 				if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwws", mdm_cfg))
7749 				{
7750 					i = 27;
7751 					if (mdm_cfg[6].length >= 4)
7752 					{
7753 						d = GET_DWORD(&mdm_cfg[6].info[1]);
7754 						cai[7] |= (byte) d;          /* line taking options */
7755 						cai[9] |= (byte)(d >> 8);    /* modulation options */
7756 						cai[++i] = (byte)(d >> 16);  /* vown modulation options */
7757 						cai[++i] = (byte)(d >> 24);
7758 						if (mdm_cfg[6].length >= 8)
7759 						{
7760 							d = GET_DWORD(&mdm_cfg[6].info[5]);
7761 							cai[10] |= (byte) d;        /* disabled modulations mask */
7762 							cai[11] |= (byte)(d >> 8);
7763 							if (mdm_cfg[6].length >= 12)
7764 							{
7765 								d = GET_DWORD(&mdm_cfg[6].info[9]);
7766 								cai[12] = (byte) d;          /* enabled modulations mask */
7767 								cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */
7768 								cai[++i] = (byte)(d >> 16);
7769 								cai[++i] = (byte)(d >> 24);
7770 								cai[++i] = 0;
7771 								if (mdm_cfg[6].length >= 14)
7772 								{
7773 									w = GET_WORD(&mdm_cfg[6].info[13]);
7774 									if (w != 0)
7775 										PUT_WORD(&cai[13], w);  /* min tx speed */
7776 									if (mdm_cfg[6].length >= 16)
7777 									{
7778 										w = GET_WORD(&mdm_cfg[6].info[15]);
7779 										if (w != 0)
7780 											PUT_WORD(&cai[15], w);  /* max tx speed */
7781 										if (mdm_cfg[6].length >= 18)
7782 										{
7783 											w = GET_WORD(&mdm_cfg[6].info[17]);
7784 											if (w != 0)
7785 												PUT_WORD(&cai[17], w);  /* min rx speed */
7786 											if (mdm_cfg[6].length >= 20)
7787 											{
7788 												w = GET_WORD(&mdm_cfg[6].info[19]);
7789 												if (w != 0)
7790 													PUT_WORD(&cai[19], w);  /* max rx speed */
7791 												if (mdm_cfg[6].length >= 22)
7792 												{
7793 													w = GET_WORD(&mdm_cfg[6].info[21]);
7794 													cai[23] = (byte)(-((short) w));  /* transmit level */
7795 													if (mdm_cfg[6].length >= 24)
7796 													{
7797 														w = GET_WORD(&mdm_cfg[6].info[23]);
7798 														cai[22] |= (byte) w;        /* info options mask */
7799 														cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */
7800 													}
7801 												}
7802 											}
7803 										}
7804 									}
7805 								}
7806 							}
7807 						}
7808 					}
7809 					cai[27] = i - 27;
7810 					i++;
7811 					if (!api_parse(&bp_parms[3].info[1], (word)bp_parms[3].length, "wwwwwwss", mdm_cfg))
7812 					{
7813 						if (!api_parse(&mdm_cfg[7].info[1], (word)mdm_cfg[7].length, "sss", mdm_cfg_v18))
7814 						{
7815 							for (n = 0; n < 3; n++)
7816 							{
7817 								cai[i] = (byte)(mdm_cfg_v18[n].length);
7818 								for (j = 1; j < ((word)(cai[i] + 1)); j++)
7819 									cai[i + j] = mdm_cfg_v18[n].info[j];
7820 								i += cai[i] + 1;
7821 							}
7822 						}
7823 					}
7824 					cai[0] = (byte)(i - 1);
7825 				}
7826 			}
7827 
7828 		}
7829 	}
7830 	if (GET_WORD(bp_parms[0].info) == 2 ||                         /* V.110 async */
7831 	    GET_WORD(bp_parms[0].info) == 3)                           /* V.110 sync */
7832 	{
7833 		if (bp_parms[3].length) {
7834 			dbug(1, dprintf("V.110,%d", GET_WORD(&bp_parms[3].info[1])));
7835 			switch (GET_WORD(&bp_parms[3].info[1])) {                 /* Rate */
7836 			case 0:
7837 			case 56000:
7838 				if (GET_WORD(bp_parms[0].info) == 3) {                  /* V.110 sync 56k */
7839 					dbug(1, dprintf("56k sync HSCX"));
7840 					cai[1] = 8;
7841 					cai[2] = 0;
7842 					cai[3] = 0;
7843 				}
7844 				else if (GET_WORD(bp_parms[0].info) == 2) {
7845 					dbug(1, dprintf("56k async DSP"));
7846 					cai[2] = 9;
7847 				}
7848 				break;
7849 			case 50:     cai[2] = 1;  break;
7850 			case 75:     cai[2] = 1;  break;
7851 			case 110:    cai[2] = 1;  break;
7852 			case 150:    cai[2] = 1;  break;
7853 			case 200:    cai[2] = 1;  break;
7854 			case 300:    cai[2] = 1;  break;
7855 			case 600:    cai[2] = 1;  break;
7856 			case 1200:   cai[2] = 2;  break;
7857 			case 2400:   cai[2] = 3;  break;
7858 			case 4800:   cai[2] = 4;  break;
7859 			case 7200:   cai[2] = 10; break;
7860 			case 9600:   cai[2] = 5;  break;
7861 			case 12000:  cai[2] = 13; break;
7862 			case 24000:  cai[2] = 0;  break;
7863 			case 14400:  cai[2] = 11; break;
7864 			case 19200:  cai[2] = 6;  break;
7865 			case 28800:  cai[2] = 12; break;
7866 			case 38400:  cai[2] = 7;  break;
7867 			case 48000:  cai[2] = 8;  break;
7868 			case 76:     cai[2] = 15; break;  /* 75/1200     */
7869 			case 1201:   cai[2] = 14; break;  /* 1200/75     */
7870 			case 56001:  cai[2] = 9;  break;  /* V.110 56000 */
7871 
7872 			default:
7873 				return _B1_PARM_NOT_SUPPORTED;
7874 			}
7875 			cai[3] = 0;
7876 			if (cai[1] == 13)                                        /* v.110 async */
7877 			{
7878 				if (bp_parms[3].length >= 8)
7879 				{
7880 					switch (GET_WORD(&bp_parms[3].info[3]))
7881 					{       /* char length */
7882 					case 5:
7883 						cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7884 						break;
7885 					case 6:
7886 						cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7887 						break;
7888 					case 7:
7889 						cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7890 						break;
7891 					}
7892 					switch (GET_WORD(&bp_parms[3].info[5]))
7893 					{       /* Parity     */
7894 					case 1: /* odd parity */
7895 						cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7896 						break;
7897 					case 2: /* even parity */
7898 						cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7899 						break;
7900 					}
7901 					switch (GET_WORD(&bp_parms[3].info[7]))
7902 					{       /* stop bits   */
7903 					case 1: /* 2 stop bits */
7904 						cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7905 						break;
7906 					}
7907 				}
7908 			}
7909 		}
7910 		else if (cai[1] == 8 || GET_WORD(bp_parms[0].info) == 3) {
7911 			dbug(1, dprintf("V.110 default 56k sync"));
7912 			cai[1] = 8;
7913 			cai[2] = 0;
7914 			cai[3] = 0;
7915 		}
7916 		else {
7917 			dbug(1, dprintf("V.110 default 9600 async"));
7918 			cai[2] = 5;
7919 		}
7920 	}
7921 	PUT_WORD(&cai[5], plci->appl->MaxDataLength);
7922 	dbug(1, dprintf("CAI[%d]=%x,%x,%x,%x,%x,%x", cai[0], cai[1], cai[2], cai[3], cai[4], cai[5], cai[6]));
7923 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7924 
7925 	add_p(plci, CAI, cai);
7926 	return 0;
7927 }
7928 
7929 /*------------------------------------------------------------------*/
7930 /* put parameter for b2 and B3  protocol in the parameter buffer    */
7931 /*------------------------------------------------------------------*/
7932 
add_b23(PLCI * plci,API_PARSE * bp)7933 static word add_b23(PLCI *plci, API_PARSE *bp)
7934 {
7935 	word i, fax_control_bits;
7936 	byte pos, len;
7937 	byte SAPI = 0x40;  /* default SAPI 16 for x.31 */
7938 	API_PARSE bp_parms[8];
7939 	API_PARSE *b1_config;
7940 	API_PARSE *b2_config;
7941 	API_PARSE b2_config_parms[8];
7942 	API_PARSE *b3_config;
7943 	API_PARSE b3_config_parms[6];
7944 	API_PARSE global_config[2];
7945 
7946 	static byte llc[3] = {2,0,0};
7947 	static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7948 	static byte nlc[256];
7949 	static byte lli[12] = {1,1};
7950 
7951 	const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7952 	const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7953 
7954 	const byte llc3[] = {4,3,2,2,6,6,0};
7955 	const byte header[] = {0,2,3,3,0,0,0};
7956 
7957 	for (i = 0; i < 8; i++) bp_parms[i].length = 0;
7958 	for (i = 0; i < 6; i++) b2_config_parms[i].length = 0;
7959 	for (i = 0; i < 5; i++) b3_config_parms[i].length = 0;
7960 
7961 	lli[0] = 1;
7962 	lli[1] = 1;
7963 	if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7964 		lli[1] |= 2;
7965 	if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7966 		lli[1] |= 4;
7967 
7968 	if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7969 		lli[1] |= 0x10;
7970 		if (plci->rx_dma_descriptor <= 0) {
7971 			plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
7972 			if (plci->rx_dma_descriptor >= 0)
7973 				plci->rx_dma_descriptor++;
7974 		}
7975 		if (plci->rx_dma_descriptor > 0) {
7976 			lli[0] = 6;
7977 			lli[1] |= 0x40;
7978 			lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7979 			lli[3] = (byte)plci->rx_dma_magic;
7980 			lli[4] = (byte)(plci->rx_dma_magic >>  8);
7981 			lli[5] = (byte)(plci->rx_dma_magic >> 16);
7982 			lli[6] = (byte)(plci->rx_dma_magic >> 24);
7983 		}
7984 	}
7985 
7986 	if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7987 		lli[1] |= 0x20;
7988 	}
7989 
7990 	dbug(1, dprintf("add_b23"));
7991 	api_save_msg(bp, "s", &plci->B_protocol);
7992 
7993 	if (!bp->length && plci->tel)
7994 	{
7995 		plci->adv_nl = true;
7996 		dbug(1, dprintf("Default adv.Nl"));
7997 		add_p(plci, LLI, lli);
7998 		plci->B2_prot = 1 /*XPARENT*/;
7999 		plci->B3_prot = 0 /*XPARENT*/;
8000 		llc[1] = 2;
8001 		llc[2] = 4;
8002 		add_p(plci, LLC, llc);
8003 		dlc[0] = 2;
8004 		PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8005 		add_p(plci, DLC, dlc);
8006 		return 0;
8007 	}
8008 
8009 	if (!bp->length) /*default*/
8010 	{
8011 		dbug(1, dprintf("ret default"));
8012 		add_p(plci, LLI, lli);
8013 		plci->B2_prot = 0 /*X.75   */;
8014 		plci->B3_prot = 0 /*XPARENT*/;
8015 		llc[1] = 1;
8016 		llc[2] = 4;
8017 		add_p(plci, LLC, llc);
8018 		dlc[0] = 2;
8019 		PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8020 		add_p(plci, DLC, dlc);
8021 		return 0;
8022 	}
8023 	dbug(1, dprintf("b_prot_len=%d", (word)bp->length));
8024 	if ((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT;
8025 
8026 	if (api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8027 	{
8028 		bp_parms[6].length = 0;
8029 		if (api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8030 		{
8031 			dbug(1, dprintf("b-form.!"));
8032 			return _WRONG_MESSAGE_FORMAT;
8033 		}
8034 	}
8035 	else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8036 	{
8037 		dbug(1, dprintf("b-form.!"));
8038 		return _WRONG_MESSAGE_FORMAT;
8039 	}
8040 
8041 	if (plci->tel == ADV_VOICE) /* transparent B on advanced voice */
8042 	{
8043 		if (GET_WORD(bp_parms[1].info) != 1
8044 		    || GET_WORD(bp_parms[2].info) != 0) return _B2_NOT_SUPPORTED;
8045 		plci->adv_nl = true;
8046 	}
8047 	else if (plci->tel) return _B2_NOT_SUPPORTED;
8048 
8049 
8050 	if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8051 	    && (GET_WORD(bp_parms[2].info) == B3_RTP)
8052 	    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8053 	{
8054 		add_p(plci, LLI, lli);
8055 		plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8056 		plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8057 		llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8058 		llc[2] = 4;
8059 		add_p(plci, LLC, llc);
8060 		dlc[0] = 2;
8061 		PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8062 		dlc[3] = 3; /* Addr A */
8063 		dlc[4] = 1; /* Addr B */
8064 		dlc[5] = 7; /* modulo mode */
8065 		dlc[6] = 7; /* window size */
8066 		dlc[7] = 0; /* XID len Lo  */
8067 		dlc[8] = 0; /* XID len Hi  */
8068 		for (i = 0; i < bp_parms[4].length; i++)
8069 			dlc[9 + i] = bp_parms[4].info[1 + i];
8070 		dlc[0] = (byte)(8 + bp_parms[4].length);
8071 		add_p(plci, DLC, dlc);
8072 		for (i = 0; i < bp_parms[5].length; i++)
8073 			nlc[1 + i] = bp_parms[5].info[1 + i];
8074 		nlc[0] = (byte)(bp_parms[5].length);
8075 		add_p(plci, NLC, nlc);
8076 		return 0;
8077 	}
8078 
8079 
8080 
8081 	if ((GET_WORD(bp_parms[1].info) >= 32)
8082 	    || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8083 		&& ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8084 		    || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8085 
8086 	{
8087 		return _B2_NOT_SUPPORTED;
8088 	}
8089 	if ((GET_WORD(bp_parms[2].info) >= 32)
8090 	    || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8091 	{
8092 		return _B3_NOT_SUPPORTED;
8093 	}
8094 	if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8095 	    && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8096 		|| (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8097 		|| (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8098 	{
8099 		return (add_modem_b23(plci, bp_parms));
8100 	}
8101 
8102 	add_p(plci, LLI, lli);
8103 
8104 	plci->B2_prot = (byte)GET_WORD(bp_parms[1].info);
8105 	plci->B3_prot = (byte)GET_WORD(bp_parms[2].info);
8106 	if (plci->B2_prot == 12) SAPI = 0; /* default SAPI D-channel */
8107 
8108 	if (bp_parms[6].length)
8109 	{
8110 		if (api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8111 		{
8112 			return _WRONG_MESSAGE_FORMAT;
8113 		}
8114 		switch (GET_WORD(global_config[0].info))
8115 		{
8116 		case 1:
8117 			plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8118 			break;
8119 		case 2:
8120 			plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8121 			break;
8122 		}
8123 	}
8124 	dbug(1, dprintf("call_dir=%04x", plci->call_dir));
8125 
8126 
8127 	if (plci->B2_prot == B2_PIAFS)
8128 		llc[1] = PIAFS_CRC;
8129 	else
8130 /* IMPLEMENT_PIAFS */
8131 	{
8132 		llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8133 			llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8134 	}
8135 	llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8136 
8137 	add_p(plci, LLC, llc);
8138 
8139 	dlc[0] = 2;
8140 	PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8141 		 header[GET_WORD(bp_parms[2].info)]);
8142 
8143 	b1_config = &bp_parms[3];
8144 	nlc[0] = 0;
8145 	if (plci->B3_prot == 4
8146 	    || plci->B3_prot == 5)
8147 	{
8148 		for (i = 0; i < sizeof(T30_INFO); i++) nlc[i] = 0;
8149 		nlc[0] = sizeof(T30_INFO);
8150 		if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8151 			((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8152 		((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8153 		if (b1_config->length >= 2)
8154 		{
8155 			((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1]) / 2400);
8156 		}
8157 	}
8158 	b2_config = &bp_parms[4];
8159 
8160 
8161 	if (llc[1] == PIAFS_CRC)
8162 	{
8163 		if (plci->B3_prot != B3_TRANSPARENT)
8164 		{
8165 			return _B_STACK_NOT_SUPPORTED;
8166 		}
8167 		if (b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8168 			return _WRONG_MESSAGE_FORMAT;
8169 		}
8170 		PUT_WORD(&dlc[1], plci->appl->MaxDataLength);
8171 		dlc[3] = 0; /* Addr A */
8172 		dlc[4] = 0; /* Addr B */
8173 		dlc[5] = 0; /* modulo mode */
8174 		dlc[6] = 0; /* window size */
8175 		if (b2_config->length >= 7) {
8176 			dlc[7] = 7;
8177 			dlc[8] = 0;
8178 			dlc[9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8179 			dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8180 			dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8181 			dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8182 			dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8183 			dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8184 			dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8185 			dlc[0] = 15;
8186 			if (b2_config->length >= 8) { /* PIAFS control abilities */
8187 				dlc[7] = 10;
8188 				dlc[16] = 2; /* Length of PIAFS extension */
8189 				dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8190 				dlc[18] = b2_config_parms[4].info[0]; /* value */
8191 				dlc[0] = 18;
8192 			}
8193 		}
8194 		else /* default values, 64K, variable, no compression */
8195 		{
8196 			dlc[7] = 7;
8197 			dlc[8] = 0;
8198 			dlc[9] = 0x03; /* PIAFS protocol Speed configuration */
8199 			dlc[10] = 0x03; /* V.42bis P0 */
8200 			dlc[11] = 0;    /* V.42bis P0 */
8201 			dlc[12] = 0;    /* V.42bis P1 */
8202 			dlc[13] = 0;    /* V.42bis P1 */
8203 			dlc[14] = 0;    /* V.42bis P2 */
8204 			dlc[15] = 0;    /* V.42bis P2 */
8205 			dlc[0] = 15;
8206 		}
8207 		add_p(plci, DLC, dlc);
8208 	}
8209 	else
8210 
8211 		if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8212 		{
8213 			if (plci->B3_prot != B3_TRANSPARENT)
8214 				return _B_STACK_NOT_SUPPORTED;
8215 
8216 			dlc[0] = 6;
8217 			PUT_WORD(&dlc[1], GET_WORD(&dlc[1]) + 2);
8218 			dlc[3] = 0x08;
8219 			dlc[4] = 0x01;
8220 			dlc[5] = 127;
8221 			dlc[6] = 7;
8222 			if (b2_config->length != 0)
8223 			{
8224 				if ((llc[1] == V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8225 					return _WRONG_MESSAGE_FORMAT;
8226 				}
8227 				dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8228 				dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8229 				if (b2_config->info[3] != 128)
8230 				{
8231 					dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8232 					return _B2_PARM_NOT_SUPPORTED;
8233 				}
8234 				dlc[5] = (byte)(b2_config->info[3] - 1);
8235 				dlc[6] = b2_config->info[4];
8236 				if (llc[1] == V120_V42BIS) {
8237 					if (b2_config->length >= 10) {
8238 						dlc[7] = 6;
8239 						dlc[8] = 0;
8240 						dlc[9] = b2_config_parms[4].info[0];
8241 						dlc[10] = b2_config_parms[4].info[1];
8242 						dlc[11] = b2_config_parms[5].info[0];
8243 						dlc[12] = b2_config_parms[5].info[1];
8244 						dlc[13] = b2_config_parms[6].info[0];
8245 						dlc[14] = b2_config_parms[6].info[1];
8246 						dlc[0] = 14;
8247 						dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8248 						dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8249 						dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8250 					}
8251 					else {
8252 						dlc[6] = 14;
8253 					}
8254 				}
8255 			}
8256 		}
8257 		else
8258 		{
8259 			if (b2_config->length)
8260 			{
8261 				dbug(1, dprintf("B2-Config"));
8262 				if (llc[1] == X75_V42BIS) {
8263 					if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8264 					{
8265 						return _WRONG_MESSAGE_FORMAT;
8266 					}
8267 				}
8268 				else {
8269 					if (api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8270 					{
8271 						return _WRONG_MESSAGE_FORMAT;
8272 					}
8273 				}
8274 				/* if B2 Protocol is LAPD, b2_config structure is different */
8275 				if (llc[1] == 6)
8276 				{
8277 					dlc[0] = 4;
8278 					if (b2_config->length >= 1) dlc[2] = b2_config->info[1];      /* TEI */
8279 					else dlc[2] = 0x01;
8280 					if ((b2_config->length >= 2) && (plci->B2_prot == 12))
8281 					{
8282 						SAPI = b2_config->info[2];    /* SAPI */
8283 					}
8284 					dlc[1] = SAPI;
8285 					if ((b2_config->length >= 3) && (b2_config->info[3] == 128))
8286 					{
8287 						dlc[3] = 127;      /* Mode */
8288 					}
8289 					else
8290 					{
8291 						dlc[3] = 7;        /* Mode */
8292 					}
8293 
8294 					if (b2_config->length >= 4) dlc[4] = b2_config->info[4];      /* Window */
8295 					else dlc[4] = 1;
8296 					dbug(1, dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8297 					if (b2_config->length > 5) return _B2_PARM_NOT_SUPPORTED;
8298 				}
8299 				else
8300 				{
8301 					dlc[0] = (byte)(b2_config_parms[4].length + 6);
8302 					dlc[3] = b2_config->info[1];
8303 					dlc[4] = b2_config->info[2];
8304 					if (b2_config->info[3] != 8 && b2_config->info[3] != 128) {
8305 						dbug(1, dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8306 						return _B2_PARM_NOT_SUPPORTED;
8307 					}
8308 
8309 					dlc[5] = (byte)(b2_config->info[3] - 1);
8310 					dlc[6] = b2_config->info[4];
8311 					if (dlc[6] > dlc[5]) {
8312 						dbug(1, dprintf("2D-dlc= %x %x %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4], dlc[5], dlc[6]));
8313 						return _B2_PARM_NOT_SUPPORTED;
8314 					}
8315 
8316 					if (llc[1] == X75_V42BIS) {
8317 						if (b2_config->length >= 10) {
8318 							dlc[7] = 6;
8319 							dlc[8] = 0;
8320 							dlc[9] = b2_config_parms[4].info[0];
8321 							dlc[10] = b2_config_parms[4].info[1];
8322 							dlc[11] = b2_config_parms[5].info[0];
8323 							dlc[12] = b2_config_parms[5].info[1];
8324 							dlc[13] = b2_config_parms[6].info[0];
8325 							dlc[14] = b2_config_parms[6].info[1];
8326 							dlc[0] = 14;
8327 							dbug(1, dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8328 							dbug(1, dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8329 							dbug(1, dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8330 						}
8331 						else {
8332 							dlc[6] = 14;
8333 						}
8334 
8335 					}
8336 					else {
8337 						PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8338 						for (i = 0; i < b2_config_parms[4].length; i++)
8339 							dlc[11 + i] = b2_config_parms[4].info[1 + i];
8340 					}
8341 				}
8342 			}
8343 		}
8344 	add_p(plci, DLC, dlc);
8345 
8346 	b3_config = &bp_parms[5];
8347 	if (b3_config->length)
8348 	{
8349 		if (plci->B3_prot == 4
8350 		    || plci->B3_prot == 5)
8351 		{
8352 			if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8353 			{
8354 				return _WRONG_MESSAGE_FORMAT;
8355 			}
8356 			i = GET_WORD((byte *)(b3_config_parms[0].info));
8357 			((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8358 								    ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8359 			((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte *)b3_config_parms[1].info));
8360 			fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8361 			if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8362 				fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8363 			if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8364 			{
8365 
8366 				if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8367 				    & (1L << PRIVATE_FAX_PAPER_FORMATS))
8368 				{
8369 					((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8370 						T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8371 						T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8372 				}
8373 
8374 				((T30_INFO *)&nlc[1])->recording_properties =
8375 					T30_RECORDING_WIDTH_ISO_A3 |
8376 					(T30_RECORDING_LENGTH_UNLIMITED << 2) |
8377 					(T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8378 			}
8379 			if (plci->B3_prot == 5)
8380 			{
8381 				if (i & 0x0002) /* Accept incoming fax-polling requests */
8382 					fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8383 				if (i & 0x2000) /* Do not use MR compression */
8384 					fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8385 				if (i & 0x4000) /* Do not use MMR compression */
8386 					fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8387 				if (i & 0x8000) /* Do not use ECM */
8388 					fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8389 				if (plci->fax_connect_info_length != 0)
8390 				{
8391 					((T30_INFO *)&nlc[1])->resolution = ((T30_INFO *)plci->fax_connect_info_buffer)->resolution;
8392 					((T30_INFO *)&nlc[1])->data_format = ((T30_INFO *)plci->fax_connect_info_buffer)->data_format;
8393 					((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO *)plci->fax_connect_info_buffer)->recording_properties;
8394 					fax_control_bits |= GET_WORD(&((T30_INFO *)plci->fax_connect_info_buffer)->control_bits_low) &
8395 						(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8396 				}
8397 			}
8398 			/* copy station id to NLC */
8399 			for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
8400 			{
8401 				if (i < b3_config_parms[2].length)
8402 				{
8403 					((T30_INFO *)&nlc[1])->station_id[i] = ((byte *)b3_config_parms[2].info)[1 + i];
8404 				}
8405 				else
8406 				{
8407 					((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8408 				}
8409 			}
8410 			((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
8411 			/* copy head line to NLC */
8412 			if (b3_config_parms[3].length)
8413 			{
8414 
8415 				pos = (byte)(fax_head_line_time(&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
8416 				if (pos != 0)
8417 				{
8418 					if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8419 						pos = 0;
8420 					else
8421 					{
8422 						nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8423 						nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8424 						len = (byte)b3_config_parms[2].length;
8425 						if (len > 20)
8426 							len = 20;
8427 						if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8428 						{
8429 							for (i = 0; i < len; i++)
8430 								nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1 + i];
8431 							nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8432 							nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
8433 						}
8434 					}
8435 				}
8436 
8437 				len = (byte)b3_config_parms[3].length;
8438 				if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8439 					len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8440 				((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8441 				nlc[0] += (byte)(pos + len);
8442 				for (i = 0; i < len; i++)
8443 					nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] =  ((byte *)b3_config_parms[3].info)[1 + i];
8444 			} else
8445 				((T30_INFO *)&nlc[1])->head_line_len = 0;
8446 
8447 			plci->nsf_control_bits = 0;
8448 			if (plci->B3_prot == 5)
8449 			{
8450 				if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8451 				    && (GET_WORD((byte *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8452 				{
8453 					plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8454 				}
8455 				if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8456 				    && (GET_WORD((byte *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8457 				{
8458 					plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8459 				}
8460 				if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8461 				    & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8462 				{
8463 					if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8464 					    & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8465 					{
8466 						fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8467 						if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8468 							fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8469 					}
8470 					len = nlc[0];
8471 					pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8472 					if (pos < plci->fax_connect_info_length)
8473 					{
8474 						for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8475 							nlc[++len] = plci->fax_connect_info_buffer[pos++];
8476 					}
8477 					else
8478 						nlc[++len] = 0;
8479 					if (pos < plci->fax_connect_info_length)
8480 					{
8481 						for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8482 							nlc[++len] = plci->fax_connect_info_buffer[pos++];
8483 					}
8484 					else
8485 						nlc[++len] = 0;
8486 					if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id - 1])
8487 					    & (1L << PRIVATE_FAX_NONSTANDARD))
8488 					{
8489 						if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8490 						{
8491 							if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos + 1] >= 2))
8492 								plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos + 2]);
8493 							for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8494 								nlc[++len] = plci->fax_connect_info_buffer[pos++];
8495 						}
8496 						else
8497 						{
8498 							if (api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8499 							{
8500 								dbug(1, dprintf("non-standard facilities info missing or wrong format"));
8501 								nlc[++len] = 0;
8502 							}
8503 							else
8504 							{
8505 								if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8506 									plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8507 								nlc[++len] = (byte)(b3_config_parms[4].length);
8508 								for (i = 0; i < b3_config_parms[4].length; i++)
8509 									nlc[++len] = b3_config_parms[4].info[1 + i];
8510 							}
8511 						}
8512 					}
8513 					nlc[0] = len;
8514 					if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8515 					    && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8516 					{
8517 						((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8518 					}
8519 				}
8520 			}
8521 
8522 			PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8523 			len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
8524 			for (i = 0; i < len; i++)
8525 				plci->fax_connect_info_buffer[i] = nlc[1 + i];
8526 			((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0;
8527 			i += ((T30_INFO *)&nlc[1])->head_line_len;
8528 			while (i < nlc[0])
8529 				plci->fax_connect_info_buffer[len++] = nlc[++i];
8530 			plci->fax_connect_info_length = len;
8531 		}
8532 		else
8533 		{
8534 			nlc[0] = 14;
8535 			if (b3_config->length != 16)
8536 				return _B3_PARM_NOT_SUPPORTED;
8537 			for (i = 0; i < 12; i++) nlc[1 + i] = b3_config->info[1 + i];
8538 			if (GET_WORD(&b3_config->info[13]) != 8 && GET_WORD(&b3_config->info[13]) != 128)
8539 				return _B3_PARM_NOT_SUPPORTED;
8540 			nlc[13] = b3_config->info[13];
8541 			if (GET_WORD(&b3_config->info[15]) >= nlc[13])
8542 				return _B3_PARM_NOT_SUPPORTED;
8543 			nlc[14] = b3_config->info[15];
8544 		}
8545 	}
8546 	else
8547 	{
8548 		if (plci->B3_prot == 4
8549 		    || plci->B3_prot == 5 /*T.30 - FAX*/) return _B3_PARM_NOT_SUPPORTED;
8550 	}
8551 	add_p(plci, NLC, nlc);
8552 	return 0;
8553 }
8554 
8555 /*----------------------------------------------------------------*/
8556 /*      make the same as add_b23, but only for the modem related  */
8557 /*      L2 and L3 B-Chan protocol.                                */
8558 /*                                                                */
8559 /*      Enabled L2 and L3 Configurations:                         */
8560 /*        If L1 == Modem all negotiation                          */
8561 /*          only L2 == Modem with full negotiation is allowed     */
8562 /*        If L1 == Modem async or sync                            */
8563 /*          only L2 == Transparent is allowed                     */
8564 /*        L3 == Modem or L3 == Transparent are allowed            */
8565 /*      B2 Configuration for modem:                               */
8566 /*          word : enable/disable compression, bitoptions         */
8567 /*      B3 Configuration for modem:                               */
8568 /*          empty                                                 */
8569 /*----------------------------------------------------------------*/
add_modem_b23(PLCI * plci,API_PARSE * bp_parms)8570 static word add_modem_b23(PLCI *plci, API_PARSE *bp_parms)
8571 {
8572 	static byte lli[12] = {1,1};
8573 	static byte llc[3] = {2,0,0};
8574 	static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8575 	API_PARSE mdm_config[2];
8576 	word i;
8577 	word b2_config = 0;
8578 
8579 	for (i = 0; i < 2; i++) mdm_config[i].length = 0;
8580 	for (i = 0; i < sizeof(dlc); i++) dlc[i] = 0;
8581 
8582 	if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8583 	     && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8584 	    || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8585 		&& (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8586 	{
8587 		return (_B_STACK_NOT_SUPPORTED);
8588 	}
8589 	if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8590 	    && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8591 	{
8592 		return (_B_STACK_NOT_SUPPORTED);
8593 	}
8594 
8595 	plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8596 	plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8597 
8598 	if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8599 	{
8600 		if (api_parse(&bp_parms[4].info[1],
8601 			      (word)bp_parms[4].length, "w",
8602 			      mdm_config))
8603 		{
8604 			return (_WRONG_MESSAGE_FORMAT);
8605 		}
8606 		b2_config = GET_WORD(mdm_config[0].info);
8607 	}
8608 
8609 	/* OK, L2 is modem */
8610 
8611 	lli[0] = 1;
8612 	lli[1] = 1;
8613 	if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8614 		lli[1] |= 2;
8615 	if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8616 		lli[1] |= 4;
8617 
8618 	if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8619 		lli[1] |= 0x10;
8620 		if (plci->rx_dma_descriptor <= 0) {
8621 			plci->rx_dma_descriptor = diva_get_dma_descriptor(plci, &plci->rx_dma_magic);
8622 			if (plci->rx_dma_descriptor >= 0)
8623 				plci->rx_dma_descriptor++;
8624 		}
8625 		if (plci->rx_dma_descriptor > 0) {
8626 			lli[1] |= 0x40;
8627 			lli[0] = 6;
8628 			lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8629 			lli[3] = (byte)plci->rx_dma_magic;
8630 			lli[4] = (byte)(plci->rx_dma_magic >>  8);
8631 			lli[5] = (byte)(plci->rx_dma_magic >> 16);
8632 			lli[6] = (byte)(plci->rx_dma_magic >> 24);
8633 		}
8634 	}
8635 
8636 	if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8637 		lli[1] |= 0x20;
8638 	}
8639 
8640 	llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8641 		/*V42*/ 10 : /*V42_IN*/ 9;
8642 	llc[2] = 4;                      /* pass L3 always transparent */
8643 	add_p(plci, LLI, lli);
8644 	add_p(plci, LLC, llc);
8645 	i =  1;
8646 	PUT_WORD(&dlc[i], plci->appl->MaxDataLength);
8647 	i += 2;
8648 	if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8649 	{
8650 		if (bp_parms[4].length)
8651 		{
8652 			dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8653 			dlc[i++] = 3; /* Addr A */
8654 			dlc[i++] = 1; /* Addr B */
8655 			dlc[i++] = 7; /* modulo mode */
8656 			dlc[i++] = 7; /* window size */
8657 			dlc[i++] = 0; /* XID len Lo  */
8658 			dlc[i++] = 0; /* XID len Hi  */
8659 
8660 			if (b2_config & MDM_B2_DISABLE_V42bis)
8661 			{
8662 				dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8663 			}
8664 			if (b2_config & MDM_B2_DISABLE_MNP)
8665 			{
8666 				dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8667 			}
8668 			if (b2_config & MDM_B2_DISABLE_TRANS)
8669 			{
8670 				dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8671 			}
8672 			if (b2_config & MDM_B2_DISABLE_V42)
8673 			{
8674 				dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8675 			}
8676 			if (b2_config & MDM_B2_DISABLE_COMP)
8677 			{
8678 				dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8679 			}
8680 			i++;
8681 		}
8682 	}
8683 	else
8684 	{
8685 		dlc[i++] = 3; /* Addr A */
8686 		dlc[i++] = 1; /* Addr B */
8687 		dlc[i++] = 7; /* modulo mode */
8688 		dlc[i++] = 7; /* window size */
8689 		dlc[i++] = 0; /* XID len Lo  */
8690 		dlc[i++] = 0; /* XID len Hi  */
8691 		dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8692 			DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8693 			DLC_MODEMPROT_DISABLE_V42_DETECT |
8694 			DLC_MODEMPROT_DISABLE_COMPRESSION;
8695 	}
8696 	dlc[0] = (byte)(i - 1);
8697 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8698 	add_p(plci, DLC, dlc);
8699 	return (0);
8700 }
8701 
8702 
8703 /*------------------------------------------------------------------*/
8704 /* send a request for the signaling entity                          */
8705 /*------------------------------------------------------------------*/
8706 
sig_req(PLCI * plci,byte req,byte Id)8707 static void sig_req(PLCI *plci, byte req, byte Id)
8708 {
8709 	if (!plci) return;
8710 	if (plci->adapter->adapter_disabled) return;
8711 	dbug(1, dprintf("sig_req(%x)", req));
8712 	if (req == REMOVE)
8713 		plci->sig_remove_id = plci->Sig.Id;
8714 	if (plci->req_in == plci->req_in_start) {
8715 		plci->req_in += 2;
8716 		plci->RBuffer[plci->req_in++] = 0;
8717 	}
8718 	PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8719 	plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
8720 	plci->RBuffer[plci->req_in++] = req;  /* request */
8721 	plci->RBuffer[plci->req_in++] = 0;    /* channel */
8722 	plci->req_in_start = plci->req_in;
8723 }
8724 
8725 /*------------------------------------------------------------------*/
8726 /* send a request for the network layer entity                      */
8727 /*------------------------------------------------------------------*/
8728 
nl_req_ncci(PLCI * plci,byte req,byte ncci)8729 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8730 {
8731 	if (!plci) return;
8732 	if (plci->adapter->adapter_disabled) return;
8733 	dbug(1, dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8734 	if (req == REMOVE)
8735 	{
8736 		plci->nl_remove_id = plci->NL.Id;
8737 		ncci_remove(plci, 0, (byte)(ncci != 0));
8738 		ncci = 0;
8739 	}
8740 	if (plci->req_in == plci->req_in_start) {
8741 		plci->req_in += 2;
8742 		plci->RBuffer[plci->req_in++] = 0;
8743 	}
8744 	PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start - 2);
8745 	plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */
8746 	plci->RBuffer[plci->req_in++] = req;  /* request */
8747 	plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
8748 	plci->req_in_start = plci->req_in;
8749 }
8750 
send_req(PLCI * plci)8751 static void send_req(PLCI *plci)
8752 {
8753 	ENTITY *e;
8754 	word l;
8755 /*  word i; */
8756 
8757 	if (!plci) return;
8758 	if (plci->adapter->adapter_disabled) return;
8759 	channel_xmit_xon(plci);
8760 
8761 	/* if nothing to do, return */
8762 	if (plci->req_in == plci->req_out) return;
8763 	dbug(1, dprintf("send_req(in=%d,out=%d)", plci->req_in, plci->req_out));
8764 
8765 	if (plci->nl_req || plci->sig_req) return;
8766 
8767 	l = GET_WORD(&plci->RBuffer[plci->req_out]);
8768 	plci->req_out += 2;
8769 	plci->XData[0].P = &plci->RBuffer[plci->req_out];
8770 	plci->req_out += l;
8771 	if (plci->RBuffer[plci->req_out] == 1)
8772 	{
8773 		e = &plci->NL;
8774 		plci->req_out++;
8775 		e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8776 		e->ReqCh = plci->RBuffer[plci->req_out++];
8777 		if (!(e->Id & 0x1f))
8778 		{
8779 			e->Id = NL_ID;
8780 			plci->RBuffer[plci->req_out - 4] = CAI;
8781 			plci->RBuffer[plci->req_out - 3] = 1;
8782 			plci->RBuffer[plci->req_out - 2] = (plci->Sig.Id == 0xff) ? 0 : plci->Sig.Id;
8783 			plci->RBuffer[plci->req_out - 1] = 0;
8784 			l += 3;
8785 			plci->nl_global_req = plci->nl_req;
8786 		}
8787 		dbug(1, dprintf("%x:NLREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8788 	}
8789 	else
8790 	{
8791 		e = &plci->Sig;
8792 		if (plci->RBuffer[plci->req_out])
8793 			e->Id = plci->RBuffer[plci->req_out];
8794 		plci->req_out++;
8795 		e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8796 		e->ReqCh = plci->RBuffer[plci->req_out++];
8797 		if (!(e->Id & 0x1f))
8798 			plci->sig_global_req = plci->sig_req;
8799 		dbug(1, dprintf("%x:SIGREQ(%x:%x:%x)", plci->adapter->Id, e->Id, e->Req, e->ReqCh));
8800 	}
8801 	plci->XData[0].PLength = l;
8802 	e->X = plci->XData;
8803 	plci->adapter->request(e);
8804 	dbug(1, dprintf("send_ok"));
8805 }
8806 
send_data(PLCI * plci)8807 static void send_data(PLCI *plci)
8808 {
8809 	DIVA_CAPI_ADAPTER *a;
8810 	DATA_B3_DESC *data;
8811 	NCCI   *ncci_ptr;
8812 	word ncci;
8813 
8814 	if (!plci->nl_req && plci->ncci_ring_list)
8815 	{
8816 		a = plci->adapter;
8817 		ncci = plci->ncci_ring_list;
8818 		do
8819 		{
8820 			ncci = a->ncci_next[ncci];
8821 			ncci_ptr = &(a->ncci[ncci]);
8822 			if (!(a->ncci_ch[ncci]
8823 			      && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8824 			{
8825 				if (ncci_ptr->data_pending)
8826 				{
8827 					if ((a->ncci_state[ncci] == CONNECTED)
8828 					    || (a->ncci_state[ncci] == INC_ACT_PENDING)
8829 					    || (plci->send_disc == ncci))
8830 					{
8831 						data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8832 						if ((plci->B2_prot == B2_V120_ASYNC)
8833 						    || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8834 						    || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8835 						{
8836 							plci->NData[1].P = TransmitBufferGet(plci->appl, data->P);
8837 							plci->NData[1].PLength = data->Length;
8838 							if (data->Flags & 0x10)
8839 								plci->NData[0].P = v120_break_header;
8840 							else
8841 								plci->NData[0].P = v120_default_header;
8842 							plci->NData[0].PLength = 1;
8843 							plci->NL.XNum = 2;
8844 							plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8845 						}
8846 						else
8847 						{
8848 							plci->NData[0].P = TransmitBufferGet(plci->appl, data->P);
8849 							plci->NData[0].PLength = data->Length;
8850 							if (data->Flags & 0x10)
8851 								plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8852 
8853 							else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8854 								plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8855 
8856 							else
8857 								plci->NL.Req = plci->nl_req = (byte)((data->Flags & 0x07) << 4 | N_DATA);
8858 						}
8859 						plci->NL.X = plci->NData;
8860 						plci->NL.ReqCh = a->ncci_ch[ncci];
8861 						dbug(1, dprintf("%x:DREQ(%x:%x)", a->Id, plci->NL.Id, plci->NL.Req));
8862 						plci->data_sent = true;
8863 						plci->data_sent_ptr = data->P;
8864 						a->request(&plci->NL);
8865 					}
8866 					else {
8867 						cleanup_ncci_data(plci, ncci);
8868 					}
8869 				}
8870 				else if (plci->send_disc == ncci)
8871 				{
8872 					/* dprintf("N_DISC"); */
8873 					plci->NData[0].PLength = 0;
8874 					plci->NL.ReqCh = a->ncci_ch[ncci];
8875 					plci->NL.Req = plci->nl_req = N_DISC;
8876 					a->request(&plci->NL);
8877 					plci->command = _DISCONNECT_B3_R;
8878 					plci->send_disc = 0;
8879 				}
8880 			}
8881 		} while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8882 		plci->ncci_ring_list = ncci;
8883 	}
8884 }
8885 
listen_check(DIVA_CAPI_ADAPTER * a)8886 static void listen_check(DIVA_CAPI_ADAPTER *a)
8887 {
8888 	word i, j;
8889 	PLCI *plci;
8890 	byte activnotifiedcalls = 0;
8891 
8892 	dbug(1, dprintf("listen_check(%d,%d)", a->listen_active, a->max_listen));
8893 	if (!remove_started && !a->adapter_disabled)
8894 	{
8895 		for (i = 0; i < a->max_plci; i++)
8896 		{
8897 			plci = &(a->plci[i]);
8898 			if (plci->notifiedcall) activnotifiedcalls++;
8899 		}
8900 		dbug(1, dprintf("listen_check(%d)", activnotifiedcalls));
8901 
8902 		for (i = a->listen_active; i < ((word)(a->max_listen + activnotifiedcalls)); i++) {
8903 			if ((j = get_plci(a))) {
8904 				a->listen_active++;
8905 				plci = &a->plci[j - 1];
8906 				plci->State = LISTENING;
8907 
8908 				add_p(plci, OAD, "\x01\xfd");
8909 
8910 				add_p(plci, KEY, "\x04\x43\x41\x32\x30");
8911 
8912 				add_p(plci, CAI, "\x01\xc0");
8913 				add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
8914 				add_p(plci, LLI, "\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */
8915 				add_p(plci, SHIFT | 6, NULL);
8916 				add_p(plci, SIN, "\x02\x00\x00");
8917 				plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
8918 				sig_req(plci, ASSIGN, DSIG_ID);
8919 				send_req(plci);
8920 			}
8921 		}
8922 	}
8923 }
8924 
8925 /*------------------------------------------------------------------*/
8926 /* functions for all parameters sent in INDs                        */
8927 /*------------------------------------------------------------------*/
8928 
IndParse(PLCI * plci,word * parms_id,byte ** parms,byte multiIEsize)8929 static void IndParse(PLCI *plci, word *parms_id, byte **parms, byte multiIEsize)
8930 {
8931 	word ploc;            /* points to current location within packet */
8932 	byte w;
8933 	byte wlen;
8934 	byte codeset, lock;
8935 	byte *in;
8936 	word i;
8937 	word code;
8938 	word mIEindex = 0;
8939 	ploc = 0;
8940 	codeset = 0;
8941 	lock = 0;
8942 
8943 	in = plci->Sig.RBuffer->P;
8944 	for (i = 0; i < parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
8945 	{                            /* element but parms array is larger      */
8946 		parms[i] = (byte *)"";
8947 	}
8948 	for (i = 0; i < multiIEsize; i++)
8949 	{
8950 		parms[i] = (byte *)"";
8951 	}
8952 
8953 	while (ploc < plci->Sig.RBuffer->length - 1) {
8954 
8955 		/* read information element id and length                   */
8956 		w = in[ploc];
8957 
8958 		if (w & 0x80) {
8959 /*    w &=0xf0; removed, cannot detect congestion levels */
8960 /*    upper 4 bit masked with w==SHIFT now               */
8961 			wlen = 0;
8962 		}
8963 		else {
8964 			wlen = (byte)(in[ploc + 1] + 1);
8965 		}
8966 		/* check if length valid (not exceeding end of packet)      */
8967 		if ((ploc + wlen) > 270) return;
8968 		if (lock & 0x80) lock &= 0x7f;
8969 		else codeset = lock;
8970 
8971 		if ((w & 0xf0) == SHIFT) {
8972 			codeset = in[ploc];
8973 			if (!(codeset & 0x08)) lock = (byte)(codeset & 7);
8974 			codeset &= 7;
8975 			lock |= 0x80;
8976 		}
8977 		else {
8978 			if (w == ESC && wlen >= 3) code = in[ploc + 2] | 0x800;
8979 			else code = w;
8980 			code |= (codeset << 8);
8981 
8982 			for (i = 1; i < parms_id[0] + 1 && parms_id[i] != code; i++);
8983 
8984 			if (i < parms_id[0] + 1) {
8985 				if (!multiIEsize) { /* with multiIEs use next field index,          */
8986 					mIEindex = i - 1;    /* with normal IEs use same index like parms_id */
8987 				}
8988 
8989 				parms[mIEindex] = &in[ploc + 1];
8990 				dbug(1, dprintf("mIE[%d]=0x%x", *parms[mIEindex], in[ploc]));
8991 				if (parms_id[i] == OAD
8992 				    || parms_id[i] == CONN_NR
8993 				    || parms_id[i] == CAD) {
8994 					if (in[ploc + 2] & 0x80) {
8995 						in[ploc + 0] = (byte)(in[ploc + 1] + 1);
8996 						in[ploc + 1] = (byte)(in[ploc + 2] & 0x7f);
8997 						in[ploc + 2] = 0x80;
8998 						parms[mIEindex] = &in[ploc];
8999 					}
9000 				}
9001 				mIEindex++;       /* effects multiIEs only */
9002 			}
9003 		}
9004 
9005 		ploc += (wlen + 1);
9006 	}
9007 	return;
9008 }
9009 
9010 /*------------------------------------------------------------------*/
9011 /* try to match a cip from received BC and HLC                      */
9012 /*------------------------------------------------------------------*/
9013 
ie_compare(byte * ie1,byte * ie2)9014 static byte ie_compare(byte *ie1, byte *ie2)
9015 {
9016 	word i;
9017 	if (!ie1 || !ie2) return false;
9018 	if (!ie1[0]) return false;
9019 	for (i = 0; i < (word)(ie1[0] + 1); i++) if (ie1[i] != ie2[i]) return false;
9020 	return true;
9021 }
9022 
find_cip(DIVA_CAPI_ADAPTER * a,byte * bc,byte * hlc)9023 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
9024 {
9025 	word i;
9026 	word j;
9027 
9028 	for (i = 9; i && !ie_compare(bc, cip_bc[i][a->u_law]); i--);
9029 
9030 	for (j = 16; j < 29 &&
9031 		     (!ie_compare(bc, cip_bc[j][a->u_law]) || !ie_compare(hlc, cip_hlc[j])); j++);
9032 	if (j == 29) return i;
9033 	return j;
9034 }
9035 
9036 
AddInfo(byte ** add_i,byte ** fty_i,byte * esc_chi,byte * facility)9037 static byte AddInfo(byte **add_i,
9038 		    byte **fty_i,
9039 		    byte *esc_chi,
9040 		    byte *facility)
9041 {
9042 	byte i;
9043 	byte j;
9044 	byte k;
9045 	byte flen;
9046 	byte len = 0;
9047 	/* facility is a nested structure */
9048 	/* FTY can be more than once      */
9049 
9050 	if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
9051 	{
9052 		add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */
9053 	}
9054 
9055 	else
9056 	{
9057 		add_i[0] = (byte *)"";
9058 	}
9059 	if (!fty_i[0][0])
9060 	{
9061 		add_i[3] = (byte *)"";
9062 	}
9063 	else
9064 	{    /* facility array found  */
9065 		for (i = 0, j = 1; i < MAX_MULTI_IE && fty_i[i][0]; i++)
9066 		{
9067 			dbug(1, dprintf("AddIFac[%d]", fty_i[i][0]));
9068 			len += fty_i[i][0];
9069 			len += 2;
9070 			flen = fty_i[i][0];
9071 			facility[j++] = 0x1c; /* copy fac IE */
9072 			for (k = 0; k <= flen; k++, j++)
9073 			{
9074 				facility[j] = fty_i[i][k];
9075 /*      dbug(1, dprintf("%x ",facility[j])); */
9076 			}
9077 		}
9078 		facility[0] = len;
9079 		add_i[3] = facility;
9080 	}
9081 /*  dbug(1, dprintf("FacArrLen=%d ",len)); */
9082 	len = add_i[0][0] + add_i[1][0] + add_i[2][0] + add_i[3][0];
9083 	len += 4;                          /* calculate length of all */
9084 	return (len);
9085 }
9086 
9087 /*------------------------------------------------------------------*/
9088 /* voice and codec features                                         */
9089 /*------------------------------------------------------------------*/
9090 
SetVoiceChannel(PLCI * plci,byte * chi,DIVA_CAPI_ADAPTER * a)9091 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
9092 {
9093 	byte voice_chi[] = "\x02\x18\x01";
9094 	byte channel;
9095 
9096 	channel = chi[chi[0]] & 0x3;
9097 	dbug(1, dprintf("ExtDevON(Ch=0x%x)", channel));
9098 	voice_chi[2] = (channel) ? channel : 1;
9099 	add_p(plci, FTY, "\x02\x01\x07");             /* B On, default on 1 */
9100 	add_p(plci, ESC, voice_chi);                  /* Channel */
9101 	sig_req(plci, TEL_CTRL, 0);
9102 	send_req(plci);
9103 	if (a->AdvSignalPLCI)
9104 	{
9105 		adv_voice_write_coefs(a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9106 	}
9107 }
9108 
VoiceChannelOff(PLCI * plci)9109 static void VoiceChannelOff(PLCI *plci)
9110 {
9111 	dbug(1, dprintf("ExtDevOFF"));
9112 	add_p(plci, FTY, "\x02\x01\x08");             /* B Off */
9113 	sig_req(plci, TEL_CTRL, 0);
9114 	send_req(plci);
9115 	if (plci->adapter->AdvSignalPLCI)
9116 	{
9117 		adv_voice_clear_config(plci->adapter->AdvSignalPLCI);
9118 	}
9119 }
9120 
9121 
AdvCodecSupport(DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,byte hook_listen)9122 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9123 			    byte hook_listen)
9124 {
9125 	word j;
9126 	PLCI *splci;
9127 
9128 	/* check if hardware supports handset with hook states (adv.codec) */
9129 	/* or if just a on board codec is supported                        */
9130 	/* the advanced codec plci is just for internal use                */
9131 
9132 	/* diva Pro with on-board codec:                                   */
9133 	if (a->profile.Global_Options & HANDSET)
9134 	{
9135 		/* new call, but hook states are already signalled */
9136 		if (a->AdvCodecFLAG)
9137 		{
9138 			if (a->AdvSignalAppl != appl || a->AdvSignalPLCI)
9139 			{
9140 				dbug(1, dprintf("AdvSigPlci=0x%x", a->AdvSignalPLCI));
9141 				return 0x2001; /* codec in use by another application */
9142 			}
9143 			if (plci != NULL)
9144 			{
9145 				a->AdvSignalPLCI = plci;
9146 				plci->tel = ADV_VOICE;
9147 			}
9148 			return 0;                      /* adv codec still used */
9149 		}
9150 		if ((j = get_plci(a)))
9151 		{
9152 			splci = &a->plci[j - 1];
9153 			splci->tel = CODEC_PERMANENT;
9154 			/* hook_listen indicates if a facility_req with handset/hook support */
9155 			/* was sent. Otherwise if just a call on an external device was made */
9156 			/* the codec will be used but the hook info will be discarded (just  */
9157 			/* the external controller is in use                                 */
9158 			if (hook_listen) splci->State = ADVANCED_VOICE_SIG;
9159 			else
9160 			{
9161 				splci->State = ADVANCED_VOICE_NOSIG;
9162 				if (plci)
9163 				{
9164 					plci->spoofed_msg = SPOOFING_REQUIRED;
9165 				}
9166 				/* indicate D-ch connect if  */
9167 			}                                        /* codec is connected OK     */
9168 			if (plci != NULL)
9169 			{
9170 				a->AdvSignalPLCI = plci;
9171 				plci->tel = ADV_VOICE;
9172 			}
9173 			a->AdvSignalAppl = appl;
9174 			a->AdvCodecFLAG = true;
9175 			a->AdvCodecPLCI = splci;
9176 			add_p(splci, CAI, "\x01\x15");
9177 			add_p(splci, LLI, "\x01\x00");
9178 			add_p(splci, ESC, "\x02\x18\x00");
9179 			add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9180 			splci->internal_command = PERM_COD_ASSIGN;
9181 			dbug(1, dprintf("Codec Assign"));
9182 			sig_req(splci, ASSIGN, DSIG_ID);
9183 			send_req(splci);
9184 		}
9185 		else
9186 		{
9187 			return 0x2001; /* wrong state, no more plcis */
9188 		}
9189 	}
9190 	else if (a->profile.Global_Options & ON_BOARD_CODEC)
9191 	{
9192 		if (hook_listen) return 0x300B;               /* Facility not supported */
9193 		/* no hook with SCOM      */
9194 		if (plci != NULL) plci->tel = CODEC;
9195 		dbug(1, dprintf("S/SCOM codec"));
9196 		/* first time we use the scom-s codec we must shut down the internal   */
9197 		/* handset application of the card. This can be done by an assign with */
9198 		/* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9199 		if (!a->scom_appl_disable) {
9200 			if ((j = get_plci(a))) {
9201 				splci = &a->plci[j - 1];
9202 				add_p(splci, CAI, "\x01\x80");
9203 				add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9204 				sig_req(splci, ASSIGN, 0xC0);  /* 0xc0 is the TEL_ID */
9205 				send_req(splci);
9206 				a->scom_appl_disable = true;
9207 			}
9208 			else{
9209 				return 0x2001; /* wrong state, no more plcis */
9210 			}
9211 		}
9212 	}
9213 	else return 0x300B;               /* Facility not supported */
9214 
9215 	return 0;
9216 }
9217 
9218 
CodecIdCheck(DIVA_CAPI_ADAPTER * a,PLCI * plci)9219 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9220 {
9221 
9222 	dbug(1, dprintf("CodecIdCheck"));
9223 
9224 	if (a->AdvSignalPLCI == plci)
9225 	{
9226 		dbug(1, dprintf("PLCI owns codec"));
9227 		VoiceChannelOff(a->AdvCodecPLCI);
9228 		if (a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9229 		{
9230 			dbug(1, dprintf("remove temp codec PLCI"));
9231 			plci_remove(a->AdvCodecPLCI);
9232 			a->AdvCodecFLAG  = 0;
9233 			a->AdvCodecPLCI  = NULL;
9234 			a->AdvSignalAppl = NULL;
9235 		}
9236 		a->AdvSignalPLCI = NULL;
9237 	}
9238 }
9239 
9240 /* -------------------------------------------------------------------
9241    Ask for physical address of card on PCI bus
9242    ------------------------------------------------------------------- */
diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER * a,IDI_SYNC_REQ * preq)9243 static void diva_ask_for_xdi_sdram_bar(DIVA_CAPI_ADAPTER *a,
9244 				       IDI_SYNC_REQ *preq) {
9245 	a->sdram_bar = 0;
9246 	if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9247 		ENTITY *e = (ENTITY *)preq;
9248 
9249 		e->user[0] = a->Id - 1;
9250 		preq->xdi_sdram_bar.info.bar    = 0;
9251 		preq->xdi_sdram_bar.Req         = 0;
9252 		preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9253 
9254 		(*(a->request))(e);
9255 
9256 		a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9257 		dbug(3, dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9258 	}
9259 }
9260 
9261 /* -------------------------------------------------------------------
9262    Ask XDI about extended features
9263    ------------------------------------------------------------------- */
diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER * a)9264 static void diva_get_extended_adapter_features(DIVA_CAPI_ADAPTER *a) {
9265 	IDI_SYNC_REQ *preq;
9266 	char buffer[((sizeof(preq->xdi_extended_features) + 4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features) + 4) : sizeof(ENTITY)];
9267 
9268 	char features[4];
9269 	preq = (IDI_SYNC_REQ *)&buffer[0];
9270 
9271 	if (!diva_xdi_extended_features) {
9272 		ENTITY *e = (ENTITY *)preq;
9273 		diva_xdi_extended_features |= 0x80000000;
9274 
9275 		e->user[0] = a->Id - 1;
9276 		preq->xdi_extended_features.Req = 0;
9277 		preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9278 		preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9279 		preq->xdi_extended_features.info.features = &features[0];
9280 
9281 		(*(a->request))(e);
9282 
9283 		if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9284 			/*
9285 			  Check features located in the byte '0'
9286 			*/
9287 			if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9288 				diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9289 			}
9290 			if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9291 				diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9292 				dbug(1, dprintf("XDI provides RxDMA"));
9293 			}
9294 			if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9295 				diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9296 			}
9297 			if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9298 				diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9299 				dbug(3, dprintf("XDI provides NO_CANCEL_RC feature"));
9300 			}
9301 
9302 		}
9303 	}
9304 
9305 	diva_ask_for_xdi_sdram_bar(a, preq);
9306 }
9307 
9308 /*------------------------------------------------------------------*/
9309 /* automatic law                                                    */
9310 /*------------------------------------------------------------------*/
9311 /* called from OS specific part after init time to get the Law              */
9312 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
AutomaticLaw(DIVA_CAPI_ADAPTER * a)9313 void AutomaticLaw(DIVA_CAPI_ADAPTER *a)
9314 {
9315 	word j;
9316 	PLCI *splci;
9317 
9318 	if (a->automatic_law) {
9319 		return;
9320 	}
9321 	if ((j = get_plci(a))) {
9322 		diva_get_extended_adapter_features(a);
9323 		splci = &a->plci[j - 1];
9324 		a->automatic_lawPLCI = splci;
9325 		a->automatic_law = 1;
9326 		add_p(splci, CAI, "\x01\x80");
9327 		add_p(splci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9328 		splci->internal_command = USELAW_REQ;
9329 		splci->command = 0;
9330 		splci->number = 0;
9331 		sig_req(splci, ASSIGN, DSIG_ID);
9332 		send_req(splci);
9333 	}
9334 }
9335 
9336 /* called from OS specific part if an application sends an Capi20Release */
CapiRelease(word Id)9337 word CapiRelease(word Id)
9338 {
9339 	word i, j, appls_found;
9340 	PLCI *plci;
9341 	APPL   *this;
9342 	DIVA_CAPI_ADAPTER *a;
9343 
9344 	if (!Id)
9345 	{
9346 		dbug(0, dprintf("A: CapiRelease(Id==0)"));
9347 		return (_WRONG_APPL_ID);
9348 	}
9349 
9350 	this = &application[Id - 1];               /* get application pointer */
9351 
9352 	for (i = 0, appls_found = 0; i < max_appl; i++)
9353 	{
9354 		if (application[i].Id)       /* an application has been found        */
9355 		{
9356 			appls_found++;
9357 		}
9358 	}
9359 
9360 	for (i = 0; i < max_adapter; i++)             /* scan all adapters...    */
9361 	{
9362 		a = &adapter[i];
9363 		if (a->request)
9364 		{
9365 			a->Info_Mask[Id - 1] = 0;
9366 			a->CIP_Mask[Id - 1] = 0;
9367 			a->Notification_Mask[Id - 1] = 0;
9368 			a->codec_listen[Id - 1] = NULL;
9369 			a->requested_options_table[Id - 1] = 0;
9370 			for (j = 0; j < a->max_plci; j++)           /* and all PLCIs connected */
9371 			{                                      /* with this application   */
9372 				plci = &a->plci[j];
9373 				if (plci->Id)                         /* if plci owns no application */
9374 				{                                    /* it may be not jet connected */
9375 					if (plci->State == INC_CON_PENDING
9376 					    || plci->State == INC_CON_ALERT)
9377 					{
9378 						if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9379 						{
9380 							clear_c_ind_mask_bit(plci, (word)(Id - 1));
9381 							if (c_ind_mask_empty(plci))
9382 							{
9383 								sig_req(plci, HANGUP, 0);
9384 								send_req(plci);
9385 								plci->State = OUTG_DIS_PENDING;
9386 							}
9387 						}
9388 					}
9389 					if (test_c_ind_mask_bit(plci, (word)(Id - 1)))
9390 					{
9391 						clear_c_ind_mask_bit(plci, (word)(Id - 1));
9392 						if (c_ind_mask_empty(plci))
9393 						{
9394 							if (!plci->appl)
9395 							{
9396 								plci_remove(plci);
9397 								plci->State = IDLE;
9398 							}
9399 						}
9400 					}
9401 					if (plci->appl == this)
9402 					{
9403 						plci->appl = NULL;
9404 						plci_remove(plci);
9405 						plci->State = IDLE;
9406 					}
9407 				}
9408 			}
9409 			listen_check(a);
9410 
9411 			if (a->flag_dynamic_l1_down)
9412 			{
9413 				if (appls_found == 1)            /* last application does a capi release */
9414 				{
9415 					if ((j = get_plci(a)))
9416 					{
9417 						plci = &a->plci[j - 1];
9418 						plci->command = 0;
9419 						add_p(plci, OAD, "\x01\xfd");
9420 						add_p(plci, CAI, "\x01\x80");
9421 						add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
9422 						add_p(plci, SHIFT | 6, NULL);
9423 						add_p(plci, SIN, "\x02\x00\x00");
9424 						plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9425 						sig_req(plci, ASSIGN, DSIG_ID);
9426 						add_p(plci, FTY, "\x02\xff\x06"); /* l1 down */
9427 						sig_req(plci, SIG_CTRL, 0);
9428 						send_req(plci);
9429 					}
9430 				}
9431 			}
9432 			if (a->AdvSignalAppl == this)
9433 			{
9434 				this->NullCREnable = false;
9435 				if (a->AdvCodecPLCI)
9436 				{
9437 					plci_remove(a->AdvCodecPLCI);
9438 					a->AdvCodecPLCI->tel = 0;
9439 					a->AdvCodecPLCI->adv_nl = 0;
9440 				}
9441 				a->AdvSignalAppl = NULL;
9442 				a->AdvSignalPLCI = NULL;
9443 				a->AdvCodecFLAG = 0;
9444 				a->AdvCodecPLCI = NULL;
9445 			}
9446 		}
9447 	}
9448 
9449 	this->Id = 0;
9450 
9451 	return GOOD;
9452 }
9453 
plci_remove_check(PLCI * plci)9454 static word plci_remove_check(PLCI *plci)
9455 {
9456 	if (!plci) return true;
9457 	if (!plci->NL.Id && c_ind_mask_empty(plci))
9458 	{
9459 		if (plci->Sig.Id == 0xff)
9460 			plci->Sig.Id = 0;
9461 		if (!plci->Sig.Id)
9462 		{
9463 			dbug(1, dprintf("plci_remove_complete(%x)", plci->Id));
9464 			dbug(1, dprintf("tel=0x%x,Sig=0x%x", plci->tel, plci->Sig.Id));
9465 			if (plci->Id)
9466 			{
9467 				CodecIdCheck(plci->adapter, plci);
9468 				clear_b1_config(plci);
9469 				ncci_remove(plci, 0, false);
9470 				plci_free_msg_in_queue(plci);
9471 				channel_flow_control_remove(plci);
9472 				plci->Id = 0;
9473 				plci->State = IDLE;
9474 				plci->channels = 0;
9475 				plci->appl = NULL;
9476 				plci->notifiedcall = 0;
9477 			}
9478 			listen_check(plci->adapter);
9479 			return true;
9480 		}
9481 	}
9482 	return false;
9483 }
9484 
9485 
9486 /*------------------------------------------------------------------*/
9487 
plci_nl_busy(PLCI * plci)9488 static byte plci_nl_busy(PLCI *plci)
9489 {
9490 	/* only applicable for non-multiplexed protocols */
9491 	return (plci->nl_req
9492 		|| (plci->ncci_ring_list
9493 		    && plci->adapter->ncci_ch[plci->ncci_ring_list]
9494 		    && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9495 }
9496 
9497 
9498 /*------------------------------------------------------------------*/
9499 /* DTMF facilities                                                  */
9500 /*------------------------------------------------------------------*/
9501 
9502 
9503 static struct
9504 {
9505 	byte send_mask;
9506 	byte listen_mask;
9507 	byte character;
9508 	byte code;
9509 } dtmf_digit_map[] =
9510 {
9511 	{ 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9512 	{ 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9513 	{ 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9514 	{ 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9515 	{ 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9516 	{ 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9517 	{ 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9518 	{ 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9519 	{ 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9520 	{ 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9521 	{ 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9522 	{ 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9523 	{ 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9524 	{ 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9525 	{ 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9526 	{ 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9527 	{ 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9528 	{ 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9529 	{ 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9530 	{ 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9531 
9532 	{ 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9533 	{ 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9534 	{ 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9535 	{ 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9536 	{ 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9537 	{ 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9538 	{ 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9539 	{ 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9540 	{ 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9541 	{ 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9542 	{ 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9543 	{ 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9544 	{ 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9545 	{ 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9546 	{ 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9547 	{ 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9548 	{ 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9549 	{ 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9550 	{ 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9551 	{ 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9552 	{ 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9553 	{ 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9554 	{ 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9555 	{ 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9556 	{ 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9557 	{ 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9558 	{ 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9559 	{ 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9560 	{ 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9561 	{ 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9562 	{ 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9563 	{ 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9564 	{ 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9565 	{ 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9566 	{ 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9567 	{ 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9568 	{ 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9569 	{ 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9570 	{ 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9571 	{ 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9572 	{ 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9573 	{ 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9574 	{ 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9575 	{ 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9576 	{ 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9577 	{ 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9578 	{ 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9579 	{ 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9580 	{ 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9581 	{ 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9582 	{ 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9583 	{ 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9584 
9585 };
9586 
9587 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9588 
9589 
dtmf_enable_receiver(PLCI * plci,byte enable_mask)9590 static void dtmf_enable_receiver(PLCI *plci, byte enable_mask)
9591 {
9592 	word min_digit_duration, min_gap_duration;
9593 
9594 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9595 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9596 			(char *)(FILE_), __LINE__, enable_mask));
9597 
9598 	if (enable_mask != 0)
9599 	{
9600 		min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9601 		min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9602 		plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9603 		PUT_WORD(&plci->internal_req_buffer[1], min_digit_duration);
9604 		PUT_WORD(&plci->internal_req_buffer[3], min_gap_duration);
9605 		plci->NData[0].PLength = 5;
9606 
9607 		PUT_WORD(&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9608 		plci->NData[0].PLength += 2;
9609 		capidtmf_recv_enable(&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9610 
9611 	}
9612 	else
9613 	{
9614 		plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9615 		plci->NData[0].PLength = 1;
9616 
9617 		capidtmf_recv_disable(&(plci->capidtmf_state));
9618 
9619 	}
9620 	plci->NData[0].P = plci->internal_req_buffer;
9621 	plci->NL.X = plci->NData;
9622 	plci->NL.ReqCh = 0;
9623 	plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9624 	plci->adapter->request(&plci->NL);
9625 }
9626 
9627 
dtmf_send_digits(PLCI * plci,byte * digit_buffer,word digit_count)9628 static void dtmf_send_digits(PLCI *plci, byte *digit_buffer, word digit_count)
9629 {
9630 	word w, i;
9631 
9632 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_digits %d",
9633 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9634 			(char *)(FILE_), __LINE__, digit_count));
9635 
9636 	plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9637 	w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9638 	PUT_WORD(&plci->internal_req_buffer[1], w);
9639 	w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9640 	PUT_WORD(&plci->internal_req_buffer[3], w);
9641 	for (i = 0; i < digit_count; i++)
9642 	{
9643 		w = 0;
9644 		while ((w < DTMF_DIGIT_MAP_ENTRIES)
9645 		       && (digit_buffer[i] != dtmf_digit_map[w].character))
9646 		{
9647 			w++;
9648 		}
9649 		plci->internal_req_buffer[5 + i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9650 			dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9651 	}
9652 	plci->NData[0].PLength = 5 + digit_count;
9653 	plci->NData[0].P = plci->internal_req_buffer;
9654 	plci->NL.X = plci->NData;
9655 	plci->NL.ReqCh = 0;
9656 	plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9657 	plci->adapter->request(&plci->NL);
9658 }
9659 
9660 
dtmf_rec_clear_config(PLCI * plci)9661 static void dtmf_rec_clear_config(PLCI *plci)
9662 {
9663 
9664 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_rec_clear_config",
9665 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9666 			(char *)(FILE_), __LINE__));
9667 
9668 	plci->dtmf_rec_active = 0;
9669 	plci->dtmf_rec_pulse_ms = 0;
9670 	plci->dtmf_rec_pause_ms = 0;
9671 
9672 	capidtmf_init(&(plci->capidtmf_state), plci->adapter->u_law);
9673 
9674 }
9675 
9676 
dtmf_send_clear_config(PLCI * plci)9677 static void dtmf_send_clear_config(PLCI *plci)
9678 {
9679 
9680 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_send_clear_config",
9681 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
9682 			(char *)(FILE_), __LINE__));
9683 
9684 	plci->dtmf_send_requests = 0;
9685 	plci->dtmf_send_pulse_ms = 0;
9686 	plci->dtmf_send_pause_ms = 0;
9687 }
9688 
9689 
dtmf_prepare_switch(dword Id,PLCI * plci)9690 static void dtmf_prepare_switch(dword Id, PLCI *plci)
9691 {
9692 
9693 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_prepare_switch",
9694 			UnMapId(Id), (char *)(FILE_), __LINE__));
9695 
9696 	while (plci->dtmf_send_requests != 0)
9697 		dtmf_confirmation(Id, plci);
9698 }
9699 
9700 
dtmf_save_config(dword Id,PLCI * plci,byte Rc)9701 static word dtmf_save_config(dword Id, PLCI *plci, byte Rc)
9702 {
9703 
9704 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_save_config %02x %d",
9705 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9706 
9707 	return (GOOD);
9708 }
9709 
9710 
dtmf_restore_config(dword Id,PLCI * plci,byte Rc)9711 static word dtmf_restore_config(dword Id, PLCI *plci, byte Rc)
9712 {
9713 	word Info;
9714 
9715 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9716 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9717 
9718 	Info = GOOD;
9719 	if (plci->B1_facilities & B1_FACILITY_DTMFR)
9720 	{
9721 		switch (plci->adjust_b_state)
9722 		{
9723 		case ADJUST_B_RESTORE_DTMF_1:
9724 			plci->internal_command = plci->adjust_b_command;
9725 			if (plci_nl_busy(plci))
9726 			{
9727 				plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9728 				break;
9729 			}
9730 			dtmf_enable_receiver(plci, plci->dtmf_rec_active);
9731 			plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9732 			break;
9733 		case ADJUST_B_RESTORE_DTMF_2:
9734 			if ((Rc != OK) && (Rc != OK_FC))
9735 			{
9736 				dbug(1, dprintf("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9737 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9738 				Info = _WRONG_STATE;
9739 				break;
9740 			}
9741 			break;
9742 		}
9743 	}
9744 	return (Info);
9745 }
9746 
9747 
dtmf_command(dword Id,PLCI * plci,byte Rc)9748 static void dtmf_command(dword Id, PLCI *plci, byte Rc)
9749 {
9750 	word internal_command, Info;
9751 	byte mask;
9752 	byte result[4];
9753 
9754 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9755 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
9756 			plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9757 			plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9758 
9759 	Info = GOOD;
9760 	result[0] = 2;
9761 	PUT_WORD(&result[1], DTMF_SUCCESS);
9762 	internal_command = plci->internal_command;
9763 	plci->internal_command = 0;
9764 	mask = 0x01;
9765 	switch (plci->dtmf_cmd)
9766 	{
9767 
9768 	case DTMF_LISTEN_TONE_START:
9769 		mask <<= 1;
9770 	case DTMF_LISTEN_MF_START:
9771 		mask <<= 1;
9772 
9773 	case DTMF_LISTEN_START:
9774 		switch (internal_command)
9775 		{
9776 		default:
9777 			adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9778 								  B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9779 		case DTMF_COMMAND_1:
9780 			if (adjust_b_process(Id, plci, Rc) != GOOD)
9781 			{
9782 				dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9783 						UnMapId(Id), (char *)(FILE_), __LINE__));
9784 				Info = _FACILITY_NOT_SUPPORTED;
9785 				break;
9786 			}
9787 			if (plci->internal_command)
9788 				return;
9789 		case DTMF_COMMAND_2:
9790 			if (plci_nl_busy(plci))
9791 			{
9792 				plci->internal_command = DTMF_COMMAND_2;
9793 				return;
9794 			}
9795 			plci->internal_command = DTMF_COMMAND_3;
9796 			dtmf_enable_receiver(plci, (byte)(plci->dtmf_rec_active | mask));
9797 			return;
9798 		case DTMF_COMMAND_3:
9799 			if ((Rc != OK) && (Rc != OK_FC))
9800 			{
9801 				dbug(1, dprintf("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9802 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9803 				Info = _FACILITY_NOT_SUPPORTED;
9804 				break;
9805 			}
9806 
9807 			plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9808 
9809 			plci->dtmf_rec_active |= mask;
9810 			break;
9811 		}
9812 		break;
9813 
9814 
9815 	case DTMF_LISTEN_TONE_STOP:
9816 		mask <<= 1;
9817 	case DTMF_LISTEN_MF_STOP:
9818 		mask <<= 1;
9819 
9820 	case DTMF_LISTEN_STOP:
9821 		switch (internal_command)
9822 		{
9823 		default:
9824 			plci->dtmf_rec_active &= ~mask;
9825 			if (plci->dtmf_rec_active)
9826 				break;
9827 /*
9828   case DTMF_COMMAND_1:
9829   if (plci->dtmf_rec_active)
9830   {
9831   if (plci_nl_busy (plci))
9832   {
9833   plci->internal_command = DTMF_COMMAND_1;
9834   return;
9835   }
9836   plci->dtmf_rec_active &= ~mask;
9837   plci->internal_command = DTMF_COMMAND_2;
9838   dtmf_enable_receiver (plci, false);
9839   return;
9840   }
9841   Rc = OK;
9842   case DTMF_COMMAND_2:
9843   if ((Rc != OK) && (Rc != OK_FC))
9844   {
9845   dbug (1, dprintf("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9846   UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9847   Info = _FACILITY_NOT_SUPPORTED;
9848   break;
9849   }
9850 */
9851 			adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
9852 								  ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9853 		case DTMF_COMMAND_3:
9854 			if (adjust_b_process(Id, plci, Rc) != GOOD)
9855 			{
9856 				dbug(1, dprintf("[%06lx] %s,%d: Unload DTMF failed",
9857 						UnMapId(Id), (char *)(FILE_), __LINE__));
9858 				Info = _FACILITY_NOT_SUPPORTED;
9859 				break;
9860 			}
9861 			if (plci->internal_command)
9862 				return;
9863 			break;
9864 		}
9865 		break;
9866 
9867 
9868 	case DTMF_SEND_TONE:
9869 		mask <<= 1;
9870 	case DTMF_SEND_MF:
9871 		mask <<= 1;
9872 
9873 	case DTMF_DIGITS_SEND:
9874 		switch (internal_command)
9875 		{
9876 		default:
9877 			adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
9878 								  ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9879 					   DTMF_COMMAND_1);
9880 		case DTMF_COMMAND_1:
9881 			if (adjust_b_process(Id, plci, Rc) != GOOD)
9882 			{
9883 				dbug(1, dprintf("[%06lx] %s,%d: Load DTMF failed",
9884 						UnMapId(Id), (char *)(FILE_), __LINE__));
9885 				Info = _FACILITY_NOT_SUPPORTED;
9886 				break;
9887 			}
9888 			if (plci->internal_command)
9889 				return;
9890 		case DTMF_COMMAND_2:
9891 			if (plci_nl_busy(plci))
9892 			{
9893 				plci->internal_command = DTMF_COMMAND_2;
9894 				return;
9895 			}
9896 			plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9897 			plci->internal_command = DTMF_COMMAND_3;
9898 			dtmf_send_digits(plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9899 			return;
9900 		case DTMF_COMMAND_3:
9901 			if ((Rc != OK) && (Rc != OK_FC))
9902 			{
9903 				dbug(1, dprintf("[%06lx] %s,%d: Send DTMF digits failed %02x",
9904 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
9905 				if (plci->dtmf_send_requests != 0)
9906 					(plci->dtmf_send_requests)--;
9907 				Info = _FACILITY_NOT_SUPPORTED;
9908 				break;
9909 			}
9910 			return;
9911 		}
9912 		break;
9913 	}
9914 	sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9915 	      "wws", Info, SELECTOR_DTMF, result);
9916 }
9917 
9918 
dtmf_request(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)9919 static byte dtmf_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
9920 {
9921 	word Info;
9922 	word i, j;
9923 	byte mask;
9924 	API_PARSE dtmf_parms[5];
9925 	byte result[40];
9926 
9927 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_request",
9928 			UnMapId(Id), (char *)(FILE_), __LINE__));
9929 
9930 	Info = GOOD;
9931 	result[0] = 2;
9932 	PUT_WORD(&result[1], DTMF_SUCCESS);
9933 	if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9934 	{
9935 		dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
9936 				UnMapId(Id), (char *)(FILE_), __LINE__));
9937 		Info = _FACILITY_NOT_SUPPORTED;
9938 	}
9939 	else if (api_parse(&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9940 	{
9941 		dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
9942 				UnMapId(Id), (char *)(FILE_), __LINE__));
9943 		Info = _WRONG_MESSAGE_FORMAT;
9944 	}
9945 
9946 	else if ((GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9947 		 || (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9948 	{
9949 		if (!((a->requested_options_table[appl->Id - 1])
9950 		      & (1L << PRIVATE_DTMF_TONE)))
9951 		{
9952 			dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
9953 					UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
9954 			PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
9955 		}
9956 		else
9957 		{
9958 			for (i = 0; i < 32; i++)
9959 				result[4 + i] = 0;
9960 			if (GET_WORD(dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9961 			{
9962 				for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9963 				{
9964 					if (dtmf_digit_map[i].listen_mask != 0)
9965 						result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9966 				}
9967 			}
9968 			else
9969 			{
9970 				for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9971 				{
9972 					if (dtmf_digit_map[i].send_mask != 0)
9973 						result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9974 				}
9975 			}
9976 			result[0] = 3 + 32;
9977 			result[3] = 32;
9978 		}
9979 	}
9980 
9981 	else if (plci == NULL)
9982 	{
9983 		dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
9984 				UnMapId(Id), (char *)(FILE_), __LINE__));
9985 		Info = _WRONG_IDENTIFIER;
9986 	}
9987 	else
9988 	{
9989 		if (!plci->State
9990 		    || !plci->NL.Id || plci->nl_remove_id)
9991 		{
9992 			dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
9993 					UnMapId(Id), (char *)(FILE_), __LINE__));
9994 			Info = _WRONG_STATE;
9995 		}
9996 		else
9997 		{
9998 			plci->command = 0;
9999 			plci->dtmf_cmd = GET_WORD(dtmf_parms[0].info);
10000 			mask = 0x01;
10001 			switch (plci->dtmf_cmd)
10002 			{
10003 
10004 			case DTMF_LISTEN_TONE_START:
10005 			case DTMF_LISTEN_TONE_STOP:
10006 				mask <<= 1;
10007 			case DTMF_LISTEN_MF_START:
10008 			case DTMF_LISTEN_MF_STOP:
10009 				mask <<= 1;
10010 				if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10011 				      & (1L << PRIVATE_DTMF_TONE)))
10012 				{
10013 					dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10014 							UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10015 					PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10016 					break;
10017 				}
10018 
10019 			case DTMF_LISTEN_START:
10020 			case DTMF_LISTEN_STOP:
10021 				if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10022 				    && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10023 				{
10024 					dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
10025 							UnMapId(Id), (char *)(FILE_), __LINE__));
10026 					Info = _FACILITY_NOT_SUPPORTED;
10027 					break;
10028 				}
10029 				if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10030 				{
10031 					if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10032 					{
10033 						plci->dtmf_rec_pulse_ms = 0;
10034 						plci->dtmf_rec_pause_ms = 0;
10035 					}
10036 					else
10037 					{
10038 						plci->dtmf_rec_pulse_ms = GET_WORD(dtmf_parms[1].info);
10039 						plci->dtmf_rec_pause_ms = GET_WORD(dtmf_parms[2].info);
10040 					}
10041 				}
10042 				start_internal_command(Id, plci, dtmf_command);
10043 				return (false);
10044 
10045 
10046 			case DTMF_SEND_TONE:
10047 				mask <<= 1;
10048 			case DTMF_SEND_MF:
10049 				mask <<= 1;
10050 				if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id - 1])
10051 				      & (1L << PRIVATE_DTMF_TONE)))
10052 				{
10053 					dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10054 							UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(dtmf_parms[0].info)));
10055 					PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10056 					break;
10057 				}
10058 
10059 			case DTMF_DIGITS_SEND:
10060 				if (api_parse(&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10061 				{
10062 					dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
10063 							UnMapId(Id), (char *)(FILE_), __LINE__));
10064 					Info = _WRONG_MESSAGE_FORMAT;
10065 					break;
10066 				}
10067 				if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10068 				{
10069 					plci->dtmf_send_pulse_ms = GET_WORD(dtmf_parms[1].info);
10070 					plci->dtmf_send_pause_ms = GET_WORD(dtmf_parms[2].info);
10071 				}
10072 				i = 0;
10073 				j = 0;
10074 				while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10075 				{
10076 					j = 0;
10077 					while ((j < DTMF_DIGIT_MAP_ENTRIES)
10078 					       && ((dtmf_parms[3].info[i + 1] != dtmf_digit_map[j].character)
10079 						   || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10080 					{
10081 						j++;
10082 					}
10083 					i++;
10084 				}
10085 				if (j == DTMF_DIGIT_MAP_ENTRIES)
10086 				{
10087 					dbug(1, dprintf("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10088 							UnMapId(Id), (char *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10089 					PUT_WORD(&result[1], DTMF_INCORRECT_DIGIT);
10090 					break;
10091 				}
10092 				if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10093 				{
10094 					dbug(1, dprintf("[%06lx] %s,%d: DTMF request overrun",
10095 							UnMapId(Id), (char *)(FILE_), __LINE__));
10096 					Info = _WRONG_STATE;
10097 					break;
10098 				}
10099 				api_save_msg(dtmf_parms, "wwws", &plci->saved_msg);
10100 				start_internal_command(Id, plci, dtmf_command);
10101 				return (false);
10102 
10103 			default:
10104 				dbug(1, dprintf("[%06lx] %s,%d: DTMF unknown request %04x",
10105 						UnMapId(Id), (char *)(FILE_), __LINE__, plci->dtmf_cmd));
10106 				PUT_WORD(&result[1], DTMF_UNKNOWN_REQUEST);
10107 			}
10108 		}
10109 	}
10110 	sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10111 	      "wws", Info, SELECTOR_DTMF, result);
10112 	return (false);
10113 }
10114 
10115 
dtmf_confirmation(dword Id,PLCI * plci)10116 static void dtmf_confirmation(dword Id, PLCI *plci)
10117 {
10118 	word i;
10119 	byte result[4];
10120 
10121 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_confirmation",
10122 			UnMapId(Id), (char *)(FILE_), __LINE__));
10123 
10124 	result[0] = 2;
10125 	PUT_WORD(&result[1], DTMF_SUCCESS);
10126 	if (plci->dtmf_send_requests != 0)
10127 	{
10128 		sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10129 		      "wws", GOOD, SELECTOR_DTMF, result);
10130 		(plci->dtmf_send_requests)--;
10131 		for (i = 0; i < plci->dtmf_send_requests; i++)
10132 			plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i + 1];
10133 	}
10134 }
10135 
10136 
dtmf_indication(dword Id,PLCI * plci,byte * msg,word length)10137 static void dtmf_indication(dword Id, PLCI *plci, byte *msg, word length)
10138 {
10139 	word i, j, n;
10140 
10141 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_indication",
10142 			UnMapId(Id), (char *)(FILE_), __LINE__));
10143 
10144 	n = 0;
10145 	for (i = 1; i < length; i++)
10146 	{
10147 		j = 0;
10148 		while ((j < DTMF_DIGIT_MAP_ENTRIES)
10149 		       && ((msg[i] != dtmf_digit_map[j].code)
10150 			   || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10151 		{
10152 			j++;
10153 		}
10154 		if (j < DTMF_DIGIT_MAP_ENTRIES)
10155 		{
10156 
10157 			if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10158 			    && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10159 			    && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10160 			{
10161 				if (n + 1 == i)
10162 				{
10163 					for (i = length; i > n + 1; i--)
10164 						msg[i] = msg[i - 1];
10165 					length++;
10166 					i++;
10167 				}
10168 				msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10169 			}
10170 			plci->tone_last_indication_code = dtmf_digit_map[j].character;
10171 
10172 			msg[++n] = dtmf_digit_map[j].character;
10173 		}
10174 	}
10175 	if (n != 0)
10176 	{
10177 		msg[0] = (byte) n;
10178 		sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10179 	}
10180 }
10181 
10182 
10183 /*------------------------------------------------------------------*/
10184 /* DTMF parameters                                                  */
10185 /*------------------------------------------------------------------*/
10186 
dtmf_parameter_write(PLCI * plci)10187 static void dtmf_parameter_write(PLCI *plci)
10188 {
10189 	word i;
10190 	byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10191 
10192 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_write",
10193 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10194 			(char *)(FILE_), __LINE__));
10195 
10196 	parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10197 	parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10198 	for (i = 0; i < plci->dtmf_parameter_length; i++)
10199 		parameter_buffer[2 + i] = plci->dtmf_parameter_buffer[i];
10200 	add_p(plci, FTY, parameter_buffer);
10201 	sig_req(plci, TEL_CTRL, 0);
10202 	send_req(plci);
10203 }
10204 
10205 
dtmf_parameter_clear_config(PLCI * plci)10206 static void dtmf_parameter_clear_config(PLCI *plci)
10207 {
10208 
10209 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_clear_config",
10210 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10211 			(char *)(FILE_), __LINE__));
10212 
10213 	plci->dtmf_parameter_length = 0;
10214 }
10215 
10216 
dtmf_parameter_prepare_switch(dword Id,PLCI * plci)10217 static void dtmf_parameter_prepare_switch(dword Id, PLCI *plci)
10218 {
10219 
10220 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10221 			UnMapId(Id), (char *)(FILE_), __LINE__));
10222 
10223 }
10224 
10225 
dtmf_parameter_save_config(dword Id,PLCI * plci,byte Rc)10226 static word dtmf_parameter_save_config(dword Id, PLCI *plci, byte Rc)
10227 {
10228 
10229 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10230 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10231 
10232 	return (GOOD);
10233 }
10234 
10235 
dtmf_parameter_restore_config(dword Id,PLCI * plci,byte Rc)10236 static word dtmf_parameter_restore_config(dword Id, PLCI *plci, byte Rc)
10237 {
10238 	word Info;
10239 
10240 	dbug(1, dprintf("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10241 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10242 
10243 	Info = GOOD;
10244 	if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10245 	    && (plci->dtmf_parameter_length != 0))
10246 	{
10247 		switch (plci->adjust_b_state)
10248 		{
10249 		case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10250 			plci->internal_command = plci->adjust_b_command;
10251 			if (plci->sig_req)
10252 			{
10253 				plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10254 				break;
10255 			}
10256 			dtmf_parameter_write(plci);
10257 			plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10258 			break;
10259 		case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10260 			if ((Rc != OK) && (Rc != OK_FC))
10261 			{
10262 				dbug(1, dprintf("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10263 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10264 				Info = _WRONG_STATE;
10265 				break;
10266 			}
10267 			break;
10268 		}
10269 	}
10270 	return (Info);
10271 }
10272 
10273 
10274 /*------------------------------------------------------------------*/
10275 /* Line interconnect facilities                                     */
10276 /*------------------------------------------------------------------*/
10277 
10278 
10279 LI_CONFIG   *li_config_table;
10280 word li_total_channels;
10281 
10282 
10283 /*------------------------------------------------------------------*/
10284 /* translate a CHI information element to a channel number          */
10285 /* returns 0xff - any channel                                       */
10286 /*         0xfe - chi wrong coding                                  */
10287 /*         0xfd - D-channel                                         */
10288 /*         0x00 - no channel                                        */
10289 /*         else channel number / PRI: timeslot                      */
10290 /* if channels is provided we accept more than one channel.         */
10291 /*------------------------------------------------------------------*/
10292 
chi_to_channel(byte * chi,dword * pchannelmap)10293 static byte chi_to_channel(byte *chi, dword *pchannelmap)
10294 {
10295 	int p;
10296 	int i;
10297 	dword map;
10298 	byte excl;
10299 	byte ofs;
10300 	byte ch;
10301 
10302 	if (pchannelmap) *pchannelmap = 0;
10303 	if (!chi[0]) return 0xff;
10304 	excl = 0;
10305 
10306 	if (chi[1] & 0x20) {
10307 		if (chi[0] == 1 && chi[1] == 0xac) return 0xfd; /* exclusive d-channel */
10308 		for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10309 		if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10310 		if ((chi[1] | 0xc8) != 0xe9) return 0xfe;
10311 		if (chi[1] & 0x08) excl = 0x40;
10312 
10313 		/* int. id present */
10314 		if (chi[1] & 0x40) {
10315 			p = i + 1;
10316 			for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10317 			if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10318 		}
10319 
10320 		/* coding standard, Number/Map, Channel Type */
10321 		p = i + 1;
10322 		for (i = p; i < chi[0] && !(chi[i] & 0x80); i++);
10323 		if (i == chi[0] || !(chi[i] & 0x80)) return 0xfe;
10324 		if ((chi[p] | 0xd0) != 0xd3) return 0xfe;
10325 
10326 		/* Number/Map */
10327 		if (chi[p] & 0x10) {
10328 
10329 			/* map */
10330 			if ((chi[0] - p) == 4) ofs = 0;
10331 			else if ((chi[0] - p) == 3) ofs = 1;
10332 			else return 0xfe;
10333 			ch = 0;
10334 			map = 0;
10335 			for (i = 0; i < 4 && p < chi[0]; i++) {
10336 				p++;
10337 				ch += 8;
10338 				map <<= 8;
10339 				if (chi[p]) {
10340 					for (ch = 0; !(chi[p] & (1 << ch)); ch++);
10341 					map |= chi[p];
10342 				}
10343 			}
10344 			ch += ofs;
10345 			map <<= ofs;
10346 		}
10347 		else {
10348 
10349 			/* number */
10350 			p = i + 1;
10351 			ch = chi[p] & 0x3f;
10352 			if (pchannelmap) {
10353 				if ((byte)(chi[0] - p) > 30) return 0xfe;
10354 				map = 0;
10355 				for (i = p; i <= chi[0]; i++) {
10356 					if ((chi[i] & 0x7f) > 31) return 0xfe;
10357 					map |= (1L << (chi[i] & 0x7f));
10358 				}
10359 			}
10360 			else {
10361 				if (p != chi[0]) return 0xfe;
10362 				if (ch > 31) return 0xfe;
10363 				map = (1L << ch);
10364 			}
10365 			if (chi[p] & 0x40) return 0xfe;
10366 		}
10367 		if (pchannelmap) *pchannelmap = map;
10368 		else if (map != ((dword)(1L << ch))) return 0xfe;
10369 		return (byte)(excl | ch);
10370 	}
10371 	else {  /* not PRI */
10372 		for (i = 1; i < chi[0] && !(chi[i] & 0x80); i++);
10373 		if (i != chi[0] || !(chi[i] & 0x80)) return 0xfe;
10374 		if (chi[1] & 0x08) excl = 0x40;
10375 
10376 		switch (chi[1] | 0x98) {
10377 		case 0x98: return 0;
10378 		case 0x99:
10379 			if (pchannelmap) *pchannelmap = 2;
10380 			return excl | 1;
10381 		case 0x9a:
10382 			if (pchannelmap) *pchannelmap = 4;
10383 			return excl | 2;
10384 		case 0x9b: return 0xff;
10385 		case 0x9c: return 0xfd; /* d-ch */
10386 		default: return 0xfe;
10387 		}
10388 	}
10389 }
10390 
10391 
mixer_set_bchannel_id_esc(PLCI * plci,byte bchannel_id)10392 static void mixer_set_bchannel_id_esc(PLCI *plci, byte bchannel_id)
10393 {
10394 	DIVA_CAPI_ADAPTER *a;
10395 	PLCI *splci;
10396 	byte old_id;
10397 
10398 	a = plci->adapter;
10399 	old_id = plci->li_bchannel_id;
10400 	if (a->li_pri)
10401 	{
10402 		if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10403 			li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10404 		plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10405 		if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10406 			li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10407 	}
10408 	else
10409 	{
10410 		if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10411 		{
10412 			if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10413 				li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10414 			plci->li_bchannel_id = bchannel_id & 0x03;
10415 			if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10416 			{
10417 				splci = a->AdvSignalPLCI;
10418 				if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10419 				{
10420 					if ((splci->li_bchannel_id != 0)
10421 					    && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10422 					{
10423 						li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10424 					}
10425 					splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10426 					li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10427 					dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10428 							(dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10429 							(char *)(FILE_), __LINE__, splci->li_bchannel_id));
10430 				}
10431 			}
10432 			if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10433 				li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10434 		}
10435 	}
10436 	if ((old_id == 0) && (plci->li_bchannel_id != 0)
10437 	    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10438 	{
10439 		mixer_clear_config(plci);
10440 	}
10441 	dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10442 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10443 			(char *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10444 }
10445 
10446 
mixer_set_bchannel_id(PLCI * plci,byte * chi)10447 static void mixer_set_bchannel_id(PLCI *plci, byte *chi)
10448 {
10449 	DIVA_CAPI_ADAPTER *a;
10450 	PLCI *splci;
10451 	byte ch, old_id;
10452 
10453 	a = plci->adapter;
10454 	old_id = plci->li_bchannel_id;
10455 	ch = chi_to_channel(chi, NULL);
10456 	if (!(ch & 0x80))
10457 	{
10458 		if (a->li_pri)
10459 		{
10460 			if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10461 				li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10462 			plci->li_bchannel_id = (ch & 0x1f) + 1;
10463 			if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10464 				li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10465 		}
10466 		else
10467 		{
10468 			if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10469 			{
10470 				if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10471 					li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10472 				plci->li_bchannel_id = ch & 0x1f;
10473 				if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10474 				{
10475 					splci = a->AdvSignalPLCI;
10476 					if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10477 					{
10478 						if ((splci->li_bchannel_id != 0)
10479 						    && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10480 						{
10481 							li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10482 						}
10483 						splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10484 						li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10485 						dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10486 								(dword)((splci->Id << 8) | UnMapController(splci->adapter->Id)),
10487 								(char *)(FILE_), __LINE__, splci->li_bchannel_id));
10488 					}
10489 				}
10490 				if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10491 					li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10492 			}
10493 		}
10494 	}
10495 	if ((old_id == 0) && (plci->li_bchannel_id != 0)
10496 	    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10497 	{
10498 		mixer_clear_config(plci);
10499 	}
10500 	dbug(1, dprintf("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10501 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10502 			(char *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10503 }
10504 
10505 
10506 #define MIXER_MAX_DUMP_CHANNELS 34
10507 
mixer_calculate_coefs(DIVA_CAPI_ADAPTER * a)10508 static void mixer_calculate_coefs(DIVA_CAPI_ADAPTER *a)
10509 {
10510 	static char hex_digit_table[0x10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
10511 	word n, i, j;
10512 	char *p;
10513 	char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10514 
10515 	dbug(1, dprintf("[%06lx] %s,%d: mixer_calculate_coefs",
10516 			(dword)(UnMapController(a->Id)), (char *)(FILE_), __LINE__));
10517 
10518 	for (i = 0; i < li_total_channels; i++)
10519 	{
10520 		li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10521 		if (li_config_table[i].chflags != 0)
10522 			li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10523 		else
10524 		{
10525 			for (j = 0; j < li_total_channels; j++)
10526 			{
10527 				if (((li_config_table[i].flag_table[j]) != 0)
10528 				    || ((li_config_table[j].flag_table[i]) != 0))
10529 				{
10530 					li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10531 				}
10532 				if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10533 				    || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10534 				{
10535 					li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10536 				}
10537 			}
10538 		}
10539 	}
10540 	for (i = 0; i < li_total_channels; i++)
10541 	{
10542 		for (j = 0; j < li_total_channels; j++)
10543 		{
10544 			li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10545 			if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10546 				li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10547 		}
10548 	}
10549 	for (n = 0; n < li_total_channels; n++)
10550 	{
10551 		if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10552 		{
10553 			for (i = 0; i < li_total_channels; i++)
10554 			{
10555 				if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10556 				{
10557 					for (j = 0; j < li_total_channels; j++)
10558 					{
10559 						li_config_table[i].coef_table[j] |=
10560 							li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10561 					}
10562 				}
10563 			}
10564 		}
10565 	}
10566 	for (i = 0; i < li_total_channels; i++)
10567 	{
10568 		if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10569 		{
10570 			li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10571 			for (j = 0; j < li_total_channels; j++)
10572 			{
10573 				if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10574 					li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10575 			}
10576 			if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10577 				li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10578 		}
10579 	}
10580 	for (i = 0; i < li_total_channels; i++)
10581 	{
10582 		if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10583 		{
10584 			for (j = 0; j < li_total_channels; j++)
10585 			{
10586 				if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10587 					li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10588 				if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10589 					li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10590 				if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10591 					li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10592 				if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10593 					li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10594 			}
10595 			if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10596 			{
10597 				for (j = 0; j < li_total_channels; j++)
10598 				{
10599 					if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10600 					{
10601 						li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10602 						if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10603 							li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10604 					}
10605 				}
10606 			}
10607 			if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10608 			{
10609 				for (j = 0; j < li_total_channels; j++)
10610 				{
10611 					if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10612 						li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10613 				}
10614 			}
10615 			if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10616 			{
10617 				for (j = 0; j < li_total_channels; j++)
10618 				{
10619 					if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10620 					{
10621 						for (n = 0; n < li_total_channels; n++)
10622 						{
10623 							if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10624 							{
10625 								li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10626 								if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10627 								{
10628 									li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10629 									if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10630 										li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10631 								}
10632 								else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10633 									li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10634 							}
10635 						}
10636 					}
10637 				}
10638 			}
10639 		}
10640 	}
10641 	for (i = 0; i < li_total_channels; i++)
10642 	{
10643 		if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10644 		{
10645 			if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10646 				li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10647 			if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10648 				li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10649 			if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10650 				li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10651 			for (j = 0; j < li_total_channels; j++)
10652 			{
10653 				if ((li_config_table[i].flag_table[j] &
10654 				     (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10655 				    || (li_config_table[j].flag_table[i] &
10656 					(LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10657 				{
10658 					li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10659 				}
10660 				if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10661 					li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10662 				if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10663 					li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10664 			}
10665 			if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10666 			{
10667 				li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10668 				li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10669 			}
10670 		}
10671 	}
10672 	for (i = 0; i < li_total_channels; i++)
10673 	{
10674 		if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10675 		{
10676 			j = 0;
10677 			while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10678 				j++;
10679 			if (j < li_total_channels)
10680 			{
10681 				for (j = 0; j < li_total_channels; j++)
10682 				{
10683 					li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10684 					if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10685 						li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10686 				}
10687 			}
10688 		}
10689 	}
10690 	n = li_total_channels;
10691 	if (n > MIXER_MAX_DUMP_CHANNELS)
10692 		n = MIXER_MAX_DUMP_CHANNELS;
10693 	p = hex_line;
10694 	for (j = 0; j < n; j++)
10695 	{
10696 		if ((j & 0x7) == 0)
10697 			*(p++) = ' ';
10698 		*(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10699 		*(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10700 	}
10701 	*p = '\0';
10702 	dbug(1, dprintf("[%06lx] CURRENT %s",
10703 			(dword)(UnMapController(a->Id)), (char *)hex_line));
10704 	p = hex_line;
10705 	for (j = 0; j < n; j++)
10706 	{
10707 		if ((j & 0x7) == 0)
10708 			*(p++) = ' ';
10709 		*(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10710 		*(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10711 	}
10712 	*p = '\0';
10713 	dbug(1, dprintf("[%06lx] CHANNEL %s",
10714 			(dword)(UnMapController(a->Id)), (char *)hex_line));
10715 	p = hex_line;
10716 	for (j = 0; j < n; j++)
10717 	{
10718 		if ((j & 0x7) == 0)
10719 			*(p++) = ' ';
10720 		*(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10721 		*(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10722 	}
10723 	*p = '\0';
10724 	dbug(1, dprintf("[%06lx] CHFLAG  %s",
10725 			(dword)(UnMapController(a->Id)), (char *)hex_line));
10726 	for (i = 0; i < n; i++)
10727 	{
10728 		p = hex_line;
10729 		for (j = 0; j < n; j++)
10730 		{
10731 			if ((j & 0x7) == 0)
10732 				*(p++) = ' ';
10733 			*(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10734 			*(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10735 		}
10736 		*p = '\0';
10737 		dbug(1, dprintf("[%06lx] FLAG[%02x]%s",
10738 				(dword)(UnMapController(a->Id)), i, (char *)hex_line));
10739 	}
10740 	for (i = 0; i < n; i++)
10741 	{
10742 		p = hex_line;
10743 		for (j = 0; j < n; j++)
10744 		{
10745 			if ((j & 0x7) == 0)
10746 				*(p++) = ' ';
10747 			*(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10748 			*(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10749 		}
10750 		*p = '\0';
10751 		dbug(1, dprintf("[%06lx] COEF[%02x]%s",
10752 				(dword)(UnMapController(a->Id)), i, (char *)hex_line));
10753 	}
10754 }
10755 
10756 
10757 static struct
10758 {
10759 	byte mask;
10760 	byte line_flags;
10761 } mixer_write_prog_pri[] =
10762 {
10763 	{ LI_COEF_CH_CH, 0 },
10764 	{ LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10765 	{ LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10766 	{ LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10767 };
10768 
10769 static struct
10770 {
10771 	byte from_ch;
10772 	byte to_ch;
10773 	byte mask;
10774 	byte xconnect_override;
10775 } mixer_write_prog_bri[] =
10776 {
10777 	{ 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10778 	{ 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10779 	{ 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10780 	{ 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10781 	{ 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10782 	{ 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10783 	{ 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10784 	{ 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10785 	{ 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10786 	{ 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10787 	{ 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10788 	{ 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10789 	{ 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10790 	{ 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10791 	{ 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10792 	{ 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10793 	{ 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10794 	{ 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10795 	{ 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10796 	{ 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10797 	{ 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10798 	{ 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10799 	{ 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10800 	{ 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10801 	{ 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10802 	{ 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10803 	{ 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10804 	{ 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10805 	{ 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10806 	{ 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10807 	{ 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10808 	{ 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10809 	{ 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10810 	{ 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10811 	{ 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10812 	{ 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10813 };
10814 
10815 static byte mixer_swapped_index_bri[] =
10816 {
10817 	18,  /* B      to B      */
10818 	19,  /* Alt B  to B      */
10819 	20,  /* PC     to B      */
10820 	21,  /* Alt PC to B      */
10821 	22,  /* IC     to B      */
10822 	23,  /* Alt IC to B      */
10823 	24,  /* B      to PC     */
10824 	25,  /* Alt B  to PC     */
10825 	26,  /* PC     to PC     */
10826 	27,  /* Alt PC to PC     */
10827 	28,  /* IC     to PC     */
10828 	29,  /* Alt IC to PC     */
10829 	30,  /* B      to IC     */
10830 	31,  /* Alt B  to IC     */
10831 	32,  /* PC     to IC     */
10832 	33,  /* Alt PC to IC     */
10833 	34,  /* IC     to IC     */
10834 	35,  /* Alt IC to IC     */
10835 	0,   /* Alt B  to Alt B  */
10836 	1,   /* B      to Alt B  */
10837 	2,   /* Alt PC to Alt B  */
10838 	3,   /* PC     to Alt B  */
10839 	4,   /* Alt IC to Alt B  */
10840 	5,   /* IC     to Alt B  */
10841 	6,   /* Alt B  to Alt PC */
10842 	7,   /* B      to Alt PC */
10843 	8,   /* Alt PC to Alt PC */
10844 	9,   /* PC     to Alt PC */
10845 	10,  /* Alt IC to Alt PC */
10846 	11,  /* IC     to Alt PC */
10847 	12,  /* Alt B  to Alt IC */
10848 	13,  /* B      to Alt IC */
10849 	14,  /* Alt PC to Alt IC */
10850 	15,  /* PC     to Alt IC */
10851 	16,  /* Alt IC to Alt IC */
10852 	17   /* IC     to Alt IC */
10853 };
10854 
10855 static struct
10856 {
10857 	byte mask;
10858 	byte from_pc;
10859 	byte to_pc;
10860 } xconnect_write_prog[] =
10861 {
10862 	{ LI_COEF_CH_CH, false, false },
10863 	{ LI_COEF_CH_PC, false, true },
10864 	{ LI_COEF_PC_CH, true, false },
10865 	{ LI_COEF_PC_PC, true, true }
10866 };
10867 
10868 
xconnect_query_addresses(PLCI * plci)10869 static void xconnect_query_addresses(PLCI *plci)
10870 {
10871 	DIVA_CAPI_ADAPTER *a;
10872 	word w, ch;
10873 	byte *p;
10874 
10875 	dbug(1, dprintf("[%06lx] %s,%d: xconnect_query_addresses",
10876 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10877 			(char *)(FILE_), __LINE__));
10878 
10879 	a = plci->adapter;
10880 	if (a->li_pri && ((plci->li_bchannel_id == 0)
10881 			  || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10882 	{
10883 		dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10884 				(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10885 				(char *)(FILE_), __LINE__));
10886 		return;
10887 	}
10888 	p = plci->internal_req_buffer;
10889 	ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10890 	*(p++) = UDATA_REQUEST_XCONNECT_FROM;
10891 	w = ch;
10892 	*(p++) = (byte) w;
10893 	*(p++) = (byte)(w >> 8);
10894 	w = ch | XCONNECT_CHANNEL_PORT_PC;
10895 	*(p++) = (byte) w;
10896 	*(p++) = (byte)(w >> 8);
10897 	plci->NData[0].P = plci->internal_req_buffer;
10898 	plci->NData[0].PLength = p - plci->internal_req_buffer;
10899 	plci->NL.X = plci->NData;
10900 	plci->NL.ReqCh = 0;
10901 	plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10902 	plci->adapter->request(&plci->NL);
10903 }
10904 
10905 
xconnect_write_coefs(PLCI * plci,word internal_command)10906 static void xconnect_write_coefs(PLCI *plci, word internal_command)
10907 {
10908 
10909 	dbug(1, dprintf("[%06lx] %s,%d: xconnect_write_coefs %04x",
10910 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
10911 			(char *)(FILE_), __LINE__, internal_command));
10912 
10913 	plci->li_write_command = internal_command;
10914 	plci->li_write_channel = 0;
10915 }
10916 
10917 
xconnect_write_coefs_process(dword Id,PLCI * plci,byte Rc)10918 static byte xconnect_write_coefs_process(dword Id, PLCI *plci, byte Rc)
10919 {
10920 	DIVA_CAPI_ADAPTER *a;
10921 	word w, n, i, j, r, s, to_ch;
10922 	dword d;
10923 	byte *p;
10924 	struct xconnect_transfer_address_s   *transfer_address;
10925 	byte ch_map[MIXER_CHANNELS_BRI];
10926 
10927 	dbug(1, dprintf("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10928 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10929 
10930 	a = plci->adapter;
10931 	if ((plci->li_bchannel_id == 0)
10932 	    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10933 	{
10934 		dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out",
10935 				UnMapId(Id), (char *)(FILE_), __LINE__));
10936 		return (true);
10937 	}
10938 	i = a->li_base + (plci->li_bchannel_id - 1);
10939 	j = plci->li_write_channel;
10940 	p = plci->internal_req_buffer;
10941 	if (j != 0)
10942 	{
10943 		if ((Rc != OK) && (Rc != OK_FC))
10944 		{
10945 			dbug(1, dprintf("[%06lx] %s,%d: LI write coefs failed %02x",
10946 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
10947 			return (false);
10948 		}
10949 	}
10950 	if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10951 	{
10952 		r = 0;
10953 		s = 0;
10954 		if (j < li_total_channels)
10955 		{
10956 			if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10957 			{
10958 				s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10959 				     (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10960 					((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10961 					 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10962 			}
10963 			r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10964 			while ((j < li_total_channels)
10965 			       && ((r == 0)
10966 				   || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10967 				   || (!li_config_table[j].adapter->li_pri
10968 				       && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10969 				   || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10970 					|| (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10971 				       && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10972 					   || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10973 				   || ((li_config_table[j].adapter->li_base != a->li_base)
10974 				       && !(r & s &
10975 					    ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10976 					     (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10977 					    ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10978 					     (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10979 			{
10980 				j++;
10981 				if (j < li_total_channels)
10982 					r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10983 			}
10984 		}
10985 		if (j < li_total_channels)
10986 		{
10987 			plci->internal_command = plci->li_write_command;
10988 			if (plci_nl_busy(plci))
10989 				return (true);
10990 			to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10991 			*(p++) = UDATA_REQUEST_XCONNECT_TO;
10992 			do
10993 			{
10994 				if (li_config_table[j].adapter->li_base != a->li_base)
10995 				{
10996 					r &= s &
10997 						((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10998 						 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10999 						((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11000 						 (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
11001 				}
11002 				n = 0;
11003 				do
11004 				{
11005 					if (r & xconnect_write_prog[n].mask)
11006 					{
11007 						if (xconnect_write_prog[n].from_pc)
11008 							transfer_address = &(li_config_table[j].send_pc);
11009 						else
11010 							transfer_address = &(li_config_table[j].send_b);
11011 						d = transfer_address->card_address.low;
11012 						*(p++) = (byte) d;
11013 						*(p++) = (byte)(d >> 8);
11014 						*(p++) = (byte)(d >> 16);
11015 						*(p++) = (byte)(d >> 24);
11016 						d = transfer_address->card_address.high;
11017 						*(p++) = (byte) d;
11018 						*(p++) = (byte)(d >> 8);
11019 						*(p++) = (byte)(d >> 16);
11020 						*(p++) = (byte)(d >> 24);
11021 						d = transfer_address->offset;
11022 						*(p++) = (byte) d;
11023 						*(p++) = (byte)(d >> 8);
11024 						*(p++) = (byte)(d >> 16);
11025 						*(p++) = (byte)(d >> 24);
11026 						w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11027 						*(p++) = (byte) w;
11028 						*(p++) = (byte)(w >> 8);
11029 						w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11030 							(li_config_table[i].adapter->u_law ?
11031 							 (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11032 							 (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11033 						*(p++) = (byte) w;
11034 						*(p++) = (byte) 0;
11035 						li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11036 					}
11037 					n++;
11038 				} while ((n < ARRAY_SIZE(xconnect_write_prog))
11039 					 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11040 				if (n == ARRAY_SIZE(xconnect_write_prog))
11041 				{
11042 					do
11043 					{
11044 						j++;
11045 						if (j < li_total_channels)
11046 							r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11047 					} while ((j < li_total_channels)
11048 						 && ((r == 0)
11049 						     || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11050 						     || (!li_config_table[j].adapter->li_pri
11051 							 && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11052 						     || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11053 							  || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11054 							 && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11055 							     || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11056 						     || ((li_config_table[j].adapter->li_base != a->li_base)
11057 							 && !(r & s &
11058 							      ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11059 							       (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11060 							      ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11061 							       (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11062 				}
11063 			} while ((j < li_total_channels)
11064 				 && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11065 		}
11066 		else if (j == li_total_channels)
11067 		{
11068 			plci->internal_command = plci->li_write_command;
11069 			if (plci_nl_busy(plci))
11070 				return (true);
11071 			if (a->li_pri)
11072 			{
11073 				*(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11074 				w = 0;
11075 				if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11076 					w |= MIXER_FEATURE_ENABLE_TX_DATA;
11077 				if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11078 					w |= MIXER_FEATURE_ENABLE_RX_DATA;
11079 				*(p++) = (byte) w;
11080 				*(p++) = (byte)(w >> 8);
11081 			}
11082 			else
11083 			{
11084 				*(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11085 				w = 0;
11086 				if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11087 				    && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11088 				{
11089 					w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11090 				}
11091 				if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11092 					w |= MIXER_FEATURE_ENABLE_TX_DATA;
11093 				if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11094 					w |= MIXER_FEATURE_ENABLE_RX_DATA;
11095 				*(p++) = (byte) w;
11096 				*(p++) = (byte)(w >> 8);
11097 				for (j = 0; j < sizeof(ch_map); j += 2)
11098 				{
11099 					if (plci->li_bchannel_id == 2)
11100 					{
11101 						ch_map[j] = (byte)(j + 1);
11102 						ch_map[j + 1] = (byte) j;
11103 					}
11104 					else
11105 					{
11106 						ch_map[j] = (byte) j;
11107 						ch_map[j + 1] = (byte)(j + 1);
11108 					}
11109 				}
11110 				for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11111 				{
11112 					i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11113 					j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11114 					if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11115 					{
11116 						*p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11117 							mixer_write_prog_bri[n].xconnect_override :
11118 							((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11119 						if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11120 						{
11121 							w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11122 							li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11123 						}
11124 					}
11125 					else
11126 					{
11127 						*p = 0x00;
11128 						if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11129 						{
11130 							w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11131 							if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11132 								*p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11133 						}
11134 					}
11135 					p++;
11136 				}
11137 			}
11138 			j = li_total_channels + 1;
11139 		}
11140 	}
11141 	else
11142 	{
11143 		if (j <= li_total_channels)
11144 		{
11145 			plci->internal_command = plci->li_write_command;
11146 			if (plci_nl_busy(plci))
11147 				return (true);
11148 			if (j < a->li_base)
11149 				j = a->li_base;
11150 			if (a->li_pri)
11151 			{
11152 				*(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11153 				w = 0;
11154 				if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11155 					w |= MIXER_FEATURE_ENABLE_TX_DATA;
11156 				if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11157 					w |= MIXER_FEATURE_ENABLE_RX_DATA;
11158 				*(p++) = (byte) w;
11159 				*(p++) = (byte)(w >> 8);
11160 				for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11161 				{
11162 					*(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11163 					for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11164 					{
11165 						w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11166 						if (w & mixer_write_prog_pri[n].mask)
11167 						{
11168 							*(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11169 							li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11170 						}
11171 						else
11172 							*(p++) = 0x00;
11173 					}
11174 					*(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11175 					for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11176 					{
11177 						w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11178 						if (w & mixer_write_prog_pri[n].mask)
11179 						{
11180 							*(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11181 							li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11182 						}
11183 						else
11184 							*(p++) = 0x00;
11185 					}
11186 				}
11187 			}
11188 			else
11189 			{
11190 				*(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11191 				w = 0;
11192 				if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11193 				    && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11194 				{
11195 					w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11196 				}
11197 				if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11198 					w |= MIXER_FEATURE_ENABLE_TX_DATA;
11199 				if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11200 					w |= MIXER_FEATURE_ENABLE_RX_DATA;
11201 				*(p++) = (byte) w;
11202 				*(p++) = (byte)(w >> 8);
11203 				for (j = 0; j < sizeof(ch_map); j += 2)
11204 				{
11205 					if (plci->li_bchannel_id == 2)
11206 					{
11207 						ch_map[j] = (byte)(j + 1);
11208 						ch_map[j + 1] = (byte) j;
11209 					}
11210 					else
11211 					{
11212 						ch_map[j] = (byte) j;
11213 						ch_map[j + 1] = (byte)(j + 1);
11214 					}
11215 				}
11216 				for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11217 				{
11218 					i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11219 					j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11220 					if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11221 					{
11222 						*p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11223 						w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11224 						li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11225 					}
11226 					else
11227 					{
11228 						*p = 0x00;
11229 						if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11230 						{
11231 							w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11232 							if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11233 								*p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11234 						}
11235 					}
11236 					p++;
11237 				}
11238 			}
11239 			j = li_total_channels + 1;
11240 		}
11241 	}
11242 	plci->li_write_channel = j;
11243 	if (p != plci->internal_req_buffer)
11244 	{
11245 		plci->NData[0].P = plci->internal_req_buffer;
11246 		plci->NData[0].PLength = p - plci->internal_req_buffer;
11247 		plci->NL.X = plci->NData;
11248 		plci->NL.ReqCh = 0;
11249 		plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11250 		plci->adapter->request(&plci->NL);
11251 	}
11252 	return (true);
11253 }
11254 
11255 
mixer_notify_update(PLCI * plci,byte others)11256 static void mixer_notify_update(PLCI *plci, byte others)
11257 {
11258 	DIVA_CAPI_ADAPTER *a;
11259 	word i, w;
11260 	PLCI *notify_plci;
11261 	byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11262 
11263 	dbug(1, dprintf("[%06lx] %s,%d: mixer_notify_update %d",
11264 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11265 			(char *)(FILE_), __LINE__, others));
11266 
11267 	a = plci->adapter;
11268 	if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11269 	{
11270 		if (others)
11271 			plci->li_notify_update = true;
11272 		i = 0;
11273 		do
11274 		{
11275 			notify_plci = NULL;
11276 			if (others)
11277 			{
11278 				while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11279 					i++;
11280 				if (i < li_total_channels)
11281 					notify_plci = li_config_table[i++].plci;
11282 			}
11283 			else
11284 			{
11285 				if ((plci->li_bchannel_id != 0)
11286 				    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11287 				{
11288 					notify_plci = plci;
11289 				}
11290 			}
11291 			if ((notify_plci != NULL)
11292 			    && !notify_plci->li_notify_update
11293 			    && (notify_plci->appl != NULL)
11294 			    && (notify_plci->State)
11295 			    && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11296 			{
11297 				notify_plci->li_notify_update = true;
11298 				((CAPI_MSG *) msg)->header.length = 18;
11299 				((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11300 				((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11301 				((CAPI_MSG *) msg)->header.number = 0;
11302 				((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11303 				((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11304 				((CAPI_MSG *) msg)->header.ncci = 0;
11305 				((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11306 				((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11307 				PUT_WORD(&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11308 				((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11309 				w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11310 				if (w != _QUEUE_FULL)
11311 				{
11312 					if (w != 0)
11313 					{
11314 						dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11315 								(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11316 								(char *)(FILE_), __LINE__,
11317 								(dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11318 					}
11319 					notify_plci->li_notify_update = false;
11320 				}
11321 			}
11322 		} while (others && (notify_plci != NULL));
11323 		if (others)
11324 			plci->li_notify_update = false;
11325 	}
11326 }
11327 
11328 
mixer_clear_config(PLCI * plci)11329 static void mixer_clear_config(PLCI *plci)
11330 {
11331 	DIVA_CAPI_ADAPTER *a;
11332 	word i, j;
11333 
11334 	dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11335 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11336 			(char *)(FILE_), __LINE__));
11337 
11338 	plci->li_notify_update = false;
11339 	plci->li_plci_b_write_pos = 0;
11340 	plci->li_plci_b_read_pos = 0;
11341 	plci->li_plci_b_req_pos = 0;
11342 	a = plci->adapter;
11343 	if ((plci->li_bchannel_id != 0)
11344 	    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11345 	{
11346 		i = a->li_base + (plci->li_bchannel_id - 1);
11347 		li_config_table[i].curchnl = 0;
11348 		li_config_table[i].channel = 0;
11349 		li_config_table[i].chflags = 0;
11350 		for (j = 0; j < li_total_channels; j++)
11351 		{
11352 			li_config_table[j].flag_table[i] = 0;
11353 			li_config_table[i].flag_table[j] = 0;
11354 			li_config_table[i].coef_table[j] = 0;
11355 			li_config_table[j].coef_table[i] = 0;
11356 		}
11357 		if (!a->li_pri)
11358 		{
11359 			li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11360 			if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11361 			{
11362 				i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11363 				li_config_table[i].curchnl = 0;
11364 				li_config_table[i].channel = 0;
11365 				li_config_table[i].chflags = 0;
11366 				for (j = 0; j < li_total_channels; j++)
11367 				{
11368 					li_config_table[i].flag_table[j] = 0;
11369 					li_config_table[j].flag_table[i] = 0;
11370 					li_config_table[i].coef_table[j] = 0;
11371 					li_config_table[j].coef_table[i] = 0;
11372 				}
11373 				if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11374 				{
11375 					i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11376 					li_config_table[i].curchnl = 0;
11377 					li_config_table[i].channel = 0;
11378 					li_config_table[i].chflags = 0;
11379 					for (j = 0; j < li_total_channels; j++)
11380 					{
11381 						li_config_table[i].flag_table[j] = 0;
11382 						li_config_table[j].flag_table[i] = 0;
11383 						li_config_table[i].coef_table[j] = 0;
11384 						li_config_table[j].coef_table[i] = 0;
11385 					}
11386 				}
11387 			}
11388 		}
11389 	}
11390 }
11391 
11392 
mixer_prepare_switch(dword Id,PLCI * plci)11393 static void mixer_prepare_switch(dword Id, PLCI *plci)
11394 {
11395 
11396 	dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11397 			UnMapId(Id), (char *)(FILE_), __LINE__));
11398 
11399 	do
11400 	{
11401 		mixer_indication_coefs_set(Id, plci);
11402 	} while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11403 }
11404 
11405 
mixer_save_config(dword Id,PLCI * plci,byte Rc)11406 static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11407 {
11408 	DIVA_CAPI_ADAPTER *a;
11409 	word i, j;
11410 
11411 	dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11412 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11413 
11414 	a = plci->adapter;
11415 	if ((plci->li_bchannel_id != 0)
11416 	    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11417 	{
11418 		i = a->li_base + (plci->li_bchannel_id - 1);
11419 		for (j = 0; j < li_total_channels; j++)
11420 		{
11421 			li_config_table[i].coef_table[j] &= 0xf;
11422 			li_config_table[j].coef_table[i] &= 0xf;
11423 		}
11424 		if (!a->li_pri)
11425 			li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11426 	}
11427 	return (GOOD);
11428 }
11429 
11430 
mixer_restore_config(dword Id,PLCI * plci,byte Rc)11431 static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11432 {
11433 	DIVA_CAPI_ADAPTER *a;
11434 	word Info;
11435 
11436 	dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11437 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11438 
11439 	Info = GOOD;
11440 	a = plci->adapter;
11441 	if ((plci->B1_facilities & B1_FACILITY_MIXER)
11442 	    && (plci->li_bchannel_id != 0)
11443 	    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11444 	{
11445 		switch (plci->adjust_b_state)
11446 		{
11447 		case ADJUST_B_RESTORE_MIXER_1:
11448 			if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11449 			{
11450 				plci->internal_command = plci->adjust_b_command;
11451 				if (plci_nl_busy(plci))
11452 				{
11453 					plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11454 					break;
11455 				}
11456 				xconnect_query_addresses(plci);
11457 				plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11458 				break;
11459 			}
11460 			plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11461 			Rc = OK;
11462 		case ADJUST_B_RESTORE_MIXER_2:
11463 		case ADJUST_B_RESTORE_MIXER_3:
11464 		case ADJUST_B_RESTORE_MIXER_4:
11465 			if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11466 			{
11467 				dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11468 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11469 				Info = _WRONG_STATE;
11470 				break;
11471 			}
11472 			if (Rc == OK)
11473 			{
11474 				if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11475 					plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11476 				else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11477 					plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11478 			}
11479 			else if (Rc == 0)
11480 			{
11481 				if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11482 					plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11483 				else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11484 					plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11485 			}
11486 			if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11487 			{
11488 				plci->internal_command = plci->adjust_b_command;
11489 				break;
11490 			}
11491 		case ADJUST_B_RESTORE_MIXER_5:
11492 			xconnect_write_coefs(plci, plci->adjust_b_command);
11493 			plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11494 			Rc = OK;
11495 		case ADJUST_B_RESTORE_MIXER_6:
11496 			if (!xconnect_write_coefs_process(Id, plci, Rc))
11497 			{
11498 				dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11499 						UnMapId(Id), (char *)(FILE_), __LINE__));
11500 				Info = _FACILITY_NOT_SUPPORTED;
11501 				break;
11502 			}
11503 			if (plci->internal_command)
11504 				break;
11505 			plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11506 		case ADJUST_B_RESTORE_MIXER_7:
11507 			break;
11508 		}
11509 	}
11510 	return (Info);
11511 }
11512 
11513 
mixer_command(dword Id,PLCI * plci,byte Rc)11514 static void mixer_command(dword Id, PLCI *plci, byte Rc)
11515 {
11516 	DIVA_CAPI_ADAPTER *a;
11517 	word i, internal_command;
11518 
11519 	dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11520 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11521 			plci->li_cmd));
11522 
11523 	a = plci->adapter;
11524 	internal_command = plci->internal_command;
11525 	plci->internal_command = 0;
11526 	switch (plci->li_cmd)
11527 	{
11528 	case LI_REQ_CONNECT:
11529 	case LI_REQ_DISCONNECT:
11530 	case LI_REQ_SILENT_UPDATE:
11531 		switch (internal_command)
11532 		{
11533 		default:
11534 			if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11535 			{
11536 				adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11537 									  B1_FACILITY_MIXER), MIXER_COMMAND_1);
11538 			}
11539 		case MIXER_COMMAND_1:
11540 			if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11541 			{
11542 				if (adjust_b_process(Id, plci, Rc) != GOOD)
11543 				{
11544 					dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11545 							UnMapId(Id), (char *)(FILE_), __LINE__));
11546 					break;
11547 				}
11548 				if (plci->internal_command)
11549 					return;
11550 			}
11551 			plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11552 			if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11553 			    || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11554 				&& (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11555 										      ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11556 			{
11557 				xconnect_write_coefs(plci, MIXER_COMMAND_2);
11558 			}
11559 			else
11560 			{
11561 				do
11562 				{
11563 					mixer_indication_coefs_set(Id, plci);
11564 				} while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11565 			}
11566 		case MIXER_COMMAND_2:
11567 			if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11568 			    || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11569 				&& (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11570 										      ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11571 			{
11572 				if (!xconnect_write_coefs_process(Id, plci, Rc))
11573 				{
11574 					dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11575 							UnMapId(Id), (char *)(FILE_), __LINE__));
11576 					if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11577 					{
11578 						do
11579 						{
11580 							plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11581 								LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11582 							i = (plci->li_plci_b_write_pos == 0) ?
11583 								LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11584 						} while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11585 							 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11586 					}
11587 					break;
11588 				}
11589 				if (plci->internal_command)
11590 					return;
11591 			}
11592 			if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11593 			{
11594 				adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11595 									  ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11596 			}
11597 		case MIXER_COMMAND_3:
11598 			if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11599 			{
11600 				if (adjust_b_process(Id, plci, Rc) != GOOD)
11601 				{
11602 					dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11603 							UnMapId(Id), (char *)(FILE_), __LINE__));
11604 					break;
11605 				}
11606 				if (plci->internal_command)
11607 					return;
11608 			}
11609 			break;
11610 		}
11611 		break;
11612 	}
11613 	if ((plci->li_bchannel_id == 0)
11614 	    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11615 	{
11616 		dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11617 				UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11618 	}
11619 	else
11620 	{
11621 		i = a->li_base + (plci->li_bchannel_id - 1);
11622 		li_config_table[i].curchnl = plci->li_channel_bits;
11623 		if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11624 		{
11625 			i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11626 			li_config_table[i].curchnl = plci->li_channel_bits;
11627 			if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11628 			{
11629 				i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11630 				li_config_table[i].curchnl = plci->li_channel_bits;
11631 			}
11632 		}
11633 	}
11634 }
11635 
11636 
li_update_connect(dword Id,DIVA_CAPI_ADAPTER * a,PLCI * plci,dword plci_b_id,byte connect,dword li_flags)11637 static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11638 			      dword plci_b_id, byte connect, dword li_flags)
11639 {
11640 	word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11641 	PLCI *plci_b;
11642 	DIVA_CAPI_ADAPTER *a_b;
11643 
11644 	a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11645 	plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11646 	ch_a = a->li_base + (plci->li_bchannel_id - 1);
11647 	if (!a->li_pri && (plci->tel == ADV_VOICE)
11648 	    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11649 	{
11650 		ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11651 		ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11652 			a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11653 	}
11654 	else
11655 	{
11656 		ch_a_v = ch_a;
11657 		ch_a_s = ch_a;
11658 	}
11659 	ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11660 	if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11661 	    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11662 	{
11663 		ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11664 		ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11665 			a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11666 	}
11667 	else
11668 	{
11669 		ch_b_v = ch_b;
11670 		ch_b_s = ch_b;
11671 	}
11672 	if (connect)
11673 	{
11674 		li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11675 		li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11676 		li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11677 		li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11678 	}
11679 	li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11680 	li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11681 	li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11682 	li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11683 	if (ch_a_v == ch_b_v)
11684 	{
11685 		li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11686 		li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11687 	}
11688 	else
11689 	{
11690 		if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11691 		{
11692 			for (i = 0; i < li_total_channels; i++)
11693 			{
11694 				if (i != ch_a_v)
11695 					li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11696 			}
11697 		}
11698 		if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11699 		{
11700 			for (i = 0; i < li_total_channels; i++)
11701 			{
11702 				if (i != ch_a_s)
11703 					li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11704 			}
11705 		}
11706 		if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11707 		{
11708 			for (i = 0; i < li_total_channels; i++)
11709 			{
11710 				if (i != ch_a_v)
11711 					li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11712 			}
11713 		}
11714 		if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11715 		{
11716 			for (i = 0; i < li_total_channels; i++)
11717 			{
11718 				if (i != ch_a_s)
11719 					li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11720 			}
11721 		}
11722 	}
11723 	if (li_flags & LI_FLAG_CONFERENCE_A_B)
11724 	{
11725 		li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11726 		li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11727 		li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11728 		li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11729 	}
11730 	if (li_flags & LI_FLAG_CONFERENCE_B_A)
11731 	{
11732 		li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11733 		li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11734 		li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11735 		li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11736 	}
11737 	if (li_flags & LI_FLAG_MONITOR_A)
11738 	{
11739 		li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11740 		li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11741 	}
11742 	if (li_flags & LI_FLAG_MONITOR_B)
11743 	{
11744 		li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11745 		li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11746 	}
11747 	if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11748 	{
11749 		li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11750 		li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11751 	}
11752 	if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11753 	{
11754 		li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11755 		li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11756 	}
11757 	if (li_flags & LI_FLAG_MIX_A)
11758 	{
11759 		li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11760 		li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11761 	}
11762 	if (li_flags & LI_FLAG_MIX_B)
11763 	{
11764 		li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11765 		li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11766 	}
11767 	if (ch_a_v != ch_a_s)
11768 	{
11769 		li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11770 		li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11771 	}
11772 	if (ch_b_v != ch_b_s)
11773 	{
11774 		li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11775 		li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11776 	}
11777 }
11778 
11779 
li2_update_connect(dword Id,DIVA_CAPI_ADAPTER * a,PLCI * plci,dword plci_b_id,byte connect,dword li_flags)11780 static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11781 			       dword plci_b_id, byte connect, dword li_flags)
11782 {
11783 	word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11784 	PLCI *plci_b;
11785 	DIVA_CAPI_ADAPTER *a_b;
11786 
11787 	a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11788 	plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11789 	ch_a = a->li_base + (plci->li_bchannel_id - 1);
11790 	if (!a->li_pri && (plci->tel == ADV_VOICE)
11791 	    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11792 	{
11793 		ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11794 		ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11795 			a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11796 	}
11797 	else
11798 	{
11799 		ch_a_v = ch_a;
11800 		ch_a_s = ch_a;
11801 	}
11802 	ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11803 	if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11804 	    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11805 	{
11806 		ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11807 		ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11808 			a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11809 	}
11810 	else
11811 	{
11812 		ch_b_v = ch_b;
11813 		ch_b_s = ch_b;
11814 	}
11815 	if (connect)
11816 	{
11817 		li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11818 		li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11819 		li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11820 		li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11821 		li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11822 		li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11823 	}
11824 	li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11825 	li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11826 	li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11827 	li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11828 	li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11829 	li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11830 	li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11831 	li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11832 	if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11833 	{
11834 		li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11835 		li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11836 		li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11837 		li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11838 	}
11839 	if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11840 	{
11841 		li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11842 		li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11843 		li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11844 		li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11845 	}
11846 	if (li_flags & LI2_FLAG_MONITOR_B)
11847 	{
11848 		li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11849 		li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11850 	}
11851 	if (li_flags & LI2_FLAG_MIX_B)
11852 	{
11853 		li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11854 		li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11855 	}
11856 	if (li_flags & LI2_FLAG_MONITOR_X)
11857 		li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11858 	if (li_flags & LI2_FLAG_MIX_X)
11859 		li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11860 	if (li_flags & LI2_FLAG_LOOP_B)
11861 	{
11862 		li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11863 		li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11864 		li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11865 		li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11866 	}
11867 	if (li_flags & LI2_FLAG_LOOP_PC)
11868 		li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11869 	if (li_flags & LI2_FLAG_LOOP_X)
11870 		li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11871 	if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11872 		li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11873 	if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11874 		li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11875 	if (ch_a_v != ch_a_s)
11876 	{
11877 		li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11878 		li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11879 	}
11880 	if (ch_b_v != ch_b_s)
11881 	{
11882 		li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11883 		li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11884 	}
11885 }
11886 
11887 
li_check_main_plci(dword Id,PLCI * plci)11888 static word li_check_main_plci(dword Id, PLCI *plci)
11889 {
11890 	if (plci == NULL)
11891 	{
11892 		dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11893 				UnMapId(Id), (char *)(FILE_), __LINE__));
11894 		return (_WRONG_IDENTIFIER);
11895 	}
11896 	if (!plci->State
11897 	    || !plci->NL.Id || plci->nl_remove_id
11898 	    || (plci->li_bchannel_id == 0))
11899 	{
11900 		dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11901 				UnMapId(Id), (char *)(FILE_), __LINE__));
11902 		return (_WRONG_STATE);
11903 	}
11904 	li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11905 	return (GOOD);
11906 }
11907 
11908 
li_check_plci_b(dword Id,PLCI * plci,dword plci_b_id,word plci_b_write_pos,byte * p_result)11909 static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11910 			     dword plci_b_id, word plci_b_write_pos, byte *p_result)
11911 {
11912 	byte ctlr_b;
11913 	PLCI *plci_b;
11914 
11915 	if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11916 	     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11917 	{
11918 		dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11919 				UnMapId(Id), (char *)(FILE_), __LINE__));
11920 		PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11921 		return (NULL);
11922 	}
11923 	ctlr_b = 0;
11924 	if ((plci_b_id & 0x7f) != 0)
11925 	{
11926 		ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11927 		if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11928 			ctlr_b = 0;
11929 	}
11930 	if ((ctlr_b == 0)
11931 	    || (((plci_b_id >> 8) & 0xff) == 0)
11932 	    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11933 	{
11934 		dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11935 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11936 		PUT_WORD(p_result, _WRONG_IDENTIFIER);
11937 		return (NULL);
11938 	}
11939 	plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11940 	if (!plci_b->State
11941 	    || !plci_b->NL.Id || plci_b->nl_remove_id
11942 	    || (plci_b->li_bchannel_id == 0))
11943 	{
11944 		dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11945 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11946 		PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11947 		return (NULL);
11948 	}
11949 	li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11950 	if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11951 	    ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11952 	    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11953 		|| !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11954 	{
11955 		dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11956 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11957 		PUT_WORD(p_result, _WRONG_IDENTIFIER);
11958 		return (NULL);
11959 	}
11960 	if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11961 							  (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11962 	{
11963 		dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11964 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11965 		PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11966 		return (NULL);
11967 	}
11968 	return (plci_b);
11969 }
11970 
11971 
li2_check_plci_b(dword Id,PLCI * plci,dword plci_b_id,word plci_b_write_pos,byte * p_result)11972 static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11973 			      dword plci_b_id, word plci_b_write_pos, byte *p_result)
11974 {
11975 	byte ctlr_b;
11976 	PLCI *plci_b;
11977 
11978 	if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11979 	     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11980 	{
11981 		dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11982 				UnMapId(Id), (char *)(FILE_), __LINE__));
11983 		PUT_WORD(p_result, _WRONG_STATE);
11984 		return (NULL);
11985 	}
11986 	ctlr_b = 0;
11987 	if ((plci_b_id & 0x7f) != 0)
11988 	{
11989 		ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11990 		if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11991 			ctlr_b = 0;
11992 	}
11993 	if ((ctlr_b == 0)
11994 	    || (((plci_b_id >> 8) & 0xff) == 0)
11995 	    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11996 	{
11997 		dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11998 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11999 		PUT_WORD(p_result, _WRONG_IDENTIFIER);
12000 		return (NULL);
12001 	}
12002 	plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
12003 	if (!plci_b->State
12004 	    || !plci_b->NL.Id || plci_b->nl_remove_id
12005 	    || (plci_b->li_bchannel_id == 0)
12006 	    || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12007 	{
12008 		dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
12009 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12010 		PUT_WORD(p_result, _WRONG_STATE);
12011 		return (NULL);
12012 	}
12013 	if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12014 	    ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
12015 	    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12016 		|| !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12017 	{
12018 		dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
12019 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12020 		PUT_WORD(p_result, _WRONG_IDENTIFIER);
12021 		return (NULL);
12022 	}
12023 	if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
12024 							  (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12025 	{
12026 		dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12027 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12028 		PUT_WORD(p_result, _WRONG_STATE);
12029 		return (NULL);
12030 	}
12031 	return (plci_b);
12032 }
12033 
12034 
mixer_request(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)12035 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
12036 {
12037 	word Info;
12038 	word i;
12039 	dword d, li_flags, plci_b_id;
12040 	PLCI *plci_b;
12041 	API_PARSE li_parms[3];
12042 	API_PARSE li_req_parms[3];
12043 	API_PARSE li_participant_struct[2];
12044 	API_PARSE li_participant_parms[3];
12045 	word participant_parms_pos;
12046 	byte result_buffer[32];
12047 	byte *result;
12048 	word result_pos;
12049 	word plci_b_write_pos;
12050 
12051 	dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
12052 			UnMapId(Id), (char *)(FILE_), __LINE__));
12053 
12054 	Info = GOOD;
12055 	result = result_buffer;
12056 	result_buffer[0] = 0;
12057 	if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12058 	{
12059 		dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12060 				UnMapId(Id), (char *)(FILE_), __LINE__));
12061 		Info = _FACILITY_NOT_SUPPORTED;
12062 	}
12063 	else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
12064 	{
12065 		dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12066 				UnMapId(Id), (char *)(FILE_), __LINE__));
12067 		Info = _WRONG_MESSAGE_FORMAT;
12068 	}
12069 	else
12070 	{
12071 		result_buffer[0] = 3;
12072 		PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
12073 		result_buffer[3] = 0;
12074 		switch (GET_WORD(li_parms[0].info))
12075 		{
12076 		case LI_GET_SUPPORTED_SERVICES:
12077 			if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12078 			{
12079 				result_buffer[0] = 17;
12080 				result_buffer[3] = 14;
12081 				PUT_WORD(&result_buffer[4], GOOD);
12082 				d = 0;
12083 				if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12084 					d |= LI_CONFERENCING_SUPPORTED;
12085 				if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12086 					d |= LI_MONITORING_SUPPORTED;
12087 				if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12088 					d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12089 				if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12090 					d |= LI_CROSS_CONTROLLER_SUPPORTED;
12091 				PUT_DWORD(&result_buffer[6], d);
12092 				if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12093 				{
12094 					d = 0;
12095 					for (i = 0; i < li_total_channels; i++)
12096 					{
12097 						if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12098 						    && (li_config_table[i].adapter->li_pri
12099 							|| (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12100 						{
12101 							d++;
12102 						}
12103 					}
12104 				}
12105 				else
12106 				{
12107 					d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12108 				}
12109 				PUT_DWORD(&result_buffer[10], d / 2);
12110 				PUT_DWORD(&result_buffer[14], d);
12111 			}
12112 			else
12113 			{
12114 				result_buffer[0] = 25;
12115 				result_buffer[3] = 22;
12116 				PUT_WORD(&result_buffer[4], GOOD);
12117 				d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12118 				if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12119 					d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12120 				if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12121 					d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12122 				if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12123 					d |= LI2_PC_LOOPING_SUPPORTED;
12124 				if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12125 					d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12126 				PUT_DWORD(&result_buffer[6], d);
12127 				d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12128 				PUT_DWORD(&result_buffer[10], d / 2);
12129 				PUT_DWORD(&result_buffer[14], d - 1);
12130 				if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12131 				{
12132 					d = 0;
12133 					for (i = 0; i < li_total_channels; i++)
12134 					{
12135 						if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12136 						    && (li_config_table[i].adapter->li_pri
12137 							|| (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12138 						{
12139 							d++;
12140 						}
12141 					}
12142 				}
12143 				PUT_DWORD(&result_buffer[18], d / 2);
12144 				PUT_DWORD(&result_buffer[22], d - 1);
12145 			}
12146 			break;
12147 
12148 		case LI_REQ_CONNECT:
12149 			if (li_parms[1].length == 8)
12150 			{
12151 				appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12152 				if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12153 				{
12154 					dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12155 							UnMapId(Id), (char *)(FILE_), __LINE__));
12156 					Info = _WRONG_MESSAGE_FORMAT;
12157 					break;
12158 				}
12159 				plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12160 				li_flags = GET_DWORD(li_req_parms[1].info);
12161 				Info = li_check_main_plci(Id, plci);
12162 				result_buffer[0] = 9;
12163 				result_buffer[3] = 6;
12164 				PUT_DWORD(&result_buffer[4], plci_b_id);
12165 				PUT_WORD(&result_buffer[8], GOOD);
12166 				if (Info != GOOD)
12167 					break;
12168 				result = plci->saved_msg.info;
12169 				for (i = 0; i <= result_buffer[0]; i++)
12170 					result[i] = result_buffer[i];
12171 				plci_b_write_pos = plci->li_plci_b_write_pos;
12172 				plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12173 				if (plci_b == NULL)
12174 					break;
12175 				li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12176 				plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12177 				plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12178 				plci->li_plci_b_write_pos = plci_b_write_pos;
12179 			}
12180 			else
12181 			{
12182 				appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12183 				if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12184 				{
12185 					dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12186 							UnMapId(Id), (char *)(FILE_), __LINE__));
12187 					Info = _WRONG_MESSAGE_FORMAT;
12188 					break;
12189 				}
12190 				li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12191 				Info = li_check_main_plci(Id, plci);
12192 				result_buffer[0] = 7;
12193 				result_buffer[3] = 4;
12194 				PUT_WORD(&result_buffer[4], Info);
12195 				result_buffer[6] = 0;
12196 				if (Info != GOOD)
12197 					break;
12198 				result = plci->saved_msg.info;
12199 				for (i = 0; i <= result_buffer[0]; i++)
12200 					result[i] = result_buffer[i];
12201 				plci_b_write_pos = plci->li_plci_b_write_pos;
12202 				participant_parms_pos = 0;
12203 				result_pos = 7;
12204 				li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12205 				while (participant_parms_pos < li_req_parms[1].length)
12206 				{
12207 					result[result_pos] = 6;
12208 					result_pos += 7;
12209 					PUT_DWORD(&result[result_pos - 6], 0);
12210 					PUT_WORD(&result[result_pos - 2], GOOD);
12211 					if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12212 						      (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12213 					{
12214 						dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12215 								UnMapId(Id), (char *)(FILE_), __LINE__));
12216 						PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12217 						break;
12218 					}
12219 					if (api_parse(&li_participant_struct[0].info[1],
12220 						      li_participant_struct[0].length, "dd", li_participant_parms))
12221 					{
12222 						dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12223 								UnMapId(Id), (char *)(FILE_), __LINE__));
12224 						PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12225 						break;
12226 					}
12227 					plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12228 					li_flags = GET_DWORD(li_participant_parms[1].info);
12229 					PUT_DWORD(&result[result_pos - 6], plci_b_id);
12230 					if (sizeof(result) - result_pos < 7)
12231 					{
12232 						dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12233 								UnMapId(Id), (char *)(FILE_), __LINE__));
12234 						PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12235 						break;
12236 					}
12237 					plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12238 					if (plci_b != NULL)
12239 					{
12240 						li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12241 						plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12242 							((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12243 								      LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12244 						plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12245 					}
12246 					participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12247 								       (&li_req_parms[1].info[1]));
12248 				}
12249 				result[0] = (byte)(result_pos - 1);
12250 				result[3] = (byte)(result_pos - 4);
12251 				result[6] = (byte)(result_pos - 7);
12252 				i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12253 				if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12254 				    || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12255 				{
12256 					plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12257 					plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12258 				}
12259 				else
12260 					plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12261 				plci->li_plci_b_write_pos = plci_b_write_pos;
12262 			}
12263 			mixer_calculate_coefs(a);
12264 			plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12265 			mixer_notify_update(plci, true);
12266 			sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12267 			      "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12268 			plci->command = 0;
12269 			plci->li_cmd = GET_WORD(li_parms[0].info);
12270 			start_internal_command(Id, plci, mixer_command);
12271 			return (false);
12272 
12273 		case LI_REQ_DISCONNECT:
12274 			if (li_parms[1].length == 4)
12275 			{
12276 				appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12277 				if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12278 				{
12279 					dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12280 							UnMapId(Id), (char *)(FILE_), __LINE__));
12281 					Info = _WRONG_MESSAGE_FORMAT;
12282 					break;
12283 				}
12284 				plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12285 				Info = li_check_main_plci(Id, plci);
12286 				result_buffer[0] = 9;
12287 				result_buffer[3] = 6;
12288 				PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12289 				PUT_WORD(&result_buffer[8], GOOD);
12290 				if (Info != GOOD)
12291 					break;
12292 				result = plci->saved_msg.info;
12293 				for (i = 0; i <= result_buffer[0]; i++)
12294 					result[i] = result_buffer[i];
12295 				plci_b_write_pos = plci->li_plci_b_write_pos;
12296 				plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12297 				if (plci_b == NULL)
12298 					break;
12299 				li_update_connect(Id, a, plci, plci_b_id, false, 0);
12300 				plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12301 				plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12302 				plci->li_plci_b_write_pos = plci_b_write_pos;
12303 			}
12304 			else
12305 			{
12306 				appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12307 				if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12308 				{
12309 					dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12310 							UnMapId(Id), (char *)(FILE_), __LINE__));
12311 					Info = _WRONG_MESSAGE_FORMAT;
12312 					break;
12313 				}
12314 				Info = li_check_main_plci(Id, plci);
12315 				result_buffer[0] = 7;
12316 				result_buffer[3] = 4;
12317 				PUT_WORD(&result_buffer[4], Info);
12318 				result_buffer[6] = 0;
12319 				if (Info != GOOD)
12320 					break;
12321 				result = plci->saved_msg.info;
12322 				for (i = 0; i <= result_buffer[0]; i++)
12323 					result[i] = result_buffer[i];
12324 				plci_b_write_pos = plci->li_plci_b_write_pos;
12325 				participant_parms_pos = 0;
12326 				result_pos = 7;
12327 				while (participant_parms_pos < li_req_parms[0].length)
12328 				{
12329 					result[result_pos] = 6;
12330 					result_pos += 7;
12331 					PUT_DWORD(&result[result_pos - 6], 0);
12332 					PUT_WORD(&result[result_pos - 2], GOOD);
12333 					if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12334 						      (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12335 					{
12336 						dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12337 								UnMapId(Id), (char *)(FILE_), __LINE__));
12338 						PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12339 						break;
12340 					}
12341 					if (api_parse(&li_participant_struct[0].info[1],
12342 						      li_participant_struct[0].length, "d", li_participant_parms))
12343 					{
12344 						dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12345 								UnMapId(Id), (char *)(FILE_), __LINE__));
12346 						PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12347 						break;
12348 					}
12349 					plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12350 					PUT_DWORD(&result[result_pos - 6], plci_b_id);
12351 					if (sizeof(result) - result_pos < 7)
12352 					{
12353 						dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12354 								UnMapId(Id), (char *)(FILE_), __LINE__));
12355 						PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12356 						break;
12357 					}
12358 					plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12359 					if (plci_b != NULL)
12360 					{
12361 						li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12362 						plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12363 						plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12364 					}
12365 					participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12366 								       (&li_req_parms[0].info[1]));
12367 				}
12368 				result[0] = (byte)(result_pos - 1);
12369 				result[3] = (byte)(result_pos - 4);
12370 				result[6] = (byte)(result_pos - 7);
12371 				i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12372 				if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12373 				    || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12374 				{
12375 					plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12376 					plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12377 				}
12378 				else
12379 					plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12380 				plci->li_plci_b_write_pos = plci_b_write_pos;
12381 			}
12382 			mixer_calculate_coefs(a);
12383 			plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12384 			mixer_notify_update(plci, true);
12385 			sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12386 			      "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12387 			plci->command = 0;
12388 			plci->li_cmd = GET_WORD(li_parms[0].info);
12389 			start_internal_command(Id, plci, mixer_command);
12390 			return (false);
12391 
12392 		case LI_REQ_SILENT_UPDATE:
12393 			if (!plci || !plci->State
12394 			    || !plci->NL.Id || plci->nl_remove_id
12395 			    || (plci->li_bchannel_id == 0)
12396 			    || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12397 			{
12398 				dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12399 						UnMapId(Id), (char *)(FILE_), __LINE__));
12400 				return (false);
12401 			}
12402 			plci_b_write_pos = plci->li_plci_b_write_pos;
12403 			if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12404 			     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12405 			{
12406 				dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12407 						UnMapId(Id), (char *)(FILE_), __LINE__));
12408 				return (false);
12409 			}
12410 			i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12411 			if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12412 			    || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12413 			{
12414 				plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12415 				plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12416 			}
12417 			else
12418 				plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12419 			plci->li_plci_b_write_pos = plci_b_write_pos;
12420 			plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12421 			plci->command = 0;
12422 			plci->li_cmd = GET_WORD(li_parms[0].info);
12423 			start_internal_command(Id, plci, mixer_command);
12424 			return (false);
12425 
12426 		default:
12427 			dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12428 					UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12429 			Info = _FACILITY_NOT_SUPPORTED;
12430 		}
12431 	}
12432 	sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12433 	      "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12434 	return (false);
12435 }
12436 
12437 
mixer_indication_coefs_set(dword Id,PLCI * plci)12438 static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12439 {
12440 	dword d;
12441 	byte result[12];
12442 
12443 	dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12444 			UnMapId(Id), (char *)(FILE_), __LINE__));
12445 
12446 	if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12447 	{
12448 		do
12449 		{
12450 			d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12451 			if (!(d & LI_PLCI_B_SKIP_FLAG))
12452 			{
12453 				if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12454 				{
12455 					if (d & LI_PLCI_B_DISC_FLAG)
12456 					{
12457 						result[0] = 5;
12458 						PUT_WORD(&result[1], LI_IND_DISCONNECT);
12459 						result[3] = 2;
12460 						PUT_WORD(&result[4], _LI_USER_INITIATED);
12461 					}
12462 					else
12463 					{
12464 						result[0] = 7;
12465 						PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12466 						result[3] = 4;
12467 						PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12468 					}
12469 				}
12470 				else
12471 				{
12472 					if (d & LI_PLCI_B_DISC_FLAG)
12473 					{
12474 						result[0] = 9;
12475 						PUT_WORD(&result[1], LI_IND_DISCONNECT);
12476 						result[3] = 6;
12477 						PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12478 						PUT_WORD(&result[8], _LI_USER_INITIATED);
12479 					}
12480 					else
12481 					{
12482 						result[0] = 7;
12483 						PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12484 						result[3] = 4;
12485 						PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12486 					}
12487 				}
12488 				sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12489 				      "ws", SELECTOR_LINE_INTERCONNECT, result);
12490 			}
12491 			plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12492 				0 : plci->li_plci_b_read_pos + 1;
12493 		} while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12494 	}
12495 }
12496 
12497 
mixer_indication_xconnect_from(dword Id,PLCI * plci,byte * msg,word length)12498 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12499 {
12500 	word i, j, ch;
12501 	struct xconnect_transfer_address_s s,   *p;
12502 	DIVA_CAPI_ADAPTER *a;
12503 
12504 	dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12505 			UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12506 
12507 	a = plci->adapter;
12508 	i = 1;
12509 	for (i = 1; i < length; i += 16)
12510 	{
12511 		s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12512 		s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12513 		s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12514 		ch = msg[i + 12] | (msg[i + 13] << 8);
12515 		j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12516 		if (!a->li_pri && (plci->li_bchannel_id == 2))
12517 			j = 1 - j;
12518 		j += a->li_base;
12519 		if (ch & XCONNECT_CHANNEL_PORT_PC)
12520 			p = &(li_config_table[j].send_pc);
12521 		else
12522 			p = &(li_config_table[j].send_b);
12523 		p->card_address.low = s.card_address.low;
12524 		p->card_address.high = s.card_address.high;
12525 		p->offset = s.offset;
12526 		li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12527 	}
12528 	if (plci->internal_command_queue[0]
12529 	    && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12530 		|| (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12531 		|| (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12532 	{
12533 		(*(plci->internal_command_queue[0]))(Id, plci, 0);
12534 		if (!plci->internal_command)
12535 			next_internal_command(Id, plci);
12536 	}
12537 	mixer_notify_update(plci, true);
12538 }
12539 
12540 
mixer_indication_xconnect_to(dword Id,PLCI * plci,byte * msg,word length)12541 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12542 {
12543 
12544 	dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12545 			UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12546 
12547 }
12548 
12549 
mixer_notify_source_removed(PLCI * plci,dword plci_b_id)12550 static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12551 {
12552 	word plci_b_write_pos;
12553 
12554 	plci_b_write_pos = plci->li_plci_b_write_pos;
12555 	if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12556 	     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12557 	{
12558 		dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12559 				(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12560 				(char *)(FILE_), __LINE__));
12561 		return (false);
12562 	}
12563 	plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12564 	plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12565 	plci->li_plci_b_write_pos = plci_b_write_pos;
12566 	return (true);
12567 }
12568 
12569 
mixer_remove(PLCI * plci)12570 static void mixer_remove(PLCI *plci)
12571 {
12572 	DIVA_CAPI_ADAPTER *a;
12573 	PLCI *notify_plci;
12574 	dword plci_b_id;
12575 	word i, j;
12576 
12577 	dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12578 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12579 			(char *)(FILE_), __LINE__));
12580 
12581 	a = plci->adapter;
12582 	plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12583 	if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12584 	{
12585 		if ((plci->li_bchannel_id != 0)
12586 		    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12587 		{
12588 			i = a->li_base + (plci->li_bchannel_id - 1);
12589 			if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12590 			{
12591 				for (j = 0; j < li_total_channels; j++)
12592 				{
12593 					if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12594 					    || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12595 					{
12596 						notify_plci = li_config_table[j].plci;
12597 						if ((notify_plci != NULL)
12598 						    && (notify_plci != plci)
12599 						    && (notify_plci->appl != NULL)
12600 						    && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12601 						    && (notify_plci->State)
12602 						    && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12603 						{
12604 							mixer_notify_source_removed(notify_plci, plci_b_id);
12605 						}
12606 					}
12607 				}
12608 				mixer_clear_config(plci);
12609 				mixer_calculate_coefs(a);
12610 				mixer_notify_update(plci, true);
12611 			}
12612 			li_config_table[i].plci = NULL;
12613 			plci->li_bchannel_id = 0;
12614 		}
12615 	}
12616 }
12617 
12618 
12619 /*------------------------------------------------------------------*/
12620 /* Echo canceller facilities                                        */
12621 /*------------------------------------------------------------------*/
12622 
12623 
ec_write_parameters(PLCI * plci)12624 static void ec_write_parameters(PLCI *plci)
12625 {
12626 	word w;
12627 	byte parameter_buffer[6];
12628 
12629 	dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12630 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12631 			(char *)(FILE_), __LINE__));
12632 
12633 	parameter_buffer[0] = 5;
12634 	parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12635 	PUT_WORD(&parameter_buffer[2], plci->ec_idi_options);
12636 	plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12637 	w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12638 	PUT_WORD(&parameter_buffer[4], w);
12639 	add_p(plci, FTY, parameter_buffer);
12640 	sig_req(plci, TEL_CTRL, 0);
12641 	send_req(plci);
12642 }
12643 
12644 
ec_clear_config(PLCI * plci)12645 static void ec_clear_config(PLCI *plci)
12646 {
12647 
12648 	dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12649 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12650 			(char *)(FILE_), __LINE__));
12651 
12652 	plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12653 		LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12654 	plci->ec_tail_length = 0;
12655 }
12656 
12657 
ec_prepare_switch(dword Id,PLCI * plci)12658 static void ec_prepare_switch(dword Id, PLCI *plci)
12659 {
12660 
12661 	dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12662 			UnMapId(Id), (char *)(FILE_), __LINE__));
12663 
12664 }
12665 
12666 
ec_save_config(dword Id,PLCI * plci,byte Rc)12667 static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12668 {
12669 
12670 	dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12671 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12672 
12673 	return (GOOD);
12674 }
12675 
12676 
ec_restore_config(dword Id,PLCI * plci,byte Rc)12677 static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12678 {
12679 	word Info;
12680 
12681 	dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12682 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12683 
12684 	Info = GOOD;
12685 	if (plci->B1_facilities & B1_FACILITY_EC)
12686 	{
12687 		switch (plci->adjust_b_state)
12688 		{
12689 		case ADJUST_B_RESTORE_EC_1:
12690 			plci->internal_command = plci->adjust_b_command;
12691 			if (plci->sig_req)
12692 			{
12693 				plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12694 				break;
12695 			}
12696 			ec_write_parameters(plci);
12697 			plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12698 			break;
12699 		case ADJUST_B_RESTORE_EC_2:
12700 			if ((Rc != OK) && (Rc != OK_FC))
12701 			{
12702 				dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12703 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12704 				Info = _WRONG_STATE;
12705 				break;
12706 			}
12707 			break;
12708 		}
12709 	}
12710 	return (Info);
12711 }
12712 
12713 
ec_command(dword Id,PLCI * plci,byte Rc)12714 static void ec_command(dword Id, PLCI *plci, byte Rc)
12715 {
12716 	word internal_command, Info;
12717 	byte result[8];
12718 
12719 	dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12720 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12721 			plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12722 
12723 	Info = GOOD;
12724 	if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12725 	{
12726 		result[0] = 2;
12727 		PUT_WORD(&result[1], EC_SUCCESS);
12728 	}
12729 	else
12730 	{
12731 		result[0] = 5;
12732 		PUT_WORD(&result[1], plci->ec_cmd);
12733 		result[3] = 2;
12734 		PUT_WORD(&result[4], GOOD);
12735 	}
12736 	internal_command = plci->internal_command;
12737 	plci->internal_command = 0;
12738 	switch (plci->ec_cmd)
12739 	{
12740 	case EC_ENABLE_OPERATION:
12741 	case EC_FREEZE_COEFFICIENTS:
12742 	case EC_RESUME_COEFFICIENT_UPDATE:
12743 	case EC_RESET_COEFFICIENTS:
12744 		switch (internal_command)
12745 		{
12746 		default:
12747 			adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12748 								  B1_FACILITY_EC), EC_COMMAND_1);
12749 		case EC_COMMAND_1:
12750 			if (adjust_b_process(Id, plci, Rc) != GOOD)
12751 			{
12752 				dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12753 						UnMapId(Id), (char *)(FILE_), __LINE__));
12754 				Info = _FACILITY_NOT_SUPPORTED;
12755 				break;
12756 			}
12757 			if (plci->internal_command)
12758 				return;
12759 		case EC_COMMAND_2:
12760 			if (plci->sig_req)
12761 			{
12762 				plci->internal_command = EC_COMMAND_2;
12763 				return;
12764 			}
12765 			plci->internal_command = EC_COMMAND_3;
12766 			ec_write_parameters(plci);
12767 			return;
12768 		case EC_COMMAND_3:
12769 			if ((Rc != OK) && (Rc != OK_FC))
12770 			{
12771 				dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12772 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12773 				Info = _FACILITY_NOT_SUPPORTED;
12774 				break;
12775 			}
12776 			break;
12777 		}
12778 		break;
12779 
12780 	case EC_DISABLE_OPERATION:
12781 		switch (internal_command)
12782 		{
12783 		default:
12784 		case EC_COMMAND_1:
12785 			if (plci->B1_facilities & B1_FACILITY_EC)
12786 			{
12787 				if (plci->sig_req)
12788 				{
12789 					plci->internal_command = EC_COMMAND_1;
12790 					return;
12791 				}
12792 				plci->internal_command = EC_COMMAND_2;
12793 				ec_write_parameters(plci);
12794 				return;
12795 			}
12796 			Rc = OK;
12797 		case EC_COMMAND_2:
12798 			if ((Rc != OK) && (Rc != OK_FC))
12799 			{
12800 				dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12801 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12802 				Info = _FACILITY_NOT_SUPPORTED;
12803 				break;
12804 			}
12805 			adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12806 								  ~B1_FACILITY_EC), EC_COMMAND_3);
12807 		case EC_COMMAND_3:
12808 			if (adjust_b_process(Id, plci, Rc) != GOOD)
12809 			{
12810 				dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12811 						UnMapId(Id), (char *)(FILE_), __LINE__));
12812 				Info = _FACILITY_NOT_SUPPORTED;
12813 				break;
12814 			}
12815 			if (plci->internal_command)
12816 				return;
12817 			break;
12818 		}
12819 		break;
12820 	}
12821 	sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12822 	      "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12823 	      PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12824 }
12825 
12826 
ec_request(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)12827 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
12828 {
12829 	word Info;
12830 	word opt;
12831 	API_PARSE ec_parms[3];
12832 	byte result[16];
12833 
12834 	dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12835 			UnMapId(Id), (char *)(FILE_), __LINE__));
12836 
12837 	Info = GOOD;
12838 	result[0] = 0;
12839 	if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12840 	{
12841 		dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12842 				UnMapId(Id), (char *)(FILE_), __LINE__));
12843 		Info = _FACILITY_NOT_SUPPORTED;
12844 	}
12845 	else
12846 	{
12847 		if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12848 		{
12849 			if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12850 			{
12851 				dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12852 						UnMapId(Id), (char *)(FILE_), __LINE__));
12853 				Info = _WRONG_MESSAGE_FORMAT;
12854 			}
12855 			else
12856 			{
12857 				if (plci == NULL)
12858 				{
12859 					dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12860 							UnMapId(Id), (char *)(FILE_), __LINE__));
12861 					Info = _WRONG_IDENTIFIER;
12862 				}
12863 				else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12864 				{
12865 					dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12866 							UnMapId(Id), (char *)(FILE_), __LINE__));
12867 					Info = _WRONG_STATE;
12868 				}
12869 				else
12870 				{
12871 					plci->command = 0;
12872 					plci->ec_cmd = GET_WORD(ec_parms[0].info);
12873 					plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12874 					result[0] = 2;
12875 					PUT_WORD(&result[1], EC_SUCCESS);
12876 					if (msg[1].length >= 4)
12877 					{
12878 						opt = GET_WORD(&ec_parms[0].info[2]);
12879 						plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12880 									  LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12881 						if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12882 							plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12883 						if (opt & EC_DETECT_DISABLE_TONE)
12884 							plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12885 						if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12886 							plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12887 						if (msg[1].length >= 6)
12888 						{
12889 							plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12890 						}
12891 					}
12892 					switch (plci->ec_cmd)
12893 					{
12894 					case EC_ENABLE_OPERATION:
12895 						plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12896 						start_internal_command(Id, plci, ec_command);
12897 						return (false);
12898 
12899 					case EC_DISABLE_OPERATION:
12900 						plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12901 							LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12902 							LEC_RESET_COEFFICIENTS;
12903 						start_internal_command(Id, plci, ec_command);
12904 						return (false);
12905 
12906 					case EC_FREEZE_COEFFICIENTS:
12907 						plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12908 						start_internal_command(Id, plci, ec_command);
12909 						return (false);
12910 
12911 					case EC_RESUME_COEFFICIENT_UPDATE:
12912 						plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12913 						start_internal_command(Id, plci, ec_command);
12914 						return (false);
12915 
12916 					case EC_RESET_COEFFICIENTS:
12917 						plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12918 						start_internal_command(Id, plci, ec_command);
12919 						return (false);
12920 
12921 					default:
12922 						dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12923 								UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12924 						PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12925 					}
12926 				}
12927 			}
12928 		}
12929 		else
12930 		{
12931 			if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12932 			{
12933 				dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12934 						UnMapId(Id), (char *)(FILE_), __LINE__));
12935 				Info = _WRONG_MESSAGE_FORMAT;
12936 			}
12937 			else
12938 			{
12939 				if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12940 				{
12941 					result[0] = 11;
12942 					PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12943 					result[3] = 8;
12944 					PUT_WORD(&result[4], GOOD);
12945 					PUT_WORD(&result[6], 0x0007);
12946 					PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12947 					PUT_WORD(&result[10], 0);
12948 				}
12949 				else if (plci == NULL)
12950 				{
12951 					dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12952 							UnMapId(Id), (char *)(FILE_), __LINE__));
12953 					Info = _WRONG_IDENTIFIER;
12954 				}
12955 				else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12956 				{
12957 					dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12958 							UnMapId(Id), (char *)(FILE_), __LINE__));
12959 					Info = _WRONG_STATE;
12960 				}
12961 				else
12962 				{
12963 					plci->command = 0;
12964 					plci->ec_cmd = GET_WORD(ec_parms[0].info);
12965 					plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12966 					result[0] = 5;
12967 					PUT_WORD(&result[1], plci->ec_cmd);
12968 					result[3] = 2;
12969 					PUT_WORD(&result[4], GOOD);
12970 					plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12971 								  LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12972 					plci->ec_tail_length = 0;
12973 					if (ec_parms[1].length >= 2)
12974 					{
12975 						opt = GET_WORD(&ec_parms[1].info[1]);
12976 						if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12977 							plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12978 						if (opt & EC_DETECT_DISABLE_TONE)
12979 							plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12980 						if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12981 							plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12982 						if (ec_parms[1].length >= 4)
12983 						{
12984 							plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12985 						}
12986 					}
12987 					switch (plci->ec_cmd)
12988 					{
12989 					case EC_ENABLE_OPERATION:
12990 						plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12991 						start_internal_command(Id, plci, ec_command);
12992 						return (false);
12993 
12994 					case EC_DISABLE_OPERATION:
12995 						plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12996 							LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12997 							LEC_RESET_COEFFICIENTS;
12998 						start_internal_command(Id, plci, ec_command);
12999 						return (false);
13000 
13001 					default:
13002 						dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
13003 								UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
13004 						PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13005 					}
13006 				}
13007 			}
13008 		}
13009 	}
13010 	sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13011 	      "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13012 	      PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13013 	return (false);
13014 }
13015 
13016 
ec_indication(dword Id,PLCI * plci,byte * msg,word length)13017 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
13018 {
13019 	byte result[8];
13020 
13021 	dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
13022 			UnMapId(Id), (char *)(FILE_), __LINE__));
13023 
13024 	if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13025 	{
13026 		if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13027 		{
13028 			result[0] = 2;
13029 			PUT_WORD(&result[1], 0);
13030 			switch (msg[1])
13031 			{
13032 			case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13033 				PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13034 				break;
13035 			case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13036 				PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13037 				break;
13038 			case LEC_DISABLE_RELEASED:
13039 				PUT_WORD(&result[1], EC_BYPASS_RELEASED);
13040 				break;
13041 			}
13042 		}
13043 		else
13044 		{
13045 			result[0] = 5;
13046 			PUT_WORD(&result[1], EC_BYPASS_INDICATION);
13047 			result[3] = 2;
13048 			PUT_WORD(&result[4], 0);
13049 			switch (msg[1])
13050 			{
13051 			case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13052 				PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13053 				break;
13054 			case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13055 				PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13056 				break;
13057 			case LEC_DISABLE_RELEASED:
13058 				PUT_WORD(&result[4], EC_BYPASS_RELEASED);
13059 				break;
13060 			}
13061 		}
13062 		sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13063 		      PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13064 	}
13065 }
13066 
13067 
13068 
13069 /*------------------------------------------------------------------*/
13070 /* Advanced voice                                                   */
13071 /*------------------------------------------------------------------*/
13072 
adv_voice_write_coefs(PLCI * plci,word write_command)13073 static void adv_voice_write_coefs(PLCI *plci, word write_command)
13074 {
13075 	DIVA_CAPI_ADAPTER *a;
13076 	word i;
13077 	byte *p;
13078 
13079 	word w, n, j, k;
13080 	byte ch_map[MIXER_CHANNELS_BRI];
13081 
13082 	byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13083 
13084 	dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
13085 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13086 			(char *)(FILE_), __LINE__, write_command));
13087 
13088 	a = plci->adapter;
13089 	p = coef_buffer + 1;
13090 	*(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13091 	i = 0;
13092 	while (i + sizeof(word) <= a->adv_voice_coef_length)
13093 	{
13094 		PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
13095 		p += 2;
13096 		i += 2;
13097 	}
13098 	while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13099 	{
13100 		PUT_WORD(p, 0x8000);
13101 		p += 2;
13102 		i += 2;
13103 	}
13104 
13105 	if (!a->li_pri && (plci->li_bchannel_id == 0))
13106 	{
13107 		if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13108 		{
13109 			plci->li_bchannel_id = 1;
13110 			li_config_table[a->li_base].plci = plci;
13111 			dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13112 					(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13113 					(char *)(FILE_), __LINE__, plci->li_bchannel_id));
13114 		}
13115 		else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13116 		{
13117 			plci->li_bchannel_id = 2;
13118 			li_config_table[a->li_base + 1].plci = plci;
13119 			dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13120 					(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13121 					(char *)(FILE_), __LINE__, plci->li_bchannel_id));
13122 		}
13123 	}
13124 	if (!a->li_pri && (plci->li_bchannel_id != 0)
13125 	    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13126 	{
13127 		i = a->li_base + (plci->li_bchannel_id - 1);
13128 		switch (write_command)
13129 		{
13130 		case ADV_VOICE_WRITE_ACTIVATION:
13131 			j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13132 			k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13133 			if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13134 			{
13135 				li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13136 				li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13137 			}
13138 			if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13139 			{
13140 				li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13141 				li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13142 				li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13143 				li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13144 			}
13145 			mixer_calculate_coefs(a);
13146 			li_config_table[i].curchnl = li_config_table[i].channel;
13147 			li_config_table[j].curchnl = li_config_table[j].channel;
13148 			if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13149 				li_config_table[k].curchnl = li_config_table[k].channel;
13150 			break;
13151 
13152 		case ADV_VOICE_WRITE_DEACTIVATION:
13153 			for (j = 0; j < li_total_channels; j++)
13154 			{
13155 				li_config_table[i].flag_table[j] = 0;
13156 				li_config_table[j].flag_table[i] = 0;
13157 			}
13158 			k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13159 			for (j = 0; j < li_total_channels; j++)
13160 			{
13161 				li_config_table[k].flag_table[j] = 0;
13162 				li_config_table[j].flag_table[k] = 0;
13163 			}
13164 			if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13165 			{
13166 				k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13167 				for (j = 0; j < li_total_channels; j++)
13168 				{
13169 					li_config_table[k].flag_table[j] = 0;
13170 					li_config_table[j].flag_table[k] = 0;
13171 				}
13172 			}
13173 			mixer_calculate_coefs(a);
13174 			break;
13175 		}
13176 		if (plci->B1_facilities & B1_FACILITY_MIXER)
13177 		{
13178 			w = 0;
13179 			if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13180 				w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13181 			if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13182 				w |= MIXER_FEATURE_ENABLE_TX_DATA;
13183 			if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13184 				w |= MIXER_FEATURE_ENABLE_RX_DATA;
13185 			*(p++) = (byte) w;
13186 			*(p++) = (byte)(w >> 8);
13187 			for (j = 0; j < sizeof(ch_map); j += 2)
13188 			{
13189 				ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13190 				ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13191 			}
13192 			for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13193 			{
13194 				i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13195 				j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13196 				if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13197 				{
13198 					*(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13199 					w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13200 					li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13201 				}
13202 				else
13203 				{
13204 					*(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13205 						a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13206 				}
13207 			}
13208 		}
13209 		else
13210 		{
13211 			for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13212 				*(p++) = a->adv_voice_coef_buffer[i];
13213 		}
13214 	}
13215 	else
13216 
13217 	{
13218 		for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13219 			*(p++) = a->adv_voice_coef_buffer[i];
13220 	}
13221 	coef_buffer[0] = (p - coef_buffer) - 1;
13222 	add_p(plci, FTY, coef_buffer);
13223 	sig_req(plci, TEL_CTRL, 0);
13224 	send_req(plci);
13225 }
13226 
13227 
adv_voice_clear_config(PLCI * plci)13228 static void adv_voice_clear_config(PLCI *plci)
13229 {
13230 	DIVA_CAPI_ADAPTER *a;
13231 
13232 	word i, j;
13233 
13234 
13235 	dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13236 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13237 			(char *)(FILE_), __LINE__));
13238 
13239 	a = plci->adapter;
13240 	if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13241 	{
13242 		a->adv_voice_coef_length = 0;
13243 
13244 		if (!a->li_pri && (plci->li_bchannel_id != 0)
13245 		    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13246 		{
13247 			i = a->li_base + (plci->li_bchannel_id - 1);
13248 			li_config_table[i].curchnl = 0;
13249 			li_config_table[i].channel = 0;
13250 			li_config_table[i].chflags = 0;
13251 			for (j = 0; j < li_total_channels; j++)
13252 			{
13253 				li_config_table[i].flag_table[j] = 0;
13254 				li_config_table[j].flag_table[i] = 0;
13255 				li_config_table[i].coef_table[j] = 0;
13256 				li_config_table[j].coef_table[i] = 0;
13257 			}
13258 			li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13259 			i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13260 			li_config_table[i].curchnl = 0;
13261 			li_config_table[i].channel = 0;
13262 			li_config_table[i].chflags = 0;
13263 			for (j = 0; j < li_total_channels; j++)
13264 			{
13265 				li_config_table[i].flag_table[j] = 0;
13266 				li_config_table[j].flag_table[i] = 0;
13267 				li_config_table[i].coef_table[j] = 0;
13268 				li_config_table[j].coef_table[i] = 0;
13269 			}
13270 			if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13271 			{
13272 				i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13273 				li_config_table[i].curchnl = 0;
13274 				li_config_table[i].channel = 0;
13275 				li_config_table[i].chflags = 0;
13276 				for (j = 0; j < li_total_channels; j++)
13277 				{
13278 					li_config_table[i].flag_table[j] = 0;
13279 					li_config_table[j].flag_table[i] = 0;
13280 					li_config_table[i].coef_table[j] = 0;
13281 					li_config_table[j].coef_table[i] = 0;
13282 				}
13283 			}
13284 		}
13285 
13286 	}
13287 }
13288 
13289 
adv_voice_prepare_switch(dword Id,PLCI * plci)13290 static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13291 {
13292 
13293 	dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13294 			UnMapId(Id), (char *)(FILE_), __LINE__));
13295 
13296 }
13297 
13298 
adv_voice_save_config(dword Id,PLCI * plci,byte Rc)13299 static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13300 {
13301 
13302 	dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13303 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13304 
13305 	return (GOOD);
13306 }
13307 
13308 
adv_voice_restore_config(dword Id,PLCI * plci,byte Rc)13309 static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13310 {
13311 	DIVA_CAPI_ADAPTER *a;
13312 	word Info;
13313 
13314 	dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13315 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13316 
13317 	Info = GOOD;
13318 	a = plci->adapter;
13319 	if ((plci->B1_facilities & B1_FACILITY_VOICE)
13320 	    && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13321 	{
13322 		switch (plci->adjust_b_state)
13323 		{
13324 		case ADJUST_B_RESTORE_VOICE_1:
13325 			plci->internal_command = plci->adjust_b_command;
13326 			if (plci->sig_req)
13327 			{
13328 				plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13329 				break;
13330 			}
13331 			adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13332 			plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13333 			break;
13334 		case ADJUST_B_RESTORE_VOICE_2:
13335 			if ((Rc != OK) && (Rc != OK_FC))
13336 			{
13337 				dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13338 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13339 				Info = _WRONG_STATE;
13340 				break;
13341 			}
13342 			break;
13343 		}
13344 	}
13345 	return (Info);
13346 }
13347 
13348 
13349 
13350 
13351 /*------------------------------------------------------------------*/
13352 /* B1 resource switching                                            */
13353 /*------------------------------------------------------------------*/
13354 
13355 static byte b1_facilities_table[] =
13356 {
13357 	0x00,  /* 0  No bchannel resources      */
13358 	0x00,  /* 1  Codec (automatic law)      */
13359 	0x00,  /* 2  Codec (A-law)              */
13360 	0x00,  /* 3  Codec (y-law)              */
13361 	0x00,  /* 4  HDLC for X.21              */
13362 	0x00,  /* 5  HDLC                       */
13363 	0x00,  /* 6  External Device 0          */
13364 	0x00,  /* 7  External Device 1          */
13365 	0x00,  /* 8  HDLC 56k                   */
13366 	0x00,  /* 9  Transparent                */
13367 	0x00,  /* 10 Loopback to network        */
13368 	0x00,  /* 11 Test pattern to net        */
13369 	0x00,  /* 12 Rate adaptation sync       */
13370 	0x00,  /* 13 Rate adaptation async      */
13371 	0x00,  /* 14 R-Interface                */
13372 	0x00,  /* 15 HDLC 128k leased line      */
13373 	0x00,  /* 16 FAX                        */
13374 	0x00,  /* 17 Modem async                */
13375 	0x00,  /* 18 Modem sync HDLC            */
13376 	0x00,  /* 19 V.110 async HDLC           */
13377 	0x12,  /* 20 Adv voice (Trans,mixer)    */
13378 	0x00,  /* 21 Codec connected to IC      */
13379 	0x0c,  /* 22 Trans,DTMF                 */
13380 	0x1e,  /* 23 Trans,DTMF+mixer           */
13381 	0x1f,  /* 24 Trans,DTMF+mixer+local     */
13382 	0x13,  /* 25 Trans,mixer+local          */
13383 	0x12,  /* 26 HDLC,mixer                 */
13384 	0x12,  /* 27 HDLC 56k,mixer             */
13385 	0x2c,  /* 28 Trans,LEC+DTMF             */
13386 	0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13387 	0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13388 	0x2c,  /* 31 RTP,LEC+DTMF               */
13389 	0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13390 	0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13391 	0x00,  /* 34 Signaling task             */
13392 	0x00,  /* 35 PIAFS                      */
13393 	0x0c,  /* 36 Trans,DTMF+TONE            */
13394 	0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13395 	0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13396 };
13397 
13398 
get_b1_facilities(PLCI * plci,byte b1_resource)13399 static word get_b1_facilities(PLCI *plci, byte b1_resource)
13400 {
13401 	word b1_facilities;
13402 
13403 	b1_facilities = b1_facilities_table[b1_resource];
13404 	if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13405 	{
13406 
13407 		if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13408 		      || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13409 
13410 		{
13411 			if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13412 				b1_facilities |= B1_FACILITY_DTMFX;
13413 			if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13414 				b1_facilities |= B1_FACILITY_DTMFR;
13415 		}
13416 	}
13417 	if ((b1_resource == 17) || (b1_resource == 18))
13418 	{
13419 		if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13420 			b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13421 	}
13422 /*
13423   dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13424   (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13425   (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13426 */
13427 	return (b1_facilities);
13428 }
13429 
13430 
add_b1_facilities(PLCI * plci,byte b1_resource,word b1_facilities)13431 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13432 {
13433 	byte b;
13434 
13435 	switch (b1_resource)
13436 	{
13437 	case 5:
13438 	case 26:
13439 		if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13440 			b = 26;
13441 		else
13442 			b = 5;
13443 		break;
13444 
13445 	case 8:
13446 	case 27:
13447 		if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13448 			b = 27;
13449 		else
13450 			b = 8;
13451 		break;
13452 
13453 	case 9:
13454 	case 20:
13455 	case 22:
13456 	case 23:
13457 	case 24:
13458 	case 25:
13459 	case 28:
13460 	case 29:
13461 	case 30:
13462 	case 36:
13463 	case 37:
13464 	case 38:
13465 		if (b1_facilities & B1_FACILITY_EC)
13466 		{
13467 			if (b1_facilities & B1_FACILITY_LOCAL)
13468 				b = 30;
13469 			else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13470 				b = 29;
13471 			else
13472 				b = 28;
13473 		}
13474 
13475 		else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13476 			 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13477 			     || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13478 		{
13479 			if (b1_facilities & B1_FACILITY_LOCAL)
13480 				b = 38;
13481 			else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13482 				b = 37;
13483 			else
13484 				b = 36;
13485 		}
13486 
13487 		else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13488 			  && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13489 			 || ((b1_facilities & B1_FACILITY_DTMFR)
13490 			     && ((b1_facilities & B1_FACILITY_MIXER)
13491 				 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13492 			 || ((b1_facilities & B1_FACILITY_DTMFX)
13493 			     && ((b1_facilities & B1_FACILITY_MIXER)
13494 				 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13495 		{
13496 			if (b1_facilities & B1_FACILITY_LOCAL)
13497 				b = 24;
13498 			else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13499 				b = 23;
13500 			else
13501 				b = 22;
13502 		}
13503 		else
13504 		{
13505 			if (b1_facilities & B1_FACILITY_LOCAL)
13506 				b = 25;
13507 			else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13508 				b = 20;
13509 			else
13510 				b = 9;
13511 		}
13512 		break;
13513 
13514 	case 31:
13515 	case 32:
13516 	case 33:
13517 		if (b1_facilities & B1_FACILITY_LOCAL)
13518 			b = 33;
13519 		else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13520 			b = 32;
13521 		else
13522 			b = 31;
13523 		break;
13524 
13525 	default:
13526 		b = b1_resource;
13527 	}
13528 	dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13529 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13530 			(char *)(FILE_), __LINE__,
13531 			b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13532 	return (b);
13533 }
13534 
13535 
adjust_b1_facilities(PLCI * plci,byte new_b1_resource,word new_b1_facilities)13536 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13537 {
13538 	word removed_facilities;
13539 
13540 	dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13541 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13542 			(char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13543 			new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13544 
13545 	new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13546 	removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13547 
13548 	if (removed_facilities & B1_FACILITY_EC)
13549 		ec_clear_config(plci);
13550 
13551 
13552 	if (removed_facilities & B1_FACILITY_DTMFR)
13553 	{
13554 		dtmf_rec_clear_config(plci);
13555 		dtmf_parameter_clear_config(plci);
13556 	}
13557 	if (removed_facilities & B1_FACILITY_DTMFX)
13558 		dtmf_send_clear_config(plci);
13559 
13560 
13561 	if (removed_facilities & B1_FACILITY_MIXER)
13562 		mixer_clear_config(plci);
13563 
13564 	if (removed_facilities & B1_FACILITY_VOICE)
13565 		adv_voice_clear_config(plci);
13566 	plci->B1_facilities = new_b1_facilities;
13567 }
13568 
13569 
adjust_b_clear(PLCI * plci)13570 static void adjust_b_clear(PLCI *plci)
13571 {
13572 
13573 	dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13574 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13575 			(char *)(FILE_), __LINE__));
13576 
13577 	plci->adjust_b_restore = false;
13578 }
13579 
13580 
adjust_b_process(dword Id,PLCI * plci,byte Rc)13581 static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13582 {
13583 	word Info;
13584 	byte b1_resource;
13585 	NCCI *ncci_ptr;
13586 	API_PARSE bp[2];
13587 
13588 	dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13589 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13590 
13591 	Info = GOOD;
13592 	switch (plci->adjust_b_state)
13593 	{
13594 	case ADJUST_B_START:
13595 		if ((plci->adjust_b_parms_msg == NULL)
13596 		    && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13597 		    && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13598 						 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13599 		{
13600 			b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13601 				0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13602 			if (b1_resource == plci->B1_resource)
13603 			{
13604 				adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13605 				break;
13606 			}
13607 			if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13608 			{
13609 				dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13610 						UnMapId(Id), (char *)(FILE_), __LINE__,
13611 						plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13612 				Info = _WRONG_STATE;
13613 				break;
13614 			}
13615 		}
13616 		if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13617 		{
13618 
13619 			mixer_prepare_switch(Id, plci);
13620 
13621 
13622 			dtmf_prepare_switch(Id, plci);
13623 			dtmf_parameter_prepare_switch(Id, plci);
13624 
13625 
13626 			ec_prepare_switch(Id, plci);
13627 
13628 			adv_voice_prepare_switch(Id, plci);
13629 		}
13630 		plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13631 		Rc = OK;
13632 	case ADJUST_B_SAVE_MIXER_1:
13633 		if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13634 		{
13635 
13636 			Info = mixer_save_config(Id, plci, Rc);
13637 			if ((Info != GOOD) || plci->internal_command)
13638 				break;
13639 
13640 		}
13641 		plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13642 		Rc = OK;
13643 	case ADJUST_B_SAVE_DTMF_1:
13644 		if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13645 		{
13646 
13647 			Info = dtmf_save_config(Id, plci, Rc);
13648 			if ((Info != GOOD) || plci->internal_command)
13649 				break;
13650 
13651 		}
13652 		plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13653 	case ADJUST_B_REMOVE_L23_1:
13654 		if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13655 		    && plci->NL.Id && !plci->nl_remove_id)
13656 		{
13657 			plci->internal_command = plci->adjust_b_command;
13658 			if (plci->adjust_b_ncci != 0)
13659 			{
13660 				ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13661 				while (ncci_ptr->data_pending)
13662 				{
13663 					plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13664 					data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13665 				}
13666 				while (ncci_ptr->data_ack_pending)
13667 					data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13668 			}
13669 			nl_req_ncci(plci, REMOVE,
13670 				    (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13671 			send_req(plci);
13672 			plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13673 			break;
13674 		}
13675 		plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13676 		Rc = OK;
13677 	case ADJUST_B_REMOVE_L23_2:
13678 		if ((Rc != OK) && (Rc != OK_FC))
13679 		{
13680 			dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13681 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13682 			Info = _WRONG_STATE;
13683 			break;
13684 		}
13685 		if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13686 		{
13687 			if (plci_nl_busy(plci))
13688 			{
13689 				plci->internal_command = plci->adjust_b_command;
13690 				break;
13691 			}
13692 		}
13693 		plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13694 		Rc = OK;
13695 	case ADJUST_B_SAVE_EC_1:
13696 		if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13697 		{
13698 
13699 			Info = ec_save_config(Id, plci, Rc);
13700 			if ((Info != GOOD) || plci->internal_command)
13701 				break;
13702 
13703 		}
13704 		plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13705 		Rc = OK;
13706 	case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13707 		if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13708 		{
13709 
13710 			Info = dtmf_parameter_save_config(Id, plci, Rc);
13711 			if ((Info != GOOD) || plci->internal_command)
13712 				break;
13713 
13714 		}
13715 		plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13716 		Rc = OK;
13717 	case ADJUST_B_SAVE_VOICE_1:
13718 		if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13719 		{
13720 			Info = adv_voice_save_config(Id, plci, Rc);
13721 			if ((Info != GOOD) || plci->internal_command)
13722 				break;
13723 		}
13724 		plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13725 	case ADJUST_B_SWITCH_L1_1:
13726 		if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13727 		{
13728 			if (plci->sig_req)
13729 			{
13730 				plci->internal_command = plci->adjust_b_command;
13731 				break;
13732 			}
13733 			if (plci->adjust_b_parms_msg != NULL)
13734 				api_load_msg(plci->adjust_b_parms_msg, bp);
13735 			else
13736 				api_load_msg(&plci->B_protocol, bp);
13737 			Info = add_b1(plci, bp,
13738 				      (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13739 				      plci->adjust_b_facilities);
13740 			if (Info != GOOD)
13741 			{
13742 				dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13743 						UnMapId(Id), (char *)(FILE_), __LINE__,
13744 						plci->B1_resource, plci->adjust_b_facilities));
13745 				break;
13746 			}
13747 			plci->internal_command = plci->adjust_b_command;
13748 			sig_req(plci, RESOURCES, 0);
13749 			send_req(plci);
13750 			plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13751 			break;
13752 		}
13753 		plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13754 		Rc = OK;
13755 	case ADJUST_B_SWITCH_L1_2:
13756 		if ((Rc != OK) && (Rc != OK_FC))
13757 		{
13758 			dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13759 					UnMapId(Id), (char *)(FILE_), __LINE__,
13760 					Rc, plci->B1_resource, plci->adjust_b_facilities));
13761 			Info = _WRONG_STATE;
13762 			break;
13763 		}
13764 		plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13765 		Rc = OK;
13766 	case ADJUST_B_RESTORE_VOICE_1:
13767 	case ADJUST_B_RESTORE_VOICE_2:
13768 		if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13769 		{
13770 			Info = adv_voice_restore_config(Id, plci, Rc);
13771 			if ((Info != GOOD) || plci->internal_command)
13772 				break;
13773 		}
13774 		plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13775 		Rc = OK;
13776 	case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13777 	case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13778 		if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13779 		{
13780 
13781 			Info = dtmf_parameter_restore_config(Id, plci, Rc);
13782 			if ((Info != GOOD) || plci->internal_command)
13783 				break;
13784 
13785 		}
13786 		plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13787 		Rc = OK;
13788 	case ADJUST_B_RESTORE_EC_1:
13789 	case ADJUST_B_RESTORE_EC_2:
13790 		if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13791 		{
13792 
13793 			Info = ec_restore_config(Id, plci, Rc);
13794 			if ((Info != GOOD) || plci->internal_command)
13795 				break;
13796 
13797 		}
13798 		plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13799 	case ADJUST_B_ASSIGN_L23_1:
13800 		if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13801 		{
13802 			if (plci_nl_busy(plci))
13803 			{
13804 				plci->internal_command = plci->adjust_b_command;
13805 				break;
13806 			}
13807 			if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13808 				plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13809 			if (plci->adjust_b_parms_msg != NULL)
13810 				api_load_msg(plci->adjust_b_parms_msg, bp);
13811 			else
13812 				api_load_msg(&plci->B_protocol, bp);
13813 			Info = add_b23(plci, bp);
13814 			if (Info != GOOD)
13815 			{
13816 				dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13817 						UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13818 				break;
13819 			}
13820 			plci->internal_command = plci->adjust_b_command;
13821 			nl_req_ncci(plci, ASSIGN, 0);
13822 			send_req(plci);
13823 			plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13824 			break;
13825 		}
13826 		plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13827 		Rc = ASSIGN_OK;
13828 	case ADJUST_B_ASSIGN_L23_2:
13829 		if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13830 		{
13831 			dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13832 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13833 			Info = _WRONG_STATE;
13834 			break;
13835 		}
13836 		if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13837 		{
13838 			if (Rc != ASSIGN_OK)
13839 			{
13840 				plci->internal_command = plci->adjust_b_command;
13841 				break;
13842 			}
13843 		}
13844 		if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13845 		{
13846 			plci->adjust_b_restore = true;
13847 			break;
13848 		}
13849 		plci->adjust_b_state = ADJUST_B_CONNECT_1;
13850 	case ADJUST_B_CONNECT_1:
13851 		if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13852 		{
13853 			plci->internal_command = plci->adjust_b_command;
13854 			if (plci_nl_busy(plci))
13855 				break;
13856 			nl_req_ncci(plci, N_CONNECT, 0);
13857 			send_req(plci);
13858 			plci->adjust_b_state = ADJUST_B_CONNECT_2;
13859 			break;
13860 		}
13861 		plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13862 		Rc = OK;
13863 	case ADJUST_B_CONNECT_2:
13864 	case ADJUST_B_CONNECT_3:
13865 	case ADJUST_B_CONNECT_4:
13866 		if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13867 		{
13868 			dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13869 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13870 			Info = _WRONG_STATE;
13871 			break;
13872 		}
13873 		if (Rc == OK)
13874 		{
13875 			if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13876 			{
13877 				get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13878 				Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13879 			}
13880 			if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13881 				plci->adjust_b_state = ADJUST_B_CONNECT_3;
13882 			else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13883 				plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13884 		}
13885 		else if (Rc == 0)
13886 		{
13887 			if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13888 				plci->adjust_b_state = ADJUST_B_CONNECT_4;
13889 			else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13890 				plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13891 		}
13892 		if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13893 		{
13894 			plci->internal_command = plci->adjust_b_command;
13895 			break;
13896 		}
13897 		Rc = OK;
13898 	case ADJUST_B_RESTORE_DTMF_1:
13899 	case ADJUST_B_RESTORE_DTMF_2:
13900 		if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13901 		{
13902 
13903 			Info = dtmf_restore_config(Id, plci, Rc);
13904 			if ((Info != GOOD) || plci->internal_command)
13905 				break;
13906 
13907 		}
13908 		plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13909 		Rc = OK;
13910 	case ADJUST_B_RESTORE_MIXER_1:
13911 	case ADJUST_B_RESTORE_MIXER_2:
13912 	case ADJUST_B_RESTORE_MIXER_3:
13913 	case ADJUST_B_RESTORE_MIXER_4:
13914 	case ADJUST_B_RESTORE_MIXER_5:
13915 	case ADJUST_B_RESTORE_MIXER_6:
13916 	case ADJUST_B_RESTORE_MIXER_7:
13917 		if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13918 		{
13919 
13920 			Info = mixer_restore_config(Id, plci, Rc);
13921 			if ((Info != GOOD) || plci->internal_command)
13922 				break;
13923 
13924 		}
13925 		plci->adjust_b_state = ADJUST_B_END;
13926 	case ADJUST_B_END:
13927 		break;
13928 	}
13929 	return (Info);
13930 }
13931 
13932 
adjust_b1_resource(dword Id,PLCI * plci,API_SAVE * bp_msg,word b1_facilities,word internal_command)13933 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13934 {
13935 
13936 	dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13937 			UnMapId(Id), (char *)(FILE_), __LINE__,
13938 			plci->B1_resource, b1_facilities));
13939 
13940 	plci->adjust_b_parms_msg = bp_msg;
13941 	plci->adjust_b_facilities = b1_facilities;
13942 	plci->adjust_b_command = internal_command;
13943 	plci->adjust_b_ncci = (word)(Id >> 16);
13944 	if ((bp_msg == NULL) && (plci->B1_resource == 0))
13945 		plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13946 	else
13947 		plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13948 	plci->adjust_b_state = ADJUST_B_START;
13949 	dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13950 			UnMapId(Id), (char *)(FILE_), __LINE__,
13951 			plci->B1_resource, b1_facilities));
13952 }
13953 
13954 
adjust_b_restore(dword Id,PLCI * plci,byte Rc)13955 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13956 {
13957 	word internal_command;
13958 
13959 	dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13960 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13961 
13962 	internal_command = plci->internal_command;
13963 	plci->internal_command = 0;
13964 	switch (internal_command)
13965 	{
13966 	default:
13967 		plci->command = 0;
13968 		if (plci->req_in != 0)
13969 		{
13970 			plci->internal_command = ADJUST_B_RESTORE_1;
13971 			break;
13972 		}
13973 		Rc = OK;
13974 	case ADJUST_B_RESTORE_1:
13975 		if ((Rc != OK) && (Rc != OK_FC))
13976 		{
13977 			dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13978 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13979 		}
13980 		plci->adjust_b_parms_msg = NULL;
13981 		plci->adjust_b_facilities = plci->B1_facilities;
13982 		plci->adjust_b_command = ADJUST_B_RESTORE_2;
13983 		plci->adjust_b_ncci = (word)(Id >> 16);
13984 		plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13985 		plci->adjust_b_state = ADJUST_B_START;
13986 		dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13987 				UnMapId(Id), (char *)(FILE_), __LINE__));
13988 	case ADJUST_B_RESTORE_2:
13989 		if (adjust_b_process(Id, plci, Rc) != GOOD)
13990 		{
13991 			dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13992 					UnMapId(Id), (char *)(FILE_), __LINE__));
13993 		}
13994 		if (plci->internal_command)
13995 			break;
13996 		break;
13997 	}
13998 }
13999 
14000 
reset_b3_command(dword Id,PLCI * plci,byte Rc)14001 static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
14002 {
14003 	word Info;
14004 	word internal_command;
14005 
14006 	dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
14007 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14008 
14009 	Info = GOOD;
14010 	internal_command = plci->internal_command;
14011 	plci->internal_command = 0;
14012 	switch (internal_command)
14013 	{
14014 	default:
14015 		plci->command = 0;
14016 		plci->adjust_b_parms_msg = NULL;
14017 		plci->adjust_b_facilities = plci->B1_facilities;
14018 		plci->adjust_b_command = RESET_B3_COMMAND_1;
14019 		plci->adjust_b_ncci = (word)(Id >> 16);
14020 		plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14021 		plci->adjust_b_state = ADJUST_B_START;
14022 		dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
14023 				UnMapId(Id), (char *)(FILE_), __LINE__));
14024 	case RESET_B3_COMMAND_1:
14025 		Info = adjust_b_process(Id, plci, Rc);
14026 		if (Info != GOOD)
14027 		{
14028 			dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
14029 					UnMapId(Id), (char *)(FILE_), __LINE__));
14030 			break;
14031 		}
14032 		if (plci->internal_command)
14033 			return;
14034 		break;
14035 	}
14036 /*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14037 	sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
14038 }
14039 
14040 
select_b_command(dword Id,PLCI * plci,byte Rc)14041 static void select_b_command(dword Id, PLCI *plci, byte Rc)
14042 {
14043 	word Info;
14044 	word internal_command;
14045 	byte esc_chi[3];
14046 
14047 	dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
14048 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14049 
14050 	Info = GOOD;
14051 	internal_command = plci->internal_command;
14052 	plci->internal_command = 0;
14053 	switch (internal_command)
14054 	{
14055 	default:
14056 		plci->command = 0;
14057 		plci->adjust_b_parms_msg = &plci->saved_msg;
14058 		if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14059 			plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14060 		else
14061 			plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14062 		plci->adjust_b_command = SELECT_B_COMMAND_1;
14063 		plci->adjust_b_ncci = (word)(Id >> 16);
14064 		if (plci->saved_msg.parms[0].length == 0)
14065 		{
14066 			plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14067 				ADJUST_B_MODE_NO_RESOURCE;
14068 		}
14069 		else
14070 		{
14071 			plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14072 				ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14073 		}
14074 		plci->adjust_b_state = ADJUST_B_START;
14075 		dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
14076 				UnMapId(Id), (char *)(FILE_), __LINE__));
14077 	case SELECT_B_COMMAND_1:
14078 		Info = adjust_b_process(Id, plci, Rc);
14079 		if (Info != GOOD)
14080 		{
14081 			dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
14082 					UnMapId(Id), (char *)(FILE_), __LINE__));
14083 			break;
14084 		}
14085 		if (plci->internal_command)
14086 			return;
14087 		if (plci->tel == ADV_VOICE)
14088 		{
14089 			esc_chi[0] = 0x02;
14090 			esc_chi[1] = 0x18;
14091 			esc_chi[2] = plci->b_channel;
14092 			SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14093 		}
14094 		break;
14095 	}
14096 	sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14097 }
14098 
14099 
fax_connect_ack_command(dword Id,PLCI * plci,byte Rc)14100 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
14101 {
14102 	word internal_command;
14103 
14104 	dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14105 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14106 
14107 	internal_command = plci->internal_command;
14108 	plci->internal_command = 0;
14109 	switch (internal_command)
14110 	{
14111 	default:
14112 		plci->command = 0;
14113 	case FAX_CONNECT_ACK_COMMAND_1:
14114 		if (plci_nl_busy(plci))
14115 		{
14116 			plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14117 			return;
14118 		}
14119 		plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14120 		plci->NData[0].P = plci->fax_connect_info_buffer;
14121 		plci->NData[0].PLength = plci->fax_connect_info_length;
14122 		plci->NL.X = plci->NData;
14123 		plci->NL.ReqCh = 0;
14124 		plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14125 		plci->adapter->request(&plci->NL);
14126 		return;
14127 	case FAX_CONNECT_ACK_COMMAND_2:
14128 		if ((Rc != OK) && (Rc != OK_FC))
14129 		{
14130 			dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14131 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14132 			break;
14133 		}
14134 	}
14135 	if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14136 	    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14137 	{
14138 		if (plci->B3_prot == 4)
14139 			sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14140 		else
14141 			sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
14142 		plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14143 	}
14144 }
14145 
14146 
fax_edata_ack_command(dword Id,PLCI * plci,byte Rc)14147 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14148 {
14149 	word internal_command;
14150 
14151 	dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14152 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14153 
14154 	internal_command = plci->internal_command;
14155 	plci->internal_command = 0;
14156 	switch (internal_command)
14157 	{
14158 	default:
14159 		plci->command = 0;
14160 	case FAX_EDATA_ACK_COMMAND_1:
14161 		if (plci_nl_busy(plci))
14162 		{
14163 			plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14164 			return;
14165 		}
14166 		plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14167 		plci->NData[0].P = plci->fax_connect_info_buffer;
14168 		plci->NData[0].PLength = plci->fax_edata_ack_length;
14169 		plci->NL.X = plci->NData;
14170 		plci->NL.ReqCh = 0;
14171 		plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14172 		plci->adapter->request(&plci->NL);
14173 		return;
14174 	case FAX_EDATA_ACK_COMMAND_2:
14175 		if ((Rc != OK) && (Rc != OK_FC))
14176 		{
14177 			dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14178 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14179 			break;
14180 		}
14181 	}
14182 }
14183 
14184 
fax_connect_info_command(dword Id,PLCI * plci,byte Rc)14185 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14186 {
14187 	word Info;
14188 	word internal_command;
14189 
14190 	dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14191 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14192 
14193 	Info = GOOD;
14194 	internal_command = plci->internal_command;
14195 	plci->internal_command = 0;
14196 	switch (internal_command)
14197 	{
14198 	default:
14199 		plci->command = 0;
14200 	case FAX_CONNECT_INFO_COMMAND_1:
14201 		if (plci_nl_busy(plci))
14202 		{
14203 			plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14204 			return;
14205 		}
14206 		plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14207 		plci->NData[0].P = plci->fax_connect_info_buffer;
14208 		plci->NData[0].PLength = plci->fax_connect_info_length;
14209 		plci->NL.X = plci->NData;
14210 		plci->NL.ReqCh = 0;
14211 		plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14212 		plci->adapter->request(&plci->NL);
14213 		return;
14214 	case FAX_CONNECT_INFO_COMMAND_2:
14215 		if ((Rc != OK) && (Rc != OK_FC))
14216 		{
14217 			dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14218 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14219 			Info = _WRONG_STATE;
14220 			break;
14221 		}
14222 		if (plci_nl_busy(plci))
14223 		{
14224 			plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14225 			return;
14226 		}
14227 		plci->command = _CONNECT_B3_R;
14228 		nl_req_ncci(plci, N_CONNECT, 0);
14229 		send_req(plci);
14230 		return;
14231 	}
14232 	sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14233 }
14234 
14235 
fax_adjust_b23_command(dword Id,PLCI * plci,byte Rc)14236 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14237 {
14238 	word Info;
14239 	word internal_command;
14240 
14241 	dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14242 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14243 
14244 	Info = GOOD;
14245 	internal_command = plci->internal_command;
14246 	plci->internal_command = 0;
14247 	switch (internal_command)
14248 	{
14249 	default:
14250 		plci->command = 0;
14251 		plci->adjust_b_parms_msg = NULL;
14252 		plci->adjust_b_facilities = plci->B1_facilities;
14253 		plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14254 		plci->adjust_b_ncci = (word)(Id >> 16);
14255 		plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14256 		plci->adjust_b_state = ADJUST_B_START;
14257 		dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14258 				UnMapId(Id), (char *)(FILE_), __LINE__));
14259 	case FAX_ADJUST_B23_COMMAND_1:
14260 		Info = adjust_b_process(Id, plci, Rc);
14261 		if (Info != GOOD)
14262 		{
14263 			dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14264 					UnMapId(Id), (char *)(FILE_), __LINE__));
14265 			break;
14266 		}
14267 		if (plci->internal_command)
14268 			return;
14269 	case FAX_ADJUST_B23_COMMAND_2:
14270 		if (plci_nl_busy(plci))
14271 		{
14272 			plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14273 			return;
14274 		}
14275 		plci->command = _CONNECT_B3_R;
14276 		nl_req_ncci(plci, N_CONNECT, 0);
14277 		send_req(plci);
14278 		return;
14279 	}
14280 	sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14281 }
14282 
14283 
fax_disconnect_command(dword Id,PLCI * plci,byte Rc)14284 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14285 {
14286 	word internal_command;
14287 
14288 	dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14289 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14290 
14291 	internal_command = plci->internal_command;
14292 	plci->internal_command = 0;
14293 	switch (internal_command)
14294 	{
14295 	default:
14296 		plci->command = 0;
14297 		plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14298 		return;
14299 	case FAX_DISCONNECT_COMMAND_1:
14300 	case FAX_DISCONNECT_COMMAND_2:
14301 	case FAX_DISCONNECT_COMMAND_3:
14302 		if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14303 		{
14304 			dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14305 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14306 			break;
14307 		}
14308 		if (Rc == OK)
14309 		{
14310 			if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14311 			    || (internal_command == FAX_DISCONNECT_COMMAND_2))
14312 			{
14313 				plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14314 			}
14315 		}
14316 		else if (Rc == 0)
14317 		{
14318 			if (internal_command == FAX_DISCONNECT_COMMAND_1)
14319 				plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14320 		}
14321 		return;
14322 	}
14323 }
14324 
14325 
14326 
rtp_connect_b3_req_command(dword Id,PLCI * plci,byte Rc)14327 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14328 {
14329 	word Info;
14330 	word internal_command;
14331 
14332 	dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14333 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14334 
14335 	Info = GOOD;
14336 	internal_command = plci->internal_command;
14337 	plci->internal_command = 0;
14338 	switch (internal_command)
14339 	{
14340 	default:
14341 		plci->command = 0;
14342 	case RTP_CONNECT_B3_REQ_COMMAND_1:
14343 		if (plci_nl_busy(plci))
14344 		{
14345 			plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14346 			return;
14347 		}
14348 		plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14349 		nl_req_ncci(plci, N_CONNECT, 0);
14350 		send_req(plci);
14351 		return;
14352 	case RTP_CONNECT_B3_REQ_COMMAND_2:
14353 		if ((Rc != OK) && (Rc != OK_FC))
14354 		{
14355 			dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14356 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14357 			Info = _WRONG_STATE;
14358 			break;
14359 		}
14360 		if (plci_nl_busy(plci))
14361 		{
14362 			plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14363 			return;
14364 		}
14365 		plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14366 		plci->NData[0].PLength = plci->internal_req_buffer[0];
14367 		plci->NData[0].P = plci->internal_req_buffer + 1;
14368 		plci->NL.X = plci->NData;
14369 		plci->NL.ReqCh = 0;
14370 		plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14371 		plci->adapter->request(&plci->NL);
14372 		break;
14373 	case RTP_CONNECT_B3_REQ_COMMAND_3:
14374 		return;
14375 	}
14376 	sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14377 }
14378 
14379 
rtp_connect_b3_res_command(dword Id,PLCI * plci,byte Rc)14380 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14381 {
14382 	word internal_command;
14383 
14384 	dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14385 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14386 
14387 	internal_command = plci->internal_command;
14388 	plci->internal_command = 0;
14389 	switch (internal_command)
14390 	{
14391 	default:
14392 		plci->command = 0;
14393 	case RTP_CONNECT_B3_RES_COMMAND_1:
14394 		if (plci_nl_busy(plci))
14395 		{
14396 			plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14397 			return;
14398 		}
14399 		plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14400 		nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14401 		send_req(plci);
14402 		return;
14403 	case RTP_CONNECT_B3_RES_COMMAND_2:
14404 		if ((Rc != OK) && (Rc != OK_FC))
14405 		{
14406 			dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14407 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14408 			break;
14409 		}
14410 		if (plci_nl_busy(plci))
14411 		{
14412 			plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14413 			return;
14414 		}
14415 		sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14416 		plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14417 		plci->NData[0].PLength = plci->internal_req_buffer[0];
14418 		plci->NData[0].P = plci->internal_req_buffer + 1;
14419 		plci->NL.X = plci->NData;
14420 		plci->NL.ReqCh = 0;
14421 		plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14422 		plci->adapter->request(&plci->NL);
14423 		return;
14424 	case RTP_CONNECT_B3_RES_COMMAND_3:
14425 		return;
14426 	}
14427 }
14428 
14429 
14430 
hold_save_command(dword Id,PLCI * plci,byte Rc)14431 static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14432 {
14433 	byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14434 	word Info;
14435 	word internal_command;
14436 
14437 	dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14438 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14439 
14440 	Info = GOOD;
14441 	internal_command = plci->internal_command;
14442 	plci->internal_command = 0;
14443 	switch (internal_command)
14444 	{
14445 	default:
14446 		if (!plci->NL.Id)
14447 			break;
14448 		plci->command = 0;
14449 		plci->adjust_b_parms_msg = NULL;
14450 		plci->adjust_b_facilities = plci->B1_facilities;
14451 		plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14452 		plci->adjust_b_ncci = (word)(Id >> 16);
14453 		plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14454 		plci->adjust_b_state = ADJUST_B_START;
14455 		dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14456 				UnMapId(Id), (char *)(FILE_), __LINE__));
14457 	case HOLD_SAVE_COMMAND_1:
14458 		Info = adjust_b_process(Id, plci, Rc);
14459 		if (Info != GOOD)
14460 		{
14461 			dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14462 					UnMapId(Id), (char *)(FILE_), __LINE__));
14463 			break;
14464 		}
14465 		if (plci->internal_command)
14466 			return;
14467 	}
14468 	sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14469 }
14470 
14471 
retrieve_restore_command(dword Id,PLCI * plci,byte Rc)14472 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14473 {
14474 	byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14475 	word Info;
14476 	word internal_command;
14477 
14478 	dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14479 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14480 
14481 	Info = GOOD;
14482 	internal_command = plci->internal_command;
14483 	plci->internal_command = 0;
14484 	switch (internal_command)
14485 	{
14486 	default:
14487 		plci->command = 0;
14488 		plci->adjust_b_parms_msg = NULL;
14489 		plci->adjust_b_facilities = plci->B1_facilities;
14490 		plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14491 		plci->adjust_b_ncci = (word)(Id >> 16);
14492 		plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14493 		plci->adjust_b_state = ADJUST_B_START;
14494 		dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14495 				UnMapId(Id), (char *)(FILE_), __LINE__));
14496 	case RETRIEVE_RESTORE_COMMAND_1:
14497 		Info = adjust_b_process(Id, plci, Rc);
14498 		if (Info != GOOD)
14499 		{
14500 			dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14501 					UnMapId(Id), (char *)(FILE_), __LINE__));
14502 			break;
14503 		}
14504 		if (plci->internal_command)
14505 			return;
14506 	}
14507 	sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14508 }
14509 
14510 
init_b1_config(PLCI * plci)14511 static void init_b1_config(PLCI *plci)
14512 {
14513 
14514 	dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14515 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14516 			(char *)(FILE_), __LINE__));
14517 
14518 	plci->B1_resource = 0;
14519 	plci->B1_facilities = 0;
14520 
14521 	plci->li_bchannel_id = 0;
14522 	mixer_clear_config(plci);
14523 
14524 
14525 	ec_clear_config(plci);
14526 
14527 
14528 	dtmf_rec_clear_config(plci);
14529 	dtmf_send_clear_config(plci);
14530 	dtmf_parameter_clear_config(plci);
14531 
14532 	adv_voice_clear_config(plci);
14533 	adjust_b_clear(plci);
14534 }
14535 
14536 
clear_b1_config(PLCI * plci)14537 static void clear_b1_config(PLCI *plci)
14538 {
14539 
14540 	dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14541 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14542 			(char *)(FILE_), __LINE__));
14543 
14544 	adv_voice_clear_config(plci);
14545 	adjust_b_clear(plci);
14546 
14547 	ec_clear_config(plci);
14548 
14549 
14550 	dtmf_rec_clear_config(plci);
14551 	dtmf_send_clear_config(plci);
14552 	dtmf_parameter_clear_config(plci);
14553 
14554 
14555 	if ((plci->li_bchannel_id != 0)
14556 	    && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14557 	{
14558 		mixer_clear_config(plci);
14559 		li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14560 		plci->li_bchannel_id = 0;
14561 	}
14562 
14563 	plci->B1_resource = 0;
14564 	plci->B1_facilities = 0;
14565 }
14566 
14567 
14568 /* -----------------------------------------------------------------
14569    XON protocol local helpers
14570    ----------------------------------------------------------------- */
channel_flow_control_remove(PLCI * plci)14571 static void channel_flow_control_remove(PLCI *plci) {
14572 	DIVA_CAPI_ADAPTER *a = plci->adapter;
14573 	word i;
14574 	for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14575 		if (a->ch_flow_plci[i] == plci->Id) {
14576 			a->ch_flow_plci[i] = 0;
14577 			a->ch_flow_control[i] = 0;
14578 		}
14579 	}
14580 }
14581 
channel_x_on(PLCI * plci,byte ch)14582 static void channel_x_on(PLCI *plci, byte ch) {
14583 	DIVA_CAPI_ADAPTER *a = plci->adapter;
14584 	if (a->ch_flow_control[ch] & N_XON_SENT) {
14585 		a->ch_flow_control[ch] &= ~N_XON_SENT;
14586 	}
14587 }
14588 
channel_x_off(PLCI * plci,byte ch,byte flag)14589 static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14590 	DIVA_CAPI_ADAPTER *a = plci->adapter;
14591 	if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14592 		a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14593 		a->ch_flow_plci[ch] = plci->Id;
14594 		a->ch_flow_control_pending++;
14595 	}
14596 }
14597 
channel_request_xon(PLCI * plci,byte ch)14598 static void channel_request_xon(PLCI *plci, byte ch) {
14599 	DIVA_CAPI_ADAPTER *a = plci->adapter;
14600 
14601 	if (a->ch_flow_control[ch] & N_CH_XOFF) {
14602 		a->ch_flow_control[ch] |= N_XON_REQ;
14603 		a->ch_flow_control[ch] &= ~N_CH_XOFF;
14604 		a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14605 	}
14606 }
14607 
channel_xmit_extended_xon(PLCI * plci)14608 static void channel_xmit_extended_xon(PLCI *plci) {
14609 	DIVA_CAPI_ADAPTER *a;
14610 	int max_ch = ARRAY_SIZE(a->ch_flow_control);
14611 	int i, one_requested = 0;
14612 
14613 	if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14614 		return;
14615 	}
14616 
14617 	for (i = 0; i < max_ch; i++) {
14618 		if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14619 		    (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14620 		    (plci->Id == a->ch_flow_plci[i])) {
14621 			channel_request_xon(plci, (byte)i);
14622 			one_requested = 1;
14623 		}
14624 	}
14625 
14626 	if (one_requested) {
14627 		channel_xmit_xon(plci);
14628 	}
14629 }
14630 
14631 /*
14632   Try to xmit next X_ON
14633 */
find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER * a,PLCI * plci)14634 static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14635 	int max_ch = ARRAY_SIZE(a->ch_flow_control);
14636 	int i;
14637 
14638 	if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14639 		return (0);
14640 	}
14641 
14642 	if (a->last_flow_control_ch >= max_ch) {
14643 		a->last_flow_control_ch = 1;
14644 	}
14645 	for (i = a->last_flow_control_ch; i < max_ch; i++) {
14646 		if ((a->ch_flow_control[i] & N_XON_REQ) &&
14647 		    (plci->Id == a->ch_flow_plci[i])) {
14648 			a->last_flow_control_ch = i + 1;
14649 			return (i);
14650 		}
14651 	}
14652 
14653 	for (i = 1; i < a->last_flow_control_ch; i++) {
14654 		if ((a->ch_flow_control[i] & N_XON_REQ) &&
14655 		    (plci->Id == a->ch_flow_plci[i])) {
14656 			a->last_flow_control_ch = i + 1;
14657 			return (i);
14658 		}
14659 	}
14660 
14661 	return (0);
14662 }
14663 
channel_xmit_xon(PLCI * plci)14664 static void channel_xmit_xon(PLCI *plci) {
14665 	DIVA_CAPI_ADAPTER *a = plci->adapter;
14666 	byte ch;
14667 
14668 	if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14669 		return;
14670 	}
14671 	if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14672 		return;
14673 	}
14674 	a->ch_flow_control[ch] &= ~N_XON_REQ;
14675 	a->ch_flow_control[ch] |= N_XON_SENT;
14676 
14677 	plci->NL.Req = plci->nl_req = (byte)N_XON;
14678 	plci->NL.ReqCh         = ch;
14679 	plci->NL.X             = plci->NData;
14680 	plci->NL.XNum          = 1;
14681 	plci->NData[0].P       = &plci->RBuffer[0];
14682 	plci->NData[0].PLength = 0;
14683 
14684 	plci->adapter->request(&plci->NL);
14685 }
14686 
channel_can_xon(PLCI * plci,byte ch)14687 static int channel_can_xon(PLCI *plci, byte ch) {
14688 	APPL *APPLptr;
14689 	DIVA_CAPI_ADAPTER *a;
14690 	word NCCIcode;
14691 	dword count;
14692 	word Num;
14693 	word i;
14694 
14695 	APPLptr = plci->appl;
14696 	a = plci->adapter;
14697 
14698 	if (!APPLptr)
14699 		return (0);
14700 
14701 	NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14702 
14703 	/* count all buffers within the Application pool    */
14704 	/* belonging to the same NCCI. XON if a first is    */
14705 	/* used.                                            */
14706 	count = 0;
14707 	Num = 0xffff;
14708 	for (i = 0; i < APPLptr->MaxBuffer; i++) {
14709 		if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14710 		if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14711 	}
14712 	if ((count > 2) || (Num == 0xffff)) {
14713 		return (0);
14714 	}
14715 	return (1);
14716 }
14717 
14718 
14719 /*------------------------------------------------------------------*/
14720 
CPN_filter_ok(byte * cpn,DIVA_CAPI_ADAPTER * a,word offset)14721 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14722 {
14723 	return 1;
14724 }
14725 
14726 
14727 
14728 /**********************************************************************************/
14729 /* function groups the listening applications according to the CIP mask and the   */
14730 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14731 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14732 /* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14733 /* function must be enabled by setting "a->group_optimization_enabled" from the   */
14734 /* OS specific part (per adapter).                                                */
14735 /**********************************************************************************/
group_optimization(DIVA_CAPI_ADAPTER * a,PLCI * plci)14736 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14737 {
14738 	word i, j, k, busy, group_found;
14739 	dword info_mask_group[MAX_CIP_TYPES];
14740 	dword cip_mask_group[MAX_CIP_TYPES];
14741 	word appl_number_group_type[MAX_APPL];
14742 	PLCI *auxplci;
14743 
14744 	set_group_ind_mask(plci); /* all APPLs within this inc. call are allowed to dial in */
14745 
14746 	if (!a->group_optimization_enabled)
14747 	{
14748 		dbug(1, dprintf("No group optimization"));
14749 		return;
14750 	}
14751 
14752 	dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14753 
14754 	for (i = 0; i < MAX_CIP_TYPES; i++)
14755 	{
14756 		info_mask_group[i] = 0;
14757 		cip_mask_group[i] = 0;
14758 	}
14759 	for (i = 0; i < MAX_APPL; i++)
14760 	{
14761 		appl_number_group_type[i] = 0;
14762 	}
14763 	for (i = 0; i < max_appl; i++) /* check if any multi instance capable application is present */
14764 	{  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14765 		if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14766 		{
14767 			dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14768 			return; /* allow good application unfiltered access */
14769 		}
14770 	}
14771 	for (i = 0; i < max_appl; i++) /* Build CIP Groups */
14772 	{
14773 		if (application[i].Id && a->CIP_Mask[i])
14774 		{
14775 			for (k = 0, busy = false; k < a->max_plci; k++)
14776 			{
14777 				if (a->plci[k].Id)
14778 				{
14779 					auxplci = &a->plci[k];
14780 					if (auxplci->appl == &application[i]) /* application has a busy PLCI */
14781 					{
14782 						busy = true;
14783 						dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14784 					}
14785 					else if (test_c_ind_mask_bit(auxplci, i)) /* application has an incoming call pending */
14786 					{
14787 						busy = true;
14788 						dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14789 					}
14790 				}
14791 			}
14792 
14793 			for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++)     /* build groups with free applications only */
14794 			{
14795 				if (j == MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14796 				{                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14797 					appl_number_group_type[i] = MAX_CIP_TYPES;
14798 					group_found = true;
14799 					dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14800 				}
14801 				else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14802 				{                                      /* is group already present ?                  */
14803 					appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14804 					group_found = true;
14805 					dbug(1, dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx", appl_number_group_type[i], i + 1, info_mask_group[j]));
14806 				}
14807 				else if (!info_mask_group[j])
14808 				{                                      /* establish a new group                       */
14809 					appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14810 					info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14811 					cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14812 					group_found = true;
14813 					dbug(1, dprintf("New Group 0x%x established with appl 0x%x, CIP=0x%lx", appl_number_group_type[i], i + 1, info_mask_group[j]));
14814 				}
14815 			}
14816 		}
14817 	}
14818 
14819 	for (i = 0; i < max_appl; i++) /* Build group_optimization_mask_table */
14820 	{
14821 		if (appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14822 		{
14823 			if (appl_number_group_type[i] == MAX_CIP_TYPES)
14824 			{
14825 				dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14826 			}
14827 			else
14828 			{
14829 				dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14830 				for (j = i + 1; j < max_appl; j++)   /* search other group members and mark them as busy        */
14831 				{
14832 					if (appl_number_group_type[i] == appl_number_group_type[j])
14833 					{
14834 						dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14835 						clear_group_ind_mask_bit(plci, j);           /* disable call on other group members */
14836 						appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14837 					}
14838 				}
14839 			}
14840 		}
14841 		else                                                 /* application should not get a call */
14842 		{
14843 			clear_group_ind_mask_bit(plci, i);
14844 		}
14845 	}
14846 
14847 }
14848 
14849 
14850 
14851 /* OS notifies the driver about a application Capi_Register */
CapiRegister(word id)14852 word CapiRegister(word id)
14853 {
14854 	word i, j, appls_found;
14855 
14856 	PLCI *plci;
14857 	DIVA_CAPI_ADAPTER *a;
14858 
14859 	for (i = 0, appls_found = 0; i < max_appl; i++)
14860 	{
14861 		if (application[i].Id && (application[i].Id != id))
14862 		{
14863 			appls_found++;                       /* an application has been found */
14864 		}
14865 	}
14866 
14867 	if (appls_found) return true;
14868 	for (i = 0; i < max_adapter; i++)                   /* scan all adapters...    */
14869 	{
14870 		a = &adapter[i];
14871 		if (a->request)
14872 		{
14873 			if (a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14874 			{
14875 				if (!appls_found)           /* first application does a capi register   */
14876 				{
14877 					if ((j = get_plci(a)))                    /* activate L1 of all adapters */
14878 					{
14879 						plci = &a->plci[j - 1];
14880 						plci->command = 0;
14881 						add_p(plci, OAD, "\x01\xfd");
14882 						add_p(plci, CAI, "\x01\x80");
14883 						add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14884 						add_p(plci, SHIFT | 6, NULL);
14885 						add_p(plci, SIN, "\x02\x00\x00");
14886 						plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14887 						sig_req(plci, ASSIGN, DSIG_ID);
14888 						add_p(plci, FTY, "\x02\xff\x07"); /* l1 start */
14889 						sig_req(plci, SIG_CTRL, 0);
14890 						send_req(plci);
14891 					}
14892 				}
14893 			}
14894 		}
14895 	}
14896 	return false;
14897 }
14898 
14899 /*------------------------------------------------------------------*/
14900 
14901 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14902 
VSwitchReqInd(PLCI * plci,dword Id,byte ** parms)14903 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14904 {
14905 	word i;
14906 	/* Format of vswitch_t:
14907 	   0 byte length
14908 	   1 byte VSWITCHIE
14909 	   2 byte VSWITCH_REQ/VSWITCH_IND
14910 	   3 byte reserved
14911 	   4 word VSwitchcommand
14912 	   6 word returnerror
14913 	   8... Params
14914 	*/
14915 	if (!plci ||
14916 	    !plci->appl ||
14917 	    !plci->State ||
14918 	    plci->Sig.Ind == NCR_FACILITY
14919 		)
14920 		return;
14921 
14922 	for (i = 0; i < MAX_MULTI_IE; i++)
14923 	{
14924 		if (!parms[i][0]) continue;
14925 		if (parms[i][0] < 7)
14926 		{
14927 			parms[i][0] = 0; /* kill it */
14928 			continue;
14929 		}
14930 		dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14931 		switch (parms[i][4])
14932 		{
14933 		case VSJOIN:
14934 			if (!plci->relatedPTYPLCI ||
14935 			    (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14936 			{ /* Error */
14937 				break;
14938 			}
14939 			/* remember all necessary informations */
14940 			if (parms[i][0] != 11 || parms[i][8] != 3) /* Length Test */
14941 			{
14942 				break;
14943 			}
14944 			if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14945 			{   /* first indication after ECT-Request on Consultation Call */
14946 				plci->vswitchstate = parms[i][9];
14947 				parms[i][9] = 2; /* State */
14948 				/* now ask first Call to join */
14949 			}
14950 			else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14951 			{ /* Answer of VSWITCH_REQ from first Call */
14952 				plci->vswitchstate = parms[i][9];
14953 				/* tell consultation call to join
14954 				   and the protocol capabilities of the first call */
14955 			}
14956 			else
14957 			{ /* Error */
14958 				break;
14959 			}
14960 			plci->vsprot = parms[i][10]; /* protocol */
14961 			plci->vsprotdialect = parms[i][11]; /* protocoldialect */
14962 			/* send join request to related PLCI */
14963 			parms[i][1] = VSWITCHIE;
14964 			parms[i][2] = VSWITCH_REQ;
14965 
14966 			plci->relatedPTYPLCI->command = 0;
14967 			plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14968 			add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14969 			sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14970 			send_req(plci->relatedPTYPLCI);
14971 			break;
14972 		case VSTRANSPORT:
14973 		default:
14974 			if (plci->relatedPTYPLCI &&
14975 			    plci->vswitchstate == 3 &&
14976 			    plci->relatedPTYPLCI->vswitchstate == 3)
14977 			{
14978 				add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14979 				sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14980 				send_req(plci->relatedPTYPLCI);
14981 			}
14982 			break;
14983 		}
14984 		parms[i][0] = 0; /* kill it */
14985 	}
14986 }
14987 
14988 
14989 /*------------------------------------------------------------------*/
14990 
diva_get_dma_descriptor(PLCI * plci,dword * dma_magic)14991 static int diva_get_dma_descriptor(PLCI *plci, dword   *dma_magic) {
14992 	ENTITY e;
14993 	IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14994 
14995 	if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14996 		return (-1);
14997 	}
14998 
14999 	pReq->xdi_dma_descriptor_operation.Req = 0;
15000 	pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15001 
15002 	pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
15003 	pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
15004 	pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15005 	pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15006 
15007 	e.user[0] = plci->adapter->Id - 1;
15008 	plci->adapter->request((ENTITY *)pReq);
15009 
15010 	if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15011 	    (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15012 	    pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15013 		*dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15014 		dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
15015 				plci->adapter->Id,
15016 				pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15017 				*dma_magic));
15018 		return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15019 	} else {
15020 		dbug(1, dprintf("dma_alloc failed"));
15021 		return (-1);
15022 	}
15023 }
15024 
diva_free_dma_descriptor(PLCI * plci,int nr)15025 static void diva_free_dma_descriptor(PLCI *plci, int nr) {
15026 	ENTITY e;
15027 	IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
15028 
15029 	if (nr < 0) {
15030 		return;
15031 	}
15032 
15033 	pReq->xdi_dma_descriptor_operation.Req = 0;
15034 	pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15035 
15036 	pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15037 	pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
15038 	pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15039 	pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15040 
15041 	e.user[0] = plci->adapter->Id - 1;
15042 	plci->adapter->request((ENTITY *)pReq);
15043 
15044 	if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15045 		dbug(1, dprintf("dma_free(%d)", nr));
15046 	} else {
15047 		dbug(1, dprintf("dma_free failed (%d)", nr));
15048 	}
15049 }
15050 
15051 /*------------------------------------------------------------------*/
15052