• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *, const 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 	static const 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 	static const word multi_fac_id[] = {1, FTY};
4872 	static const word multi_pi_id[]  = {1, PI};
4873 	static const word multi_CiPN_id[]  = {1, OAD};
4874 	static const word multi_ssext_id[]  = {1, ESC_SSEXT};
4875 
4876 	static const word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4877 
4878 	byte *cau;
4879 	word ncci;
4880 	byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4881 	byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4882 	byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4883 	byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\x00\x00\x00\x00";
4884 	byte force_mt_info = false;
4885 	byte dir;
4886 	dword d;
4887 	word w;
4888 
4889 	a = plci->adapter;
4890 	Id = ((word)plci->Id << 8) | a->Id;
4891 	PUT_WORD(&SS_Ind[4], 0x0000);
4892 
4893 	if (plci->sig_remove_id)
4894 	{
4895 		plci->Sig.RNR = 2; /* discard */
4896 		dbug(1, dprintf("SIG discard while remove pending"));
4897 		return;
4898 	}
4899 	if (plci->tel && plci->SuppState != CALL_HELD) Id |= EXT_CONTROLLER;
4900 	dbug(1, dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4901 			Id, plci->Id, plci->tel, plci->State, plci->channels, plci->hangup_flow_ctrl_timer));
4902 	if (plci->Sig.Ind == CALL_HOLD_ACK && plci->channels)
4903 	{
4904 		plci->Sig.RNR = 1;
4905 		return;
4906 	}
4907 	if (plci->Sig.Ind == HANGUP && plci->channels)
4908 	{
4909 		plci->Sig.RNR = 1;
4910 		plci->hangup_flow_ctrl_timer++;
4911 		/* recover the network layer after timeout */
4912 		if (plci->hangup_flow_ctrl_timer == 100)
4913 		{
4914 			dbug(1, dprintf("Exceptional disc"));
4915 			plci->Sig.RNR = 0;
4916 			plci->hangup_flow_ctrl_timer = 0;
4917 			for (ncci = 1; ncci < MAX_NCCI + 1; ncci++)
4918 			{
4919 				if (a->ncci_plci[ncci] == plci->Id)
4920 				{
4921 					cleanup_ncci_data(plci, ncci);
4922 					if (plci->channels)plci->channels--;
4923 					if (plci->appl)
4924 						sendf(plci->appl, _DISCONNECT_B3_I, (((dword) ncci) << 16) | Id, 0, "ws", 0, "");
4925 				}
4926 			}
4927 			if (plci->appl)
4928 				sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4929 			plci_remove(plci);
4930 			plci->State = IDLE;
4931 		}
4932 		return;
4933 	}
4934 
4935 	/* do first parse the info with no OAD in, because OAD will be converted */
4936 	/* first the multiple facility IE, then mult. progress ind.              */
4937 	/* then the parameters for the info_ind + conn_ind                       */
4938 	IndParse(plci, multi_fac_id, multi_fac_parms, MAX_MULTI_IE);
4939 	IndParse(plci, multi_pi_id, multi_pi_parms, MAX_MULTI_IE);
4940 	IndParse(plci, multi_ssext_id, multi_ssext_parms, MAX_MULTI_IE);
4941 
4942 	IndParse(plci, multi_vswitch_id, multi_vswitch_parms, MAX_MULTI_IE);
4943 
4944 	IndParse(plci, parms_id, parms, 0);
4945 	IndParse(plci, multi_CiPN_id, multi_CiPN_parms, MAX_MULTI_IE);
4946 	esc_chi  = parms[14];
4947 	esc_law  = parms[18];
4948 	pty_cai  = parms[24];
4949 	esc_cr   = parms[25];
4950 	esc_profile = parms[27];
4951 	if (esc_cr[0] && plci)
4952 	{
4953 		if (plci->cr_enquiry && plci->appl)
4954 		{
4955 			plci->cr_enquiry = false;
4956 			/* d = MANU_ID            */
4957 			/* w = m_command          */
4958 			/* b = total length       */
4959 			/* b = indication type    */
4960 			/* b = length of all IEs  */
4961 			/* b = IE1                */
4962 			/* S = IE1 length + cont. */
4963 			/* b = IE2                */
4964 			/* S = IE2 length + cont. */
4965 			sendf(plci->appl,
4966 			      _MANUFACTURER_I,
4967 			      Id,
4968 			      0,
4969 			      "dwbbbbSbS", _DI_MANU_ID, plci->m_command,
4970 			      2 + 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], plci->Sig.Ind, 1 + 1 + esc_cr[0] + 1 + 1 + esc_law[0], ESC, esc_cr, ESC, esc_law);
4971 		}
4972 	}
4973 	/* create the additional info structure                                  */
4974 	add_i[1] = parms[15]; /* KEY of additional info */
4975 	add_i[2] = parms[11]; /* UUI of additional info */
4976 	ai_len = AddInfo(add_i, multi_fac_parms, esc_chi, facility);
4977 
4978 	/* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4979 	/* indication returns by the card if requested by the function           */
4980 	/* AutomaticLaw() after driver init                                      */
4981 	if (a->automatic_law < 4)
4982 	{
4983 		if (esc_law[0]) {
4984 			if (esc_law[2]) {
4985 				dbug(0, dprintf("u-Law selected"));
4986 				a->u_law = 1;
4987 			}
4988 			else {
4989 				dbug(0, dprintf("a-Law selected"));
4990 				a->u_law = 0;
4991 			}
4992 			a->automatic_law = 4;
4993 			if (plci == a->automatic_lawPLCI) {
4994 				plci->internal_command = 0;
4995 				sig_req(plci, REMOVE, 0);
4996 				send_req(plci);
4997 				a->automatic_lawPLCI = NULL;
4998 			}
4999 		}
5000 		if (esc_profile[0])
5001 		{
5002 			dbug(1, dprintf("[%06x] CardProfile: %lx %lx %lx %lx %lx",
5003 					UnMapController(a->Id), GET_DWORD(&esc_profile[6]),
5004 					GET_DWORD(&esc_profile[10]), GET_DWORD(&esc_profile[14]),
5005 					GET_DWORD(&esc_profile[18]), GET_DWORD(&esc_profile[46])));
5006 
5007 			a->profile.Global_Options &= 0x000000ffL;
5008 			a->profile.B1_Protocols &= 0x000003ffL;
5009 			a->profile.B2_Protocols &= 0x00001fdfL;
5010 			a->profile.B3_Protocols &= 0x000000b7L;
5011 
5012 			a->profile.Global_Options &= GET_DWORD(&esc_profile[6]) |
5013 				GL_BCHANNEL_OPERATION_SUPPORTED;
5014 			a->profile.B1_Protocols &= GET_DWORD(&esc_profile[10]);
5015 			a->profile.B2_Protocols &= GET_DWORD(&esc_profile[14]);
5016 			a->profile.B3_Protocols &= GET_DWORD(&esc_profile[18]);
5017 			a->manufacturer_features = GET_DWORD(&esc_profile[46]);
5018 			a->man_profile.private_options = 0;
5019 
5020 			if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5021 			{
5022 				a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5023 				a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5024 			}
5025 
5026 
5027 			if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5028 				a->man_profile.private_options |= 1L << PRIVATE_RTP;
5029 			a->man_profile.rtp_primary_payloads = GET_DWORD(&esc_profile[50]);
5030 			a->man_profile.rtp_additional_payloads = GET_DWORD(&esc_profile[54]);
5031 
5032 
5033 			if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5034 				a->man_profile.private_options |= 1L << PRIVATE_T38;
5035 
5036 
5037 			if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5038 				a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5039 
5040 
5041 			if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5042 				a->man_profile.private_options |= 1L << PRIVATE_V18;
5043 
5044 
5045 			if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5046 				a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5047 
5048 
5049 			if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5050 				a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5051 
5052 
5053 			if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5054 				a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5055 
5056 
5057 			if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5058 				a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5059 
5060 
5061 			if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5062 				a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5063 
5064 		}
5065 		else
5066 		{
5067 			a->profile.Global_Options &= 0x0000007fL;
5068 			a->profile.B1_Protocols &= 0x000003dfL;
5069 			a->profile.B2_Protocols &= 0x00001adfL;
5070 			a->profile.B3_Protocols &= 0x000000b7L;
5071 			a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5072 		}
5073 		if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5074 						MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5075 		{
5076 			a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5077 		}
5078 		a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5079 		dbug(1, dprintf("[%06x] Profile: %lx %lx %lx %lx %lx",
5080 				UnMapController(a->Id), a->profile.Global_Options,
5081 				a->profile.B1_Protocols, a->profile.B2_Protocols,
5082 				a->profile.B3_Protocols, a->manufacturer_features));
5083 	}
5084 	/* codec plci for the handset/hook state support is just an internal id  */
5085 	if (plci != a->AdvCodecPLCI)
5086 	{
5087 		force_mt_info = SendMultiIE(plci, Id, multi_fac_parms, FTY, 0x20, 0);
5088 		force_mt_info |= SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, 0);
5089 		SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
5090 		SendInfo(plci, Id, parms, force_mt_info);
5091 
5092 		VSwitchReqInd(plci, Id, multi_vswitch_parms);
5093 
5094 	}
5095 
5096 	/* switch the codec to the b-channel                                     */
5097 	if (esc_chi[0] && plci && !plci->SuppState) {
5098 		plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5099 		mixer_set_bchannel_id_esc(plci, plci->b_channel);
5100 		dbug(1, dprintf("storeChannel=0x%x", plci->b_channel));
5101 		if (plci->tel == ADV_VOICE && plci->appl) {
5102 			SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5103 		}
5104 	}
5105 
5106 	if (plci->appl) plci->appl->Number++;
5107 
5108 	switch (plci->Sig.Ind) {
5109 		/* Response to Get_Supported_Services request */
5110 	case S_SUPPORTED:
5111 		dbug(1, dprintf("S_Supported"));
5112 		if (!plci->appl) break;
5113 		if (pty_cai[0] == 4)
5114 		{
5115 			PUT_DWORD(&CF_Ind[6], GET_DWORD(&pty_cai[1]));
5116 		}
5117 		else
5118 		{
5119 			PUT_DWORD(&CF_Ind[6], MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5120 		}
5121 		PUT_WORD(&CF_Ind[1], 0);
5122 		PUT_WORD(&CF_Ind[4], 0);
5123 		sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0x7, plci->number, "wws", 0, 3, CF_Ind);
5124 		plci_remove(plci);
5125 		break;
5126 
5127 		/* Supplementary Service rejected */
5128 	case S_SERVICE_REJ:
5129 		dbug(1, dprintf("S_Reject=0x%x", pty_cai[5]));
5130 		if (!pty_cai[0]) break;
5131 		switch (pty_cai[5])
5132 		{
5133 		case ECT_EXECUTE:
5134 		case THREE_PTY_END:
5135 		case THREE_PTY_BEGIN:
5136 			if (!plci->relatedPTYPLCI) break;
5137 			tplci = plci->relatedPTYPLCI;
5138 			rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5139 			if (tplci->tel) rId |= EXT_CONTROLLER;
5140 			if (pty_cai[5] == ECT_EXECUTE)
5141 			{
5142 				PUT_WORD(&SS_Ind[1], S_ECT);
5143 
5144 				plci->vswitchstate = 0;
5145 				plci->relatedPTYPLCI->vswitchstate = 0;
5146 
5147 			}
5148 			else
5149 			{
5150 				PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5151 			}
5152 			if (pty_cai[2] != 0xff)
5153 			{
5154 				PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5155 			}
5156 			else
5157 			{
5158 				PUT_WORD(&SS_Ind[4], 0x300E);
5159 			}
5160 			plci->relatedPTYPLCI = NULL;
5161 			plci->ptyState = 0;
5162 			sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5163 			break;
5164 
5165 		case CALL_DEFLECTION:
5166 			if (pty_cai[2] != 0xff)
5167 			{
5168 				PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5169 			}
5170 			else
5171 			{
5172 				PUT_WORD(&SS_Ind[4], 0x300E);
5173 			}
5174 			PUT_WORD(&SS_Ind[1], pty_cai[5]);
5175 			for (i = 0; i < max_appl; i++)
5176 			{
5177 				if (application[i].CDEnable)
5178 				{
5179 					if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5180 					application[i].CDEnable = false;
5181 				}
5182 			}
5183 			break;
5184 
5185 		case DEACTIVATION_DIVERSION:
5186 		case ACTIVATION_DIVERSION:
5187 		case DIVERSION_INTERROGATE_CFU:
5188 		case DIVERSION_INTERROGATE_CFB:
5189 		case DIVERSION_INTERROGATE_CFNR:
5190 		case DIVERSION_INTERROGATE_NUM:
5191 		case CCBS_REQUEST:
5192 		case CCBS_DEACTIVATE:
5193 		case CCBS_INTERROGATE:
5194 			if (!plci->appl) break;
5195 			if (pty_cai[2] != 0xff)
5196 			{
5197 				PUT_WORD(&Interr_Err_Ind[4], 0x3600 | (word)pty_cai[2]);
5198 			}
5199 			else
5200 			{
5201 				PUT_WORD(&Interr_Err_Ind[4], 0x300E);
5202 			}
5203 			switch (pty_cai[5])
5204 			{
5205 			case DEACTIVATION_DIVERSION:
5206 				dbug(1, dprintf("Deact_Div"));
5207 				Interr_Err_Ind[0] = 0x9;
5208 				Interr_Err_Ind[3] = 0x6;
5209 				PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_STOP);
5210 				break;
5211 			case ACTIVATION_DIVERSION:
5212 				dbug(1, dprintf("Act_Div"));
5213 				Interr_Err_Ind[0] = 0x9;
5214 				Interr_Err_Ind[3] = 0x6;
5215 				PUT_WORD(&Interr_Err_Ind[1], S_CALL_FORWARDING_START);
5216 				break;
5217 			case DIVERSION_INTERROGATE_CFU:
5218 			case DIVERSION_INTERROGATE_CFB:
5219 			case DIVERSION_INTERROGATE_CFNR:
5220 				dbug(1, dprintf("Interr_Div"));
5221 				Interr_Err_Ind[0] = 0xa;
5222 				Interr_Err_Ind[3] = 0x7;
5223 				PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_DIVERSION);
5224 				break;
5225 			case DIVERSION_INTERROGATE_NUM:
5226 				dbug(1, dprintf("Interr_Num"));
5227 				Interr_Err_Ind[0] = 0xa;
5228 				Interr_Err_Ind[3] = 0x7;
5229 				PUT_WORD(&Interr_Err_Ind[1], S_INTERROGATE_NUMBERS);
5230 				break;
5231 			case CCBS_REQUEST:
5232 				dbug(1, dprintf("CCBS Request"));
5233 				Interr_Err_Ind[0] = 0xd;
5234 				Interr_Err_Ind[3] = 0xa;
5235 				PUT_WORD(&Interr_Err_Ind[1], S_CCBS_REQUEST);
5236 				break;
5237 			case CCBS_DEACTIVATE:
5238 				dbug(1, dprintf("CCBS Deactivate"));
5239 				Interr_Err_Ind[0] = 0x9;
5240 				Interr_Err_Ind[3] = 0x6;
5241 				PUT_WORD(&Interr_Err_Ind[1], S_CCBS_DEACTIVATE);
5242 				break;
5243 			case CCBS_INTERROGATE:
5244 				dbug(1, dprintf("CCBS Interrogate"));
5245 				Interr_Err_Ind[0] = 0xb;
5246 				Interr_Err_Ind[3] = 0x8;
5247 				PUT_WORD(&Interr_Err_Ind[1], S_CCBS_INTERROGATE);
5248 				break;
5249 			}
5250 			PUT_DWORD(&Interr_Err_Ind[6], plci->appl->S_Handle);
5251 			sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, Interr_Err_Ind);
5252 			plci_remove(plci);
5253 			break;
5254 		case ACTIVATION_MWI:
5255 		case DEACTIVATION_MWI:
5256 			if (pty_cai[5] == ACTIVATION_MWI)
5257 			{
5258 				PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5259 			}
5260 			else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5261 
5262 			if (pty_cai[2] != 0xff)
5263 			{
5264 				PUT_WORD(&SS_Ind[4], 0x3600 | (word)pty_cai[2]);
5265 			}
5266 			else
5267 			{
5268 				PUT_WORD(&SS_Ind[4], 0x300E);
5269 			}
5270 
5271 			if (plci->cr_enquiry)
5272 			{
5273 				sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5274 				plci_remove(plci);
5275 			}
5276 			else
5277 			{
5278 				sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5279 			}
5280 			break;
5281 		case CONF_ADD: /* ERROR */
5282 		case CONF_BEGIN:
5283 		case CONF_DROP:
5284 		case CONF_ISOLATE:
5285 		case CONF_REATTACH:
5286 			CONF_Ind[0] = 9;
5287 			CONF_Ind[3] = 6;
5288 			switch (pty_cai[5])
5289 			{
5290 			case CONF_BEGIN:
5291 				PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5292 				plci->ptyState = 0;
5293 				break;
5294 			case CONF_DROP:
5295 				CONF_Ind[0] = 5;
5296 				CONF_Ind[3] = 2;
5297 				PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5298 				plci->ptyState = CONNECTED;
5299 				break;
5300 			case CONF_ISOLATE:
5301 				CONF_Ind[0] = 5;
5302 				CONF_Ind[3] = 2;
5303 				PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5304 				plci->ptyState = CONNECTED;
5305 				break;
5306 			case CONF_REATTACH:
5307 				CONF_Ind[0] = 5;
5308 				CONF_Ind[3] = 2;
5309 				PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5310 				plci->ptyState = CONNECTED;
5311 				break;
5312 			case CONF_ADD:
5313 				PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5314 				plci->relatedPTYPLCI = NULL;
5315 				tplci = plci->relatedPTYPLCI;
5316 				if (tplci) tplci->ptyState = CONNECTED;
5317 				plci->ptyState = CONNECTED;
5318 				break;
5319 			}
5320 
5321 			if (pty_cai[2] != 0xff)
5322 			{
5323 				PUT_WORD(&CONF_Ind[4], 0x3600 | (word)pty_cai[2]);
5324 			}
5325 			else
5326 			{
5327 				PUT_WORD(&CONF_Ind[4], 0x3303); /* Time-out: network did not respond
5328 								  within the required time */
5329 			}
5330 
5331 			PUT_DWORD(&CONF_Ind[6], 0x0);
5332 			sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5333 			break;
5334 		}
5335 		break;
5336 
5337 		/* Supplementary Service indicates success */
5338 	case S_SERVICE:
5339 		dbug(1, dprintf("Service_Ind"));
5340 		PUT_WORD(&CF_Ind[4], 0);
5341 		switch (pty_cai[5])
5342 		{
5343 		case THREE_PTY_END:
5344 		case THREE_PTY_BEGIN:
5345 		case ECT_EXECUTE:
5346 			if (!plci->relatedPTYPLCI) break;
5347 			tplci = plci->relatedPTYPLCI;
5348 			rId = ((word)tplci->Id << 8) | tplci->adapter->Id;
5349 			if (tplci->tel) rId |= EXT_CONTROLLER;
5350 			if (pty_cai[5] == ECT_EXECUTE)
5351 			{
5352 				PUT_WORD(&SS_Ind[1], S_ECT);
5353 
5354 				if (plci->vswitchstate != 3)
5355 				{
5356 
5357 					plci->ptyState = IDLE;
5358 					plci->relatedPTYPLCI = NULL;
5359 					plci->ptyState = 0;
5360 
5361 				}
5362 
5363 				dbug(1, dprintf("ECT OK"));
5364 				sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5365 
5366 
5367 
5368 			}
5369 			else
5370 			{
5371 				switch (plci->ptyState)
5372 				{
5373 				case S_3PTY_BEGIN:
5374 					plci->ptyState = CONNECTED;
5375 					dbug(1, dprintf("3PTY ON"));
5376 					break;
5377 
5378 				case S_3PTY_END:
5379 					plci->ptyState = IDLE;
5380 					plci->relatedPTYPLCI = NULL;
5381 					plci->ptyState = 0;
5382 					dbug(1, dprintf("3PTY OFF"));
5383 					break;
5384 				}
5385 				PUT_WORD(&SS_Ind[1], pty_cai[5] + 3);
5386 				sendf(tplci->appl, _FACILITY_I, rId, 0, "ws", 3, SS_Ind);
5387 			}
5388 			break;
5389 
5390 		case CALL_DEFLECTION:
5391 			PUT_WORD(&SS_Ind[1], pty_cai[5]);
5392 			for (i = 0; i < max_appl; i++)
5393 			{
5394 				if (application[i].CDEnable)
5395 				{
5396 					if (application[i].Id) sendf(&application[i], _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5397 					application[i].CDEnable = false;
5398 				}
5399 			}
5400 			break;
5401 
5402 		case DEACTIVATION_DIVERSION:
5403 		case ACTIVATION_DIVERSION:
5404 			if (!plci->appl) break;
5405 			PUT_WORD(&CF_Ind[1], pty_cai[5] + 2);
5406 			PUT_DWORD(&CF_Ind[6], plci->appl->S_Handle);
5407 			sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "ws", 3, CF_Ind);
5408 			plci_remove(plci);
5409 			break;
5410 
5411 		case DIVERSION_INTERROGATE_CFU:
5412 		case DIVERSION_INTERROGATE_CFB:
5413 		case DIVERSION_INTERROGATE_CFNR:
5414 		case DIVERSION_INTERROGATE_NUM:
5415 		case CCBS_REQUEST:
5416 		case CCBS_DEACTIVATE:
5417 		case CCBS_INTERROGATE:
5418 			if (!plci->appl) break;
5419 			switch (pty_cai[5])
5420 			{
5421 			case DIVERSION_INTERROGATE_CFU:
5422 			case DIVERSION_INTERROGATE_CFB:
5423 			case DIVERSION_INTERROGATE_CFNR:
5424 				dbug(1, dprintf("Interr_Div"));
5425 				PUT_WORD(&pty_cai[1], S_INTERROGATE_DIVERSION);
5426 				pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5427 				break;
5428 			case DIVERSION_INTERROGATE_NUM:
5429 				dbug(1, dprintf("Interr_Num"));
5430 				PUT_WORD(&pty_cai[1], S_INTERROGATE_NUMBERS);
5431 				pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5432 				break;
5433 			case CCBS_REQUEST:
5434 				dbug(1, dprintf("CCBS Request"));
5435 				PUT_WORD(&pty_cai[1], S_CCBS_REQUEST);
5436 				pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5437 				break;
5438 			case CCBS_DEACTIVATE:
5439 				dbug(1, dprintf("CCBS Deactivate"));
5440 				PUT_WORD(&pty_cai[1], S_CCBS_DEACTIVATE);
5441 				pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5442 				break;
5443 			case CCBS_INTERROGATE:
5444 				dbug(1, dprintf("CCBS Interrogate"));
5445 				PUT_WORD(&pty_cai[1], S_CCBS_INTERROGATE);
5446 				pty_cai[3] = pty_cai[0] - 3; /* Supplementary Service-specific parameter len */
5447 				break;
5448 			}
5449 			PUT_WORD(&pty_cai[4], 0); /* Supplementary Service Reason */
5450 			PUT_DWORD(&pty_cai[6], plci->appl->S_Handle);
5451 			sendf(plci->appl, _FACILITY_I, Id & 0x7, 0, "wS", 3, pty_cai);
5452 			plci_remove(plci);
5453 			break;
5454 
5455 		case ACTIVATION_MWI:
5456 		case DEACTIVATION_MWI:
5457 			if (pty_cai[5] == ACTIVATION_MWI)
5458 			{
5459 				PUT_WORD(&SS_Ind[1], S_MWI_ACTIVATE);
5460 			}
5461 			else PUT_WORD(&SS_Ind[1], S_MWI_DEACTIVATE);
5462 			if (plci->cr_enquiry)
5463 			{
5464 				sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "ws", 3, SS_Ind);
5465 				plci_remove(plci);
5466 			}
5467 			else
5468 			{
5469 				sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5470 			}
5471 			break;
5472 		case MWI_INDICATION:
5473 			if (pty_cai[0] >= 0x12)
5474 			{
5475 				PUT_WORD(&pty_cai[3], S_MWI_INDICATE);
5476 				pty_cai[2] = pty_cai[0] - 2; /* len Parameter */
5477 				pty_cai[5] = pty_cai[0] - 5; /* Supplementary Service-specific parameter len */
5478 				if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_MWI))
5479 				{
5480 					if (plci->internal_command == GET_MWI_STATE) /* result on Message Waiting Listen */
5481 					{
5482 						sendf(plci->appl, _FACILITY_I, Id & 0xf, 0, "wS", 3, &pty_cai[2]);
5483 						plci_remove(plci);
5484 						return;
5485 					}
5486 					else sendf(plci->appl, _FACILITY_I, Id, 0, "wS", 3, &pty_cai[2]);
5487 					pty_cai[0] = 0;
5488 				}
5489 				else
5490 				{
5491 					for (i = 0; i < max_appl; i++)
5492 					{
5493 						if (a->Notification_Mask[i]&SMASK_MWI)
5494 						{
5495 							sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "wS", 3, &pty_cai[2]);
5496 							pty_cai[0] = 0;
5497 						}
5498 					}
5499 				}
5500 
5501 				if (!pty_cai[0])
5502 				{ /* acknowledge */
5503 					facility[2] = 0; /* returncode */
5504 				}
5505 				else facility[2] = 0xff;
5506 			}
5507 			else
5508 			{
5509 				/* reject */
5510 				facility[2] = 0xff; /* returncode */
5511 			}
5512 			facility[0] = 2;
5513 			facility[1] = MWI_RESPONSE; /* Function */
5514 			add_p(plci, CAI, facility);
5515 			add_p(plci, ESC, multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5516 			sig_req(plci, S_SERVICE, 0);
5517 			send_req(plci);
5518 			plci->command = 0;
5519 			next_internal_command(Id, plci);
5520 			break;
5521 		case CONF_ADD: /* OK */
5522 		case CONF_BEGIN:
5523 		case CONF_DROP:
5524 		case CONF_ISOLATE:
5525 		case CONF_REATTACH:
5526 		case CONF_PARTYDISC:
5527 			CONF_Ind[0] = 9;
5528 			CONF_Ind[3] = 6;
5529 			switch (pty_cai[5])
5530 			{
5531 			case CONF_BEGIN:
5532 				PUT_WORD(&CONF_Ind[1], S_CONF_BEGIN);
5533 				if (pty_cai[0] == 6)
5534 				{
5535 					d = pty_cai[6];
5536 					PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5537 				}
5538 				else
5539 				{
5540 					PUT_DWORD(&CONF_Ind[6], 0x0);
5541 				}
5542 				break;
5543 			case CONF_ISOLATE:
5544 				PUT_WORD(&CONF_Ind[1], S_CONF_ISOLATE);
5545 				CONF_Ind[0] = 5;
5546 				CONF_Ind[3] = 2;
5547 				break;
5548 			case CONF_REATTACH:
5549 				PUT_WORD(&CONF_Ind[1], S_CONF_REATTACH);
5550 				CONF_Ind[0] = 5;
5551 				CONF_Ind[3] = 2;
5552 				break;
5553 			case CONF_DROP:
5554 				PUT_WORD(&CONF_Ind[1], S_CONF_DROP);
5555 				CONF_Ind[0] = 5;
5556 				CONF_Ind[3] = 2;
5557 				break;
5558 			case CONF_ADD:
5559 				PUT_WORD(&CONF_Ind[1], S_CONF_ADD);
5560 				d = pty_cai[6];
5561 				PUT_DWORD(&CONF_Ind[6], d); /* PartyID */
5562 				tplci = plci->relatedPTYPLCI;
5563 				if (tplci) tplci->ptyState = CONNECTED;
5564 				break;
5565 			case CONF_PARTYDISC:
5566 				CONF_Ind[0] = 7;
5567 				CONF_Ind[3] = 4;
5568 				PUT_WORD(&CONF_Ind[1], S_CONF_PARTYDISC);
5569 				d = pty_cai[6];
5570 				PUT_DWORD(&CONF_Ind[4], d); /* PartyID */
5571 				break;
5572 			}
5573 			plci->ptyState = CONNECTED;
5574 			sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5575 			break;
5576 		case CCBS_INFO_RETAIN:
5577 		case CCBS_ERASECALLLINKAGEID:
5578 		case CCBS_STOP_ALERTING:
5579 			CONF_Ind[0] = 5;
5580 			CONF_Ind[3] = 2;
5581 			switch (pty_cai[5])
5582 			{
5583 			case CCBS_INFO_RETAIN:
5584 				PUT_WORD(&CONF_Ind[1], S_CCBS_INFO_RETAIN);
5585 				break;
5586 			case CCBS_STOP_ALERTING:
5587 				PUT_WORD(&CONF_Ind[1], S_CCBS_STOP_ALERTING);
5588 				break;
5589 			case CCBS_ERASECALLLINKAGEID:
5590 				PUT_WORD(&CONF_Ind[1], S_CCBS_ERASECALLLINKAGEID);
5591 				CONF_Ind[0] = 7;
5592 				CONF_Ind[3] = 4;
5593 				CONF_Ind[6] = 0;
5594 				CONF_Ind[7] = 0;
5595 				break;
5596 			}
5597 			w = pty_cai[6];
5598 			PUT_WORD(&CONF_Ind[4], w); /* PartyID */
5599 
5600 			if (plci->appl && (a->Notification_Mask[plci->appl->Id - 1] & SMASK_CCBS))
5601 			{
5602 				sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, CONF_Ind);
5603 			}
5604 			else
5605 			{
5606 				for (i = 0; i < max_appl; i++)
5607 					if (a->Notification_Mask[i] & SMASK_CCBS)
5608 						sendf(&application[i], _FACILITY_I, Id & 0x7, 0, "ws", 3, CONF_Ind);
5609 			}
5610 			break;
5611 		}
5612 		break;
5613 	case CALL_HOLD_REJ:
5614 		cau = parms[7];
5615 		if (cau)
5616 		{
5617 			i = _L3_CAUSE | cau[2];
5618 			if (cau[2] == 0) i = 0x3603;
5619 		}
5620 		else
5621 		{
5622 			i = 0x3603;
5623 		}
5624 		PUT_WORD(&SS_Ind[1], S_HOLD);
5625 		PUT_WORD(&SS_Ind[4], i);
5626 		if (plci->SuppState == HOLD_REQUEST)
5627 		{
5628 			plci->SuppState = IDLE;
5629 			sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5630 		}
5631 		break;
5632 
5633 	case CALL_HOLD_ACK:
5634 		if (plci->SuppState == HOLD_REQUEST)
5635 		{
5636 			plci->SuppState = CALL_HELD;
5637 			CodecIdCheck(a, plci);
5638 			start_internal_command(Id, plci, hold_save_command);
5639 		}
5640 		break;
5641 
5642 	case CALL_RETRIEVE_REJ:
5643 		cau = parms[7];
5644 		if (cau)
5645 		{
5646 			i = _L3_CAUSE | cau[2];
5647 			if (cau[2] == 0) i = 0x3603;
5648 		}
5649 		else
5650 		{
5651 			i = 0x3603;
5652 		}
5653 		PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5654 		PUT_WORD(&SS_Ind[4], i);
5655 		if (plci->SuppState == RETRIEVE_REQUEST)
5656 		{
5657 			plci->SuppState = CALL_HELD;
5658 			CodecIdCheck(a, plci);
5659 			sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5660 		}
5661 		break;
5662 
5663 	case CALL_RETRIEVE_ACK:
5664 		PUT_WORD(&SS_Ind[1], S_RETRIEVE);
5665 		if (plci->SuppState == RETRIEVE_REQUEST)
5666 		{
5667 			plci->SuppState = IDLE;
5668 			plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5669 			plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5670 			if (plci->tel)
5671 			{
5672 				mixer_set_bchannel_id_esc(plci, plci->b_channel);
5673 				dbug(1, dprintf("RetrChannel=0x%x", plci->b_channel));
5674 				SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5675 				if (plci->B2_prot == B2_TRANSPARENT && plci->B3_prot == B3_TRANSPARENT)
5676 				{
5677 					dbug(1, dprintf("Get B-ch"));
5678 					start_internal_command(Id, plci, retrieve_restore_command);
5679 				}
5680 				else
5681 					sendf(plci->appl, _FACILITY_I, Id, 0, "ws", 3, SS_Ind);
5682 			}
5683 			else
5684 				start_internal_command(Id, plci, retrieve_restore_command);
5685 		}
5686 		break;
5687 
5688 	case INDICATE_IND:
5689 		if (plci->State != LISTENING) {
5690 			sig_req(plci, HANGUP, 0);
5691 			send_req(plci);
5692 			break;
5693 		}
5694 		cip = find_cip(a, parms[4], parms[6]);
5695 		cip_mask = 1L << cip;
5696 		dbug(1, dprintf("cip=%d,cip_mask=%lx", cip, cip_mask));
5697 		clear_c_ind_mask(plci);
5698 		if (!remove_started && !a->adapter_disabled)
5699 		{
5700 			set_c_ind_mask_bit(plci, MAX_APPL);
5701 			group_optimization(a, plci);
5702 			for (i = 0; i < max_appl; i++) {
5703 				if (application[i].Id
5704 				    && (a->CIP_Mask[i] & 1 || a->CIP_Mask[i] & cip_mask)
5705 				    && CPN_filter_ok(parms[0], a, i)
5706 				    && test_group_ind_mask_bit(plci, i)) {
5707 					dbug(1, dprintf("storedcip_mask[%d]=0x%lx", i, a->CIP_Mask[i]));
5708 					set_c_ind_mask_bit(plci, i);
5709 					dump_c_ind_mask(plci);
5710 					plci->State = INC_CON_PENDING;
5711 					plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5712 						CALL_DIR_IN | CALL_DIR_ANSWER;
5713 					if (esc_chi[0]) {
5714 						plci->b_channel = esc_chi[esc_chi[0]] & 0x1f;
5715 						mixer_set_bchannel_id_esc(plci, plci->b_channel);
5716 					}
5717 					/* if a listen on the ext controller is done, check if hook states */
5718 					/* are supported or if just a on board codec must be activated     */
5719 					if (a->codec_listen[i] && !a->AdvSignalPLCI) {
5720 						if (a->profile.Global_Options & HANDSET)
5721 							plci->tel = ADV_VOICE;
5722 						else if (a->profile.Global_Options & ON_BOARD_CODEC)
5723 							plci->tel = CODEC;
5724 						if (plci->tel) Id |= EXT_CONTROLLER;
5725 						a->codec_listen[i] = plci;
5726 					}
5727 
5728 					sendf(&application[i], _CONNECT_I, Id, 0,
5729 					      "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5730 					      parms[0],    /* CalledPartyNumber   */
5731 					      multi_CiPN_parms[0],    /* CallingPartyNumber  */
5732 					      parms[2],    /* CalledPartySubad    */
5733 					      parms[3],    /* CallingPartySubad   */
5734 					      parms[4],    /* BearerCapability    */
5735 					      parms[5],    /* LowLC               */
5736 					      parms[6],    /* HighLC              */
5737 					      ai_len,      /* nested struct add_i */
5738 					      add_i[0],    /* B channel info    */
5739 					      add_i[1],    /* keypad facility   */
5740 					      add_i[2],    /* user user data    */
5741 					      add_i[3],    /* nested facility   */
5742 					      multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5743 						);
5744 					SendSSExtInd(&application[i],
5745 						     plci,
5746 						     Id,
5747 						     multi_ssext_parms);
5748 					SendSetupInfo(&application[i],
5749 						      plci,
5750 						      Id,
5751 						      parms,
5752 						      SendMultiIE(plci, Id, multi_pi_parms, PI, 0x210, true));
5753 				}
5754 			}
5755 			clear_c_ind_mask_bit(plci, MAX_APPL);
5756 			dump_c_ind_mask(plci);
5757 		}
5758 		if (c_ind_mask_empty(plci)) {
5759 			sig_req(plci, HANGUP, 0);
5760 			send_req(plci);
5761 			plci->State = IDLE;
5762 		}
5763 		plci->notifiedcall = 0;
5764 		a->listen_active--;
5765 		listen_check(a);
5766 		break;
5767 
5768 	case CALL_PEND_NOTIFY:
5769 		plci->notifiedcall = 1;
5770 		listen_check(a);
5771 		break;
5772 
5773 	case CALL_IND:
5774 	case CALL_CON:
5775 		if (plci->State == ADVANCED_VOICE_SIG || plci->State == ADVANCED_VOICE_NOSIG)
5776 		{
5777 			if (plci->internal_command == PERM_COD_CONN_PEND)
5778 			{
5779 				if (plci->State == ADVANCED_VOICE_NOSIG)
5780 				{
5781 					dbug(1, dprintf("***Codec OK"));
5782 					if (a->AdvSignalPLCI)
5783 					{
5784 						tplci = a->AdvSignalPLCI;
5785 						if (tplci->spoofed_msg)
5786 						{
5787 							dbug(1, dprintf("***Spoofed Msg(0x%x)", tplci->spoofed_msg));
5788 							tplci->command = 0;
5789 							tplci->internal_command = 0;
5790 							x_Id = ((word)tplci->Id << 8) | tplci->adapter->Id | 0x80;
5791 							switch (tplci->spoofed_msg)
5792 							{
5793 							case CALL_RES:
5794 								tplci->command = _CONNECT_I | RESPONSE;
5795 								api_load_msg(&tplci->saved_msg, saved_parms);
5796 								add_b1(tplci, &saved_parms[1], 0, tplci->B1_facilities);
5797 								if (tplci->adapter->Info_Mask[tplci->appl->Id - 1] & 0x200)
5798 								{
5799 									/* early B3 connect (CIP mask bit 9) no release after a disc */
5800 									add_p(tplci, LLI, "\x01\x01");
5801 								}
5802 								add_s(tplci, CONN_NR, &saved_parms[2]);
5803 								add_s(tplci, LLC, &saved_parms[4]);
5804 								add_ai(tplci, &saved_parms[5]);
5805 								tplci->State = INC_CON_ACCEPT;
5806 								sig_req(tplci, CALL_RES, 0);
5807 								send_req(tplci);
5808 								break;
5809 
5810 							case AWAITING_SELECT_B:
5811 								dbug(1, dprintf("Select_B continue"));
5812 								start_internal_command(x_Id, tplci, select_b_command);
5813 								break;
5814 
5815 							case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5816 								if (!tplci->Sig.Id)
5817 								{
5818 									dbug(1, dprintf("No SigID!"));
5819 									sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, _OUT_OF_PLCI);
5820 									plci_remove(tplci);
5821 									break;
5822 								}
5823 								tplci->command = _MANUFACTURER_R;
5824 								api_load_msg(&tplci->saved_msg, saved_parms);
5825 								dir = saved_parms[2].info[0];
5826 								if (dir == 1) {
5827 									sig_req(tplci, CALL_REQ, 0);
5828 								}
5829 								else if (!dir) {
5830 									sig_req(tplci, LISTEN_REQ, 0);
5831 								}
5832 								send_req(tplci);
5833 								sendf(tplci->appl, _MANUFACTURER_R | CONFIRM, x_Id, tplci->number, "dww", _DI_MANU_ID, _MANUFACTURER_R, 0);
5834 								break;
5835 
5836 							case (CALL_REQ | AWAITING_MANUF_CON):
5837 								sig_req(tplci, CALL_REQ, 0);
5838 								send_req(tplci);
5839 								break;
5840 
5841 							case CALL_REQ:
5842 								if (!tplci->Sig.Id)
5843 								{
5844 									dbug(1, dprintf("No SigID!"));
5845 									sendf(tplci->appl, _CONNECT_R | CONFIRM, tplci->adapter->Id, 0, "w", _OUT_OF_PLCI);
5846 									plci_remove(tplci);
5847 									break;
5848 								}
5849 								tplci->command = _CONNECT_R;
5850 								api_load_msg(&tplci->saved_msg, saved_parms);
5851 								add_s(tplci, CPN, &saved_parms[1]);
5852 								add_s(tplci, DSA, &saved_parms[3]);
5853 								add_ai(tplci, &saved_parms[9]);
5854 								sig_req(tplci, CALL_REQ, 0);
5855 								send_req(tplci);
5856 								break;
5857 
5858 							case CALL_RETRIEVE:
5859 								tplci->command = C_RETRIEVE_REQ;
5860 								sig_req(tplci, CALL_RETRIEVE, 0);
5861 								send_req(tplci);
5862 								break;
5863 							}
5864 							tplci->spoofed_msg = 0;
5865 							if (tplci->internal_command == 0)
5866 								next_internal_command(x_Id, tplci);
5867 						}
5868 					}
5869 					next_internal_command(Id, plci);
5870 					break;
5871 				}
5872 				dbug(1, dprintf("***Codec Hook Init Req"));
5873 				plci->internal_command = PERM_COD_HOOK;
5874 				add_p(plci, FTY, "\x01\x09");             /* Get Hook State*/
5875 				sig_req(plci, TEL_CTRL, 0);
5876 				send_req(plci);
5877 			}
5878 		}
5879 		else if (plci->command != _MANUFACTURER_R  /* old style permanent connect */
5880 			 && plci->State != INC_ACT_PENDING)
5881 		{
5882 			mixer_set_bchannel_id_esc(plci, plci->b_channel);
5883 			if (plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5884 			{
5885 				chi[2] = plci->b_channel;
5886 				SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5887 			}
5888 			sendf(plci->appl, _CONNECT_ACTIVE_I, Id, 0, "Sss", parms[21], "", "");
5889 			plci->State = INC_ACT_PENDING;
5890 		}
5891 		break;
5892 
5893 	case TEL_CTRL:
5894 		ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5895 		if (plci->State == ADVANCED_VOICE_SIG && ie[0]) {
5896 			switch (ie[1] & 0x91) {
5897 			case 0x80:   /* hook off */
5898 			case 0x81:
5899 				if (plci->internal_command == PERM_COD_HOOK)
5900 				{
5901 					dbug(1, dprintf("init:hook_off"));
5902 					plci->hook_state = ie[1];
5903 					next_internal_command(Id, plci);
5904 					break;
5905 				}
5906 				else /* ignore doubled hook indications */
5907 				{
5908 					if (((plci->hook_state) & 0xf0) == 0x80)
5909 					{
5910 						dbug(1, dprintf("ignore hook"));
5911 						break;
5912 					}
5913 					plci->hook_state = ie[1]&0x91;
5914 				}
5915 				/* check for incoming call pending */
5916 				/* and signal '+'.Appl must decide */
5917 				/* with connect_res if call must   */
5918 				/* accepted or not                 */
5919 				for (i = 0, tplci = NULL; i < max_appl; i++) {
5920 					if (a->codec_listen[i]
5921 					    && (a->codec_listen[i]->State == INC_CON_PENDING
5922 						|| a->codec_listen[i]->State == INC_CON_ALERT)) {
5923 						tplci = a->codec_listen[i];
5924 						tplci->appl = &application[i];
5925 					}
5926 				}
5927 				/* no incoming call, do outgoing call */
5928 				/* and signal '+' if outg. setup   */
5929 				if (!a->AdvSignalPLCI && !tplci) {
5930 					if ((i = get_plci(a))) {
5931 						a->AdvSignalPLCI = &a->plci[i - 1];
5932 						tplci = a->AdvSignalPLCI;
5933 						tplci->tel  = ADV_VOICE;
5934 						PUT_WORD(&voice_cai[5], a->AdvSignalAppl->MaxDataLength);
5935 						if (a->Info_Mask[a->AdvSignalAppl->Id - 1] & 0x200) {
5936 							/* early B3 connect (CIP mask bit 9) no release after a disc */
5937 							add_p(tplci, LLI, "\x01\x01");
5938 						}
5939 						add_p(tplci, CAI, voice_cai);
5940 						add_p(tplci, OAD, a->TelOAD);
5941 						add_p(tplci, OSA, a->TelOSA);
5942 						add_p(tplci, SHIFT | 6, NULL);
5943 						add_p(tplci, SIN, "\x02\x01\x00");
5944 						add_p(tplci, UID, "\x06\x43\x61\x70\x69\x32\x30");
5945 						sig_req(tplci, ASSIGN, DSIG_ID);
5946 						a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5947 						a->AdvSignalPLCI->command = 0;
5948 						tplci->appl = a->AdvSignalAppl;
5949 						tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5950 						send_req(tplci);
5951 					}
5952 
5953 				}
5954 
5955 				if (!tplci) break;
5956 				Id = ((word)tplci->Id << 8) | a->Id;
5957 				Id |= EXT_CONTROLLER;
5958 				sendf(tplci->appl,
5959 				      _FACILITY_I,
5960 				      Id,
5961 				      0,
5962 				      "ws", (word)0, "\x01+");
5963 				break;
5964 
5965 			case 0x90:   /* hook on  */
5966 			case 0x91:
5967 				if (plci->internal_command == PERM_COD_HOOK)
5968 				{
5969 					dbug(1, dprintf("init:hook_on"));
5970 					plci->hook_state = ie[1] & 0x91;
5971 					next_internal_command(Id, plci);
5972 					break;
5973 				}
5974 				else /* ignore doubled hook indications */
5975 				{
5976 					if (((plci->hook_state) & 0xf0) == 0x90) break;
5977 					plci->hook_state = ie[1] & 0x91;
5978 				}
5979 				/* hangup the adv. voice call and signal '-' to the appl */
5980 				if (a->AdvSignalPLCI) {
5981 					Id = ((word)a->AdvSignalPLCI->Id << 8) | a->Id;
5982 					if (plci->tel) Id |= EXT_CONTROLLER;
5983 					sendf(a->AdvSignalAppl,
5984 					      _FACILITY_I,
5985 					      Id,
5986 					      0,
5987 					      "ws", (word)0, "\x01-");
5988 					a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5989 					a->AdvSignalPLCI->command = 0;
5990 					sig_req(a->AdvSignalPLCI, HANGUP, 0);
5991 					send_req(a->AdvSignalPLCI);
5992 				}
5993 				break;
5994 			}
5995 		}
5996 		break;
5997 
5998 	case RESUME:
5999 		clear_c_ind_mask_bit(plci, (word)(plci->appl->Id - 1));
6000 		PUT_WORD(&resume_cau[4], GOOD);
6001 		sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6002 		break;
6003 
6004 	case SUSPEND:
6005 		clear_c_ind_mask(plci);
6006 
6007 		if (plci->NL.Id && !plci->nl_remove_id) {
6008 			mixer_remove(plci);
6009 			nl_req_ncci(plci, REMOVE, 0);
6010 		}
6011 		if (!plci->sig_remove_id) {
6012 			plci->internal_command = 0;
6013 			sig_req(plci, REMOVE, 0);
6014 		}
6015 		send_req(plci);
6016 		if (!plci->channels) {
6017 			sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6018 			sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6019 		}
6020 		break;
6021 
6022 	case SUSPEND_REJ:
6023 		break;
6024 
6025 	case HANGUP:
6026 		plci->hangup_flow_ctrl_timer = 0;
6027 		if (plci->manufacturer && plci->State == LOCAL_CONNECT) break;
6028 		cau = parms[7];
6029 		if (cau) {
6030 			i = _L3_CAUSE | cau[2];
6031 			if (cau[2] == 0) i = 0;
6032 			else if (cau[2] == 8) i = _L1_ERROR;
6033 			else if (cau[2] == 9 || cau[2] == 10) i = _L2_ERROR;
6034 			else if (cau[2] == 5) i = _CAPI_GUARD_ERROR;
6035 		}
6036 		else {
6037 			i = _L3_ERROR;
6038 		}
6039 
6040 		if (plci->State == INC_CON_PENDING || plci->State == INC_CON_ALERT)
6041 		{
6042 			for (i = 0; i < max_appl; i++)
6043 			{
6044 				if (test_c_ind_mask_bit(plci, i))
6045 					sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6046 			}
6047 		}
6048 		else
6049 		{
6050 			clear_c_ind_mask(plci);
6051 		}
6052 		if (!plci->appl)
6053 		{
6054 			if (plci->State == LISTENING)
6055 			{
6056 				plci->notifiedcall = 0;
6057 				a->listen_active--;
6058 			}
6059 			plci->State = INC_DIS_PENDING;
6060 			if (c_ind_mask_empty(plci))
6061 			{
6062 				plci->State = IDLE;
6063 				if (plci->NL.Id && !plci->nl_remove_id)
6064 				{
6065 					mixer_remove(plci);
6066 					nl_req_ncci(plci, REMOVE, 0);
6067 				}
6068 				if (!plci->sig_remove_id)
6069 				{
6070 					plci->internal_command = 0;
6071 					sig_req(plci, REMOVE, 0);
6072 				}
6073 				send_req(plci);
6074 			}
6075 		}
6076 		else
6077 		{
6078 			/* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
6079 			/* result in a second HANGUP! Don't generate another        */
6080 			/* DISCONNECT                                               */
6081 			if (plci->State != IDLE && plci->State != INC_DIS_PENDING)
6082 			{
6083 				if (plci->State == RESUMING)
6084 				{
6085 					PUT_WORD(&resume_cau[4], i);
6086 					sendf(plci->appl, _FACILITY_I, Id, 0, "ws", (word)3, resume_cau);
6087 				}
6088 				plci->State = INC_DIS_PENDING;
6089 				sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", i);
6090 			}
6091 		}
6092 		break;
6093 
6094 	case SSEXT_IND:
6095 		SendSSExtInd(NULL, plci, Id, multi_ssext_parms);
6096 		break;
6097 
6098 	case VSWITCH_REQ:
6099 		VSwitchReqInd(plci, Id, multi_vswitch_parms);
6100 		break;
6101 	case VSWITCH_IND:
6102 		if (plci->relatedPTYPLCI &&
6103 		    plci->vswitchstate == 3 &&
6104 		    plci->relatedPTYPLCI->vswitchstate == 3 &&
6105 		    parms[MAXPARMSIDS - 1][0])
6106 		{
6107 			add_p(plci->relatedPTYPLCI, SMSG, parms[MAXPARMSIDS - 1]);
6108 			sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
6109 			send_req(plci->relatedPTYPLCI);
6110 		}
6111 		else VSwitchReqInd(plci, Id, multi_vswitch_parms);
6112 		break;
6113 
6114 	}
6115 }
6116 
6117 
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,const word * parms_id,byte ** parms,byte multiIEsize)8929 static void IndParse(PLCI *plci, const 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 				((CAPI_MSG *) msg)->info.facility_req.structs[1] = LI_REQ_SILENT_UPDATE & 0xff;
11308 				((CAPI_MSG *) msg)->info.facility_req.structs[2] = LI_REQ_SILENT_UPDATE >> 8;
11309 				((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11310 				w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
11311 				if (w != _QUEUE_FULL)
11312 				{
11313 					if (w != 0)
11314 					{
11315 						dbug(1, dprintf("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11316 								(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11317 								(char *)(FILE_), __LINE__,
11318 								(dword)((notify_plci->Id << 8) | UnMapController(notify_plci->adapter->Id)), w));
11319 					}
11320 					notify_plci->li_notify_update = false;
11321 				}
11322 			}
11323 		} while (others && (notify_plci != NULL));
11324 		if (others)
11325 			plci->li_notify_update = false;
11326 	}
11327 }
11328 
11329 
mixer_clear_config(PLCI * plci)11330 static void mixer_clear_config(PLCI *plci)
11331 {
11332 	DIVA_CAPI_ADAPTER *a;
11333 	word i, j;
11334 
11335 	dbug(1, dprintf("[%06lx] %s,%d: mixer_clear_config",
11336 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
11337 			(char *)(FILE_), __LINE__));
11338 
11339 	plci->li_notify_update = false;
11340 	plci->li_plci_b_write_pos = 0;
11341 	plci->li_plci_b_read_pos = 0;
11342 	plci->li_plci_b_req_pos = 0;
11343 	a = plci->adapter;
11344 	if ((plci->li_bchannel_id != 0)
11345 	    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11346 	{
11347 		i = a->li_base + (plci->li_bchannel_id - 1);
11348 		li_config_table[i].curchnl = 0;
11349 		li_config_table[i].channel = 0;
11350 		li_config_table[i].chflags = 0;
11351 		for (j = 0; j < li_total_channels; j++)
11352 		{
11353 			li_config_table[j].flag_table[i] = 0;
11354 			li_config_table[i].flag_table[j] = 0;
11355 			li_config_table[i].coef_table[j] = 0;
11356 			li_config_table[j].coef_table[i] = 0;
11357 		}
11358 		if (!a->li_pri)
11359 		{
11360 			li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11361 			if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11362 			{
11363 				i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11364 				li_config_table[i].curchnl = 0;
11365 				li_config_table[i].channel = 0;
11366 				li_config_table[i].chflags = 0;
11367 				for (j = 0; j < li_total_channels; j++)
11368 				{
11369 					li_config_table[i].flag_table[j] = 0;
11370 					li_config_table[j].flag_table[i] = 0;
11371 					li_config_table[i].coef_table[j] = 0;
11372 					li_config_table[j].coef_table[i] = 0;
11373 				}
11374 				if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11375 				{
11376 					i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11377 					li_config_table[i].curchnl = 0;
11378 					li_config_table[i].channel = 0;
11379 					li_config_table[i].chflags = 0;
11380 					for (j = 0; j < li_total_channels; j++)
11381 					{
11382 						li_config_table[i].flag_table[j] = 0;
11383 						li_config_table[j].flag_table[i] = 0;
11384 						li_config_table[i].coef_table[j] = 0;
11385 						li_config_table[j].coef_table[i] = 0;
11386 					}
11387 				}
11388 			}
11389 		}
11390 	}
11391 }
11392 
11393 
mixer_prepare_switch(dword Id,PLCI * plci)11394 static void mixer_prepare_switch(dword Id, PLCI *plci)
11395 {
11396 
11397 	dbug(1, dprintf("[%06lx] %s,%d: mixer_prepare_switch",
11398 			UnMapId(Id), (char *)(FILE_), __LINE__));
11399 
11400 	do
11401 	{
11402 		mixer_indication_coefs_set(Id, plci);
11403 	} while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11404 }
11405 
11406 
mixer_save_config(dword Id,PLCI * plci,byte Rc)11407 static word mixer_save_config(dword Id, PLCI *plci, byte Rc)
11408 {
11409 	DIVA_CAPI_ADAPTER *a;
11410 	word i, j;
11411 
11412 	dbug(1, dprintf("[%06lx] %s,%d: mixer_save_config %02x %d",
11413 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11414 
11415 	a = plci->adapter;
11416 	if ((plci->li_bchannel_id != 0)
11417 	    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11418 	{
11419 		i = a->li_base + (plci->li_bchannel_id - 1);
11420 		for (j = 0; j < li_total_channels; j++)
11421 		{
11422 			li_config_table[i].coef_table[j] &= 0xf;
11423 			li_config_table[j].coef_table[i] &= 0xf;
11424 		}
11425 		if (!a->li_pri)
11426 			li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11427 	}
11428 	return (GOOD);
11429 }
11430 
11431 
mixer_restore_config(dword Id,PLCI * plci,byte Rc)11432 static word mixer_restore_config(dword Id, PLCI *plci, byte Rc)
11433 {
11434 	DIVA_CAPI_ADAPTER *a;
11435 	word Info;
11436 
11437 	dbug(1, dprintf("[%06lx] %s,%d: mixer_restore_config %02x %d",
11438 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11439 
11440 	Info = GOOD;
11441 	a = plci->adapter;
11442 	if ((plci->B1_facilities & B1_FACILITY_MIXER)
11443 	    && (plci->li_bchannel_id != 0)
11444 	    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11445 	{
11446 		switch (plci->adjust_b_state)
11447 		{
11448 		case ADJUST_B_RESTORE_MIXER_1:
11449 			if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11450 			{
11451 				plci->internal_command = plci->adjust_b_command;
11452 				if (plci_nl_busy(plci))
11453 				{
11454 					plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11455 					break;
11456 				}
11457 				xconnect_query_addresses(plci);
11458 				plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11459 				break;
11460 			}
11461 			plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11462 			Rc = OK;
11463 		case ADJUST_B_RESTORE_MIXER_2:
11464 		case ADJUST_B_RESTORE_MIXER_3:
11465 		case ADJUST_B_RESTORE_MIXER_4:
11466 			if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11467 			{
11468 				dbug(1, dprintf("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11469 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
11470 				Info = _WRONG_STATE;
11471 				break;
11472 			}
11473 			if (Rc == OK)
11474 			{
11475 				if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11476 					plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11477 				else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11478 					plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11479 			}
11480 			else if (Rc == 0)
11481 			{
11482 				if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11483 					plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11484 				else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11485 					plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11486 			}
11487 			if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11488 			{
11489 				plci->internal_command = plci->adjust_b_command;
11490 				break;
11491 			}
11492 		case ADJUST_B_RESTORE_MIXER_5:
11493 			xconnect_write_coefs(plci, plci->adjust_b_command);
11494 			plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11495 			Rc = OK;
11496 		case ADJUST_B_RESTORE_MIXER_6:
11497 			if (!xconnect_write_coefs_process(Id, plci, Rc))
11498 			{
11499 				dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11500 						UnMapId(Id), (char *)(FILE_), __LINE__));
11501 				Info = _FACILITY_NOT_SUPPORTED;
11502 				break;
11503 			}
11504 			if (plci->internal_command)
11505 				break;
11506 			plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11507 		case ADJUST_B_RESTORE_MIXER_7:
11508 			break;
11509 		}
11510 	}
11511 	return (Info);
11512 }
11513 
11514 
mixer_command(dword Id,PLCI * plci,byte Rc)11515 static void mixer_command(dword Id, PLCI *plci, byte Rc)
11516 {
11517 	DIVA_CAPI_ADAPTER *a;
11518 	word i, internal_command;
11519 
11520 	dbug(1, dprintf("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11521 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
11522 			plci->li_cmd));
11523 
11524 	a = plci->adapter;
11525 	internal_command = plci->internal_command;
11526 	plci->internal_command = 0;
11527 	switch (plci->li_cmd)
11528 	{
11529 	case LI_REQ_CONNECT:
11530 	case LI_REQ_DISCONNECT:
11531 	case LI_REQ_SILENT_UPDATE:
11532 		switch (internal_command)
11533 		{
11534 		default:
11535 			if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11536 			{
11537 				adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
11538 									  B1_FACILITY_MIXER), MIXER_COMMAND_1);
11539 			}
11540 		case MIXER_COMMAND_1:
11541 			if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11542 			{
11543 				if (adjust_b_process(Id, plci, Rc) != GOOD)
11544 				{
11545 					dbug(1, dprintf("[%06lx] %s,%d: Load mixer failed",
11546 							UnMapId(Id), (char *)(FILE_), __LINE__));
11547 					break;
11548 				}
11549 				if (plci->internal_command)
11550 					return;
11551 			}
11552 			plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11553 			if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11554 			    || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11555 				&& (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11556 										      ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11557 			{
11558 				xconnect_write_coefs(plci, MIXER_COMMAND_2);
11559 			}
11560 			else
11561 			{
11562 				do
11563 				{
11564 					mixer_indication_coefs_set(Id, plci);
11565 				} while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11566 			}
11567 		case MIXER_COMMAND_2:
11568 			if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11569 			    || ((get_b1_facilities(plci, plci->B1_resource) & B1_FACILITY_MIXER)
11570 				&& (add_b1_facilities(plci, plci->B1_resource, (word)(plci->B1_facilities &
11571 										      ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11572 			{
11573 				if (!xconnect_write_coefs_process(Id, plci, Rc))
11574 				{
11575 					dbug(1, dprintf("[%06lx] %s,%d: Write mixer coefs failed",
11576 							UnMapId(Id), (char *)(FILE_), __LINE__));
11577 					if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11578 					{
11579 						do
11580 						{
11581 							plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11582 								LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11583 							i = (plci->li_plci_b_write_pos == 0) ?
11584 								LI_PLCI_B_QUEUE_ENTRIES - 1 : plci->li_plci_b_write_pos - 1;
11585 						} while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11586 							 && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11587 					}
11588 					break;
11589 				}
11590 				if (plci->internal_command)
11591 					return;
11592 			}
11593 			if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11594 			{
11595 				adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
11596 									  ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11597 			}
11598 		case MIXER_COMMAND_3:
11599 			if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11600 			{
11601 				if (adjust_b_process(Id, plci, Rc) != GOOD)
11602 				{
11603 					dbug(1, dprintf("[%06lx] %s,%d: Unload mixer failed",
11604 							UnMapId(Id), (char *)(FILE_), __LINE__));
11605 					break;
11606 				}
11607 				if (plci->internal_command)
11608 					return;
11609 			}
11610 			break;
11611 		}
11612 		break;
11613 	}
11614 	if ((plci->li_bchannel_id == 0)
11615 	    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11616 	{
11617 		dbug(1, dprintf("[%06x] %s,%d: Channel id wiped out %d",
11618 				UnMapId(Id), (char *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11619 	}
11620 	else
11621 	{
11622 		i = a->li_base + (plci->li_bchannel_id - 1);
11623 		li_config_table[i].curchnl = plci->li_channel_bits;
11624 		if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11625 		{
11626 			i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11627 			li_config_table[i].curchnl = plci->li_channel_bits;
11628 			if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11629 			{
11630 				i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11631 				li_config_table[i].curchnl = plci->li_channel_bits;
11632 			}
11633 		}
11634 	}
11635 }
11636 
11637 
li_update_connect(dword Id,DIVA_CAPI_ADAPTER * a,PLCI * plci,dword plci_b_id,byte connect,dword li_flags)11638 static void li_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11639 			      dword plci_b_id, byte connect, dword li_flags)
11640 {
11641 	word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11642 	PLCI *plci_b;
11643 	DIVA_CAPI_ADAPTER *a_b;
11644 
11645 	a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11646 	plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11647 	ch_a = a->li_base + (plci->li_bchannel_id - 1);
11648 	if (!a->li_pri && (plci->tel == ADV_VOICE)
11649 	    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11650 	{
11651 		ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11652 		ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11653 			a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11654 	}
11655 	else
11656 	{
11657 		ch_a_v = ch_a;
11658 		ch_a_s = ch_a;
11659 	}
11660 	ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11661 	if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11662 	    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11663 	{
11664 		ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11665 		ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11666 			a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11667 	}
11668 	else
11669 	{
11670 		ch_b_v = ch_b;
11671 		ch_b_s = ch_b;
11672 	}
11673 	if (connect)
11674 	{
11675 		li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11676 		li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11677 		li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11678 		li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11679 	}
11680 	li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11681 	li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11682 	li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11683 	li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11684 	if (ch_a_v == ch_b_v)
11685 	{
11686 		li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11687 		li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11688 	}
11689 	else
11690 	{
11691 		if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11692 		{
11693 			for (i = 0; i < li_total_channels; i++)
11694 			{
11695 				if (i != ch_a_v)
11696 					li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11697 			}
11698 		}
11699 		if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11700 		{
11701 			for (i = 0; i < li_total_channels; i++)
11702 			{
11703 				if (i != ch_a_s)
11704 					li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11705 			}
11706 		}
11707 		if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11708 		{
11709 			for (i = 0; i < li_total_channels; i++)
11710 			{
11711 				if (i != ch_a_v)
11712 					li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11713 			}
11714 		}
11715 		if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11716 		{
11717 			for (i = 0; i < li_total_channels; i++)
11718 			{
11719 				if (i != ch_a_s)
11720 					li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11721 			}
11722 		}
11723 	}
11724 	if (li_flags & LI_FLAG_CONFERENCE_A_B)
11725 	{
11726 		li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11727 		li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11728 		li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11729 		li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11730 	}
11731 	if (li_flags & LI_FLAG_CONFERENCE_B_A)
11732 	{
11733 		li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11734 		li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11735 		li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11736 		li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11737 	}
11738 	if (li_flags & LI_FLAG_MONITOR_A)
11739 	{
11740 		li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11741 		li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11742 	}
11743 	if (li_flags & LI_FLAG_MONITOR_B)
11744 	{
11745 		li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11746 		li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11747 	}
11748 	if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11749 	{
11750 		li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11751 		li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11752 	}
11753 	if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11754 	{
11755 		li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11756 		li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11757 	}
11758 	if (li_flags & LI_FLAG_MIX_A)
11759 	{
11760 		li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11761 		li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11762 	}
11763 	if (li_flags & LI_FLAG_MIX_B)
11764 	{
11765 		li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11766 		li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11767 	}
11768 	if (ch_a_v != ch_a_s)
11769 	{
11770 		li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11771 		li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11772 	}
11773 	if (ch_b_v != ch_b_s)
11774 	{
11775 		li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11776 		li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11777 	}
11778 }
11779 
11780 
li2_update_connect(dword Id,DIVA_CAPI_ADAPTER * a,PLCI * plci,dword plci_b_id,byte connect,dword li_flags)11781 static void li2_update_connect(dword Id, DIVA_CAPI_ADAPTER *a, PLCI *plci,
11782 			       dword plci_b_id, byte connect, dword li_flags)
11783 {
11784 	word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11785 	PLCI *plci_b;
11786 	DIVA_CAPI_ADAPTER *a_b;
11787 
11788 	a_b = &(adapter[MapController((byte)(plci_b_id & 0x7f)) - 1]);
11789 	plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11790 	ch_a = a->li_base + (plci->li_bchannel_id - 1);
11791 	if (!a->li_pri && (plci->tel == ADV_VOICE)
11792 	    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11793 	{
11794 		ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11795 		ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11796 			a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11797 	}
11798 	else
11799 	{
11800 		ch_a_v = ch_a;
11801 		ch_a_s = ch_a;
11802 	}
11803 	ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11804 	if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11805 	    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11806 	{
11807 		ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11808 		ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11809 			a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11810 	}
11811 	else
11812 	{
11813 		ch_b_v = ch_b;
11814 		ch_b_s = ch_b;
11815 	}
11816 	if (connect)
11817 	{
11818 		li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11819 		li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11820 		li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11821 		li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11822 		li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11823 		li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11824 	}
11825 	li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11826 	li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11827 	li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11828 	li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11829 	li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11830 	li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11831 	li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11832 	li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11833 	if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11834 	{
11835 		li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11836 		li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11837 		li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11838 		li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11839 	}
11840 	if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11841 	{
11842 		li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11843 		li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11844 		li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11845 		li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11846 	}
11847 	if (li_flags & LI2_FLAG_MONITOR_B)
11848 	{
11849 		li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11850 		li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11851 	}
11852 	if (li_flags & LI2_FLAG_MIX_B)
11853 	{
11854 		li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11855 		li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11856 	}
11857 	if (li_flags & LI2_FLAG_MONITOR_X)
11858 		li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11859 	if (li_flags & LI2_FLAG_MIX_X)
11860 		li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11861 	if (li_flags & LI2_FLAG_LOOP_B)
11862 	{
11863 		li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11864 		li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11865 		li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11866 		li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11867 	}
11868 	if (li_flags & LI2_FLAG_LOOP_PC)
11869 		li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11870 	if (li_flags & LI2_FLAG_LOOP_X)
11871 		li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11872 	if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11873 		li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11874 	if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11875 		li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11876 	if (ch_a_v != ch_a_s)
11877 	{
11878 		li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11879 		li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11880 	}
11881 	if (ch_b_v != ch_b_s)
11882 	{
11883 		li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11884 		li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11885 	}
11886 }
11887 
11888 
li_check_main_plci(dword Id,PLCI * plci)11889 static word li_check_main_plci(dword Id, PLCI *plci)
11890 {
11891 	if (plci == NULL)
11892 	{
11893 		dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
11894 				UnMapId(Id), (char *)(FILE_), __LINE__));
11895 		return (_WRONG_IDENTIFIER);
11896 	}
11897 	if (!plci->State
11898 	    || !plci->NL.Id || plci->nl_remove_id
11899 	    || (plci->li_bchannel_id == 0))
11900 	{
11901 		dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
11902 				UnMapId(Id), (char *)(FILE_), __LINE__));
11903 		return (_WRONG_STATE);
11904 	}
11905 	li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11906 	return (GOOD);
11907 }
11908 
11909 
li_check_plci_b(dword Id,PLCI * plci,dword plci_b_id,word plci_b_write_pos,byte * p_result)11910 static PLCI *li_check_plci_b(dword Id, PLCI *plci,
11911 			     dword plci_b_id, word plci_b_write_pos, byte *p_result)
11912 {
11913 	byte ctlr_b;
11914 	PLCI *plci_b;
11915 
11916 	if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11917 	     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11918 	{
11919 		dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11920 				UnMapId(Id), (char *)(FILE_), __LINE__));
11921 		PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11922 		return (NULL);
11923 	}
11924 	ctlr_b = 0;
11925 	if ((plci_b_id & 0x7f) != 0)
11926 	{
11927 		ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11928 		if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11929 			ctlr_b = 0;
11930 	}
11931 	if ((ctlr_b == 0)
11932 	    || (((plci_b_id >> 8) & 0xff) == 0)
11933 	    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11934 	{
11935 		dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11936 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11937 		PUT_WORD(p_result, _WRONG_IDENTIFIER);
11938 		return (NULL);
11939 	}
11940 	plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11941 	if (!plci_b->State
11942 	    || !plci_b->NL.Id || plci_b->nl_remove_id
11943 	    || (plci_b->li_bchannel_id == 0))
11944 	{
11945 		dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
11946 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11947 		PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11948 		return (NULL);
11949 	}
11950 	li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11951 	if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11952 	    ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
11953 	    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11954 		|| !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11955 	{
11956 		dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
11957 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
11958 		PUT_WORD(p_result, _WRONG_IDENTIFIER);
11959 		return (NULL);
11960 	}
11961 	if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
11962 							  (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11963 	{
11964 		dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11965 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
11966 		PUT_WORD(p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11967 		return (NULL);
11968 	}
11969 	return (plci_b);
11970 }
11971 
11972 
li2_check_plci_b(dword Id,PLCI * plci,dword plci_b_id,word plci_b_write_pos,byte * p_result)11973 static PLCI *li2_check_plci_b(dword Id, PLCI *plci,
11974 			      dword plci_b_id, word plci_b_write_pos, byte *p_result)
11975 {
11976 	byte ctlr_b;
11977 	PLCI *plci_b;
11978 
11979 	if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11980 	     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11981 	{
11982 		dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
11983 				UnMapId(Id), (char *)(FILE_), __LINE__));
11984 		PUT_WORD(p_result, _WRONG_STATE);
11985 		return (NULL);
11986 	}
11987 	ctlr_b = 0;
11988 	if ((plci_b_id & 0x7f) != 0)
11989 	{
11990 		ctlr_b = MapController((byte)(plci_b_id & 0x7f));
11991 		if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11992 			ctlr_b = 0;
11993 	}
11994 	if ((ctlr_b == 0)
11995 	    || (((plci_b_id >> 8) & 0xff) == 0)
11996 	    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11997 	{
11998 		dbug(1, dprintf("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11999 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12000 		PUT_WORD(p_result, _WRONG_IDENTIFIER);
12001 		return (NULL);
12002 	}
12003 	plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
12004 	if (!plci_b->State
12005 	    || !plci_b->NL.Id || plci_b->nl_remove_id
12006 	    || (plci_b->li_bchannel_id == 0)
12007 	    || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12008 	{
12009 		dbug(1, dprintf("[%06lx] %s,%d: LI peer in wrong state %08lx",
12010 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12011 		PUT_WORD(p_result, _WRONG_STATE);
12012 		return (NULL);
12013 	}
12014 	if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12015 	    ((byte)(UnMapController(plci->adapter->Id) & ~EXT_CONTROLLER))
12016 	    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12017 		|| !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12018 	{
12019 		dbug(1, dprintf("[%06lx] %s,%d: LI not on same ctrl %08lx",
12020 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b_id));
12021 		PUT_WORD(p_result, _WRONG_IDENTIFIER);
12022 		return (NULL);
12023 	}
12024 	if (!(get_b1_facilities(plci_b, add_b1_facilities(plci_b, plci_b->B1_resource,
12025 							  (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12026 	{
12027 		dbug(1, dprintf("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12028 				UnMapId(Id), (char *)(FILE_), __LINE__, plci_b->B1_resource));
12029 		PUT_WORD(p_result, _WRONG_STATE);
12030 		return (NULL);
12031 	}
12032 	return (plci_b);
12033 }
12034 
12035 
mixer_request(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)12036 static byte mixer_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
12037 {
12038 	word Info;
12039 	word i;
12040 	dword d, li_flags, plci_b_id;
12041 	PLCI *plci_b;
12042 	API_PARSE li_parms[3];
12043 	API_PARSE li_req_parms[3];
12044 	API_PARSE li_participant_struct[2];
12045 	API_PARSE li_participant_parms[3];
12046 	word participant_parms_pos;
12047 	byte result_buffer[32];
12048 	byte *result;
12049 	word result_pos;
12050 	word plci_b_write_pos;
12051 
12052 	dbug(1, dprintf("[%06lx] %s,%d: mixer_request",
12053 			UnMapId(Id), (char *)(FILE_), __LINE__));
12054 
12055 	Info = GOOD;
12056 	result = result_buffer;
12057 	result_buffer[0] = 0;
12058 	if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12059 	{
12060 		dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12061 				UnMapId(Id), (char *)(FILE_), __LINE__));
12062 		Info = _FACILITY_NOT_SUPPORTED;
12063 	}
12064 	else if (api_parse(&msg[1].info[1], msg[1].length, "ws", li_parms))
12065 	{
12066 		dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12067 				UnMapId(Id), (char *)(FILE_), __LINE__));
12068 		Info = _WRONG_MESSAGE_FORMAT;
12069 	}
12070 	else
12071 	{
12072 		result_buffer[0] = 3;
12073 		PUT_WORD(&result_buffer[1], GET_WORD(li_parms[0].info));
12074 		result_buffer[3] = 0;
12075 		switch (GET_WORD(li_parms[0].info))
12076 		{
12077 		case LI_GET_SUPPORTED_SERVICES:
12078 			if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12079 			{
12080 				result_buffer[0] = 17;
12081 				result_buffer[3] = 14;
12082 				PUT_WORD(&result_buffer[4], GOOD);
12083 				d = 0;
12084 				if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12085 					d |= LI_CONFERENCING_SUPPORTED;
12086 				if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12087 					d |= LI_MONITORING_SUPPORTED;
12088 				if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12089 					d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12090 				if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12091 					d |= LI_CROSS_CONTROLLER_SUPPORTED;
12092 				PUT_DWORD(&result_buffer[6], d);
12093 				if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12094 				{
12095 					d = 0;
12096 					for (i = 0; i < li_total_channels; i++)
12097 					{
12098 						if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12099 						    && (li_config_table[i].adapter->li_pri
12100 							|| (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12101 						{
12102 							d++;
12103 						}
12104 					}
12105 				}
12106 				else
12107 				{
12108 					d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12109 				}
12110 				PUT_DWORD(&result_buffer[10], d / 2);
12111 				PUT_DWORD(&result_buffer[14], d);
12112 			}
12113 			else
12114 			{
12115 				result_buffer[0] = 25;
12116 				result_buffer[3] = 22;
12117 				PUT_WORD(&result_buffer[4], GOOD);
12118 				d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12119 				if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12120 					d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12121 				if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12122 					d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12123 				if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12124 					d |= LI2_PC_LOOPING_SUPPORTED;
12125 				if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12126 					d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12127 				PUT_DWORD(&result_buffer[6], d);
12128 				d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12129 				PUT_DWORD(&result_buffer[10], d / 2);
12130 				PUT_DWORD(&result_buffer[14], d - 1);
12131 				if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12132 				{
12133 					d = 0;
12134 					for (i = 0; i < li_total_channels; i++)
12135 					{
12136 						if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12137 						    && (li_config_table[i].adapter->li_pri
12138 							|| (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12139 						{
12140 							d++;
12141 						}
12142 					}
12143 				}
12144 				PUT_DWORD(&result_buffer[18], d / 2);
12145 				PUT_DWORD(&result_buffer[22], d - 1);
12146 			}
12147 			break;
12148 
12149 		case LI_REQ_CONNECT:
12150 			if (li_parms[1].length == 8)
12151 			{
12152 				appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12153 				if (api_parse(&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12154 				{
12155 					dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12156 							UnMapId(Id), (char *)(FILE_), __LINE__));
12157 					Info = _WRONG_MESSAGE_FORMAT;
12158 					break;
12159 				}
12160 				plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12161 				li_flags = GET_DWORD(li_req_parms[1].info);
12162 				Info = li_check_main_plci(Id, plci);
12163 				result_buffer[0] = 9;
12164 				result_buffer[3] = 6;
12165 				PUT_DWORD(&result_buffer[4], plci_b_id);
12166 				PUT_WORD(&result_buffer[8], GOOD);
12167 				if (Info != GOOD)
12168 					break;
12169 				result = plci->saved_msg.info;
12170 				for (i = 0; i <= result_buffer[0]; i++)
12171 					result[i] = result_buffer[i];
12172 				plci_b_write_pos = plci->li_plci_b_write_pos;
12173 				plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12174 				if (plci_b == NULL)
12175 					break;
12176 				li_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12177 				plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12178 				plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12179 				plci->li_plci_b_write_pos = plci_b_write_pos;
12180 			}
12181 			else
12182 			{
12183 				appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12184 				if (api_parse(&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12185 				{
12186 					dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12187 							UnMapId(Id), (char *)(FILE_), __LINE__));
12188 					Info = _WRONG_MESSAGE_FORMAT;
12189 					break;
12190 				}
12191 				li_flags = GET_DWORD(li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12192 				Info = li_check_main_plci(Id, plci);
12193 				result_buffer[0] = 7;
12194 				result_buffer[3] = 4;
12195 				PUT_WORD(&result_buffer[4], Info);
12196 				result_buffer[6] = 0;
12197 				if (Info != GOOD)
12198 					break;
12199 				result = plci->saved_msg.info;
12200 				for (i = 0; i <= result_buffer[0]; i++)
12201 					result[i] = result_buffer[i];
12202 				plci_b_write_pos = plci->li_plci_b_write_pos;
12203 				participant_parms_pos = 0;
12204 				result_pos = 7;
12205 				li2_update_connect(Id, a, plci, UnMapId(Id), true, li_flags);
12206 				while (participant_parms_pos < li_req_parms[1].length)
12207 				{
12208 					result[result_pos] = 6;
12209 					result_pos += 7;
12210 					PUT_DWORD(&result[result_pos - 6], 0);
12211 					PUT_WORD(&result[result_pos - 2], GOOD);
12212 					if (api_parse(&li_req_parms[1].info[1 + participant_parms_pos],
12213 						      (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12214 					{
12215 						dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12216 								UnMapId(Id), (char *)(FILE_), __LINE__));
12217 						PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12218 						break;
12219 					}
12220 					if (api_parse(&li_participant_struct[0].info[1],
12221 						      li_participant_struct[0].length, "dd", li_participant_parms))
12222 					{
12223 						dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12224 								UnMapId(Id), (char *)(FILE_), __LINE__));
12225 						PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12226 						break;
12227 					}
12228 					plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12229 					li_flags = GET_DWORD(li_participant_parms[1].info);
12230 					PUT_DWORD(&result[result_pos - 6], plci_b_id);
12231 					if (sizeof(result) - result_pos < 7)
12232 					{
12233 						dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12234 								UnMapId(Id), (char *)(FILE_), __LINE__));
12235 						PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12236 						break;
12237 					}
12238 					plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12239 					if (plci_b != NULL)
12240 					{
12241 						li2_update_connect(Id, a, plci, plci_b_id, true, li_flags);
12242 						plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12243 							((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12244 								      LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12245 						plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12246 					}
12247 					participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12248 								       (&li_req_parms[1].info[1]));
12249 				}
12250 				result[0] = (byte)(result_pos - 1);
12251 				result[3] = (byte)(result_pos - 4);
12252 				result[6] = (byte)(result_pos - 7);
12253 				i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12254 				if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12255 				    || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12256 				{
12257 					plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12258 					plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12259 				}
12260 				else
12261 					plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12262 				plci->li_plci_b_write_pos = plci_b_write_pos;
12263 			}
12264 			mixer_calculate_coefs(a);
12265 			plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12266 			mixer_notify_update(plci, true);
12267 			sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12268 			      "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12269 			plci->command = 0;
12270 			plci->li_cmd = GET_WORD(li_parms[0].info);
12271 			start_internal_command(Id, plci, mixer_command);
12272 			return (false);
12273 
12274 		case LI_REQ_DISCONNECT:
12275 			if (li_parms[1].length == 4)
12276 			{
12277 				appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12278 				if (api_parse(&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12279 				{
12280 					dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12281 							UnMapId(Id), (char *)(FILE_), __LINE__));
12282 					Info = _WRONG_MESSAGE_FORMAT;
12283 					break;
12284 				}
12285 				plci_b_id = GET_DWORD(li_req_parms[0].info) & 0xffff;
12286 				Info = li_check_main_plci(Id, plci);
12287 				result_buffer[0] = 9;
12288 				result_buffer[3] = 6;
12289 				PUT_DWORD(&result_buffer[4], GET_DWORD(li_req_parms[0].info));
12290 				PUT_WORD(&result_buffer[8], GOOD);
12291 				if (Info != GOOD)
12292 					break;
12293 				result = plci->saved_msg.info;
12294 				for (i = 0; i <= result_buffer[0]; i++)
12295 					result[i] = result_buffer[i];
12296 				plci_b_write_pos = plci->li_plci_b_write_pos;
12297 				plci_b = li_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12298 				if (plci_b == NULL)
12299 					break;
12300 				li_update_connect(Id, a, plci, plci_b_id, false, 0);
12301 				plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12302 				plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12303 				plci->li_plci_b_write_pos = plci_b_write_pos;
12304 			}
12305 			else
12306 			{
12307 				appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12308 				if (api_parse(&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12309 				{
12310 					dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12311 							UnMapId(Id), (char *)(FILE_), __LINE__));
12312 					Info = _WRONG_MESSAGE_FORMAT;
12313 					break;
12314 				}
12315 				Info = li_check_main_plci(Id, plci);
12316 				result_buffer[0] = 7;
12317 				result_buffer[3] = 4;
12318 				PUT_WORD(&result_buffer[4], Info);
12319 				result_buffer[6] = 0;
12320 				if (Info != GOOD)
12321 					break;
12322 				result = plci->saved_msg.info;
12323 				for (i = 0; i <= result_buffer[0]; i++)
12324 					result[i] = result_buffer[i];
12325 				plci_b_write_pos = plci->li_plci_b_write_pos;
12326 				participant_parms_pos = 0;
12327 				result_pos = 7;
12328 				while (participant_parms_pos < li_req_parms[0].length)
12329 				{
12330 					result[result_pos] = 6;
12331 					result_pos += 7;
12332 					PUT_DWORD(&result[result_pos - 6], 0);
12333 					PUT_WORD(&result[result_pos - 2], GOOD);
12334 					if (api_parse(&li_req_parms[0].info[1 + participant_parms_pos],
12335 						      (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12336 					{
12337 						dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12338 								UnMapId(Id), (char *)(FILE_), __LINE__));
12339 						PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12340 						break;
12341 					}
12342 					if (api_parse(&li_participant_struct[0].info[1],
12343 						      li_participant_struct[0].length, "d", li_participant_parms))
12344 					{
12345 						dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12346 								UnMapId(Id), (char *)(FILE_), __LINE__));
12347 						PUT_WORD(&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12348 						break;
12349 					}
12350 					plci_b_id = GET_DWORD(li_participant_parms[0].info) & 0xffff;
12351 					PUT_DWORD(&result[result_pos - 6], plci_b_id);
12352 					if (sizeof(result) - result_pos < 7)
12353 					{
12354 						dbug(1, dprintf("[%06lx] %s,%d: LI result overrun",
12355 								UnMapId(Id), (char *)(FILE_), __LINE__));
12356 						PUT_WORD(&result[result_pos - 2], _WRONG_STATE);
12357 						break;
12358 					}
12359 					plci_b = li2_check_plci_b(Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12360 					if (plci_b != NULL)
12361 					{
12362 						li2_update_connect(Id, a, plci, plci_b_id, false, 0);
12363 						plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12364 						plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12365 					}
12366 					participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12367 								       (&li_req_parms[0].info[1]));
12368 				}
12369 				result[0] = (byte)(result_pos - 1);
12370 				result[3] = (byte)(result_pos - 4);
12371 				result[6] = (byte)(result_pos - 7);
12372 				i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12373 				if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12374 				    || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12375 				{
12376 					plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12377 					plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12378 				}
12379 				else
12380 					plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12381 				plci->li_plci_b_write_pos = plci_b_write_pos;
12382 			}
12383 			mixer_calculate_coefs(a);
12384 			plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12385 			mixer_notify_update(plci, true);
12386 			sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12387 			      "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12388 			plci->command = 0;
12389 			plci->li_cmd = GET_WORD(li_parms[0].info);
12390 			start_internal_command(Id, plci, mixer_command);
12391 			return (false);
12392 
12393 		case LI_REQ_SILENT_UPDATE:
12394 			if (!plci || !plci->State
12395 			    || !plci->NL.Id || plci->nl_remove_id
12396 			    || (plci->li_bchannel_id == 0)
12397 			    || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12398 			{
12399 				dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12400 						UnMapId(Id), (char *)(FILE_), __LINE__));
12401 				return (false);
12402 			}
12403 			plci_b_write_pos = plci->li_plci_b_write_pos;
12404 			if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12405 			     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12406 			{
12407 				dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12408 						UnMapId(Id), (char *)(FILE_), __LINE__));
12409 				return (false);
12410 			}
12411 			i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES - 1 : plci_b_write_pos - 1;
12412 			if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12413 			    || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12414 			{
12415 				plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12416 				plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12417 			}
12418 			else
12419 				plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12420 			plci->li_plci_b_write_pos = plci_b_write_pos;
12421 			plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12422 			plci->command = 0;
12423 			plci->li_cmd = GET_WORD(li_parms[0].info);
12424 			start_internal_command(Id, plci, mixer_command);
12425 			return (false);
12426 
12427 		default:
12428 			dbug(1, dprintf("[%06lx] %s,%d: LI unknown request %04x",
12429 					UnMapId(Id), (char *)(FILE_), __LINE__, GET_WORD(li_parms[0].info)));
12430 			Info = _FACILITY_NOT_SUPPORTED;
12431 		}
12432 	}
12433 	sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12434 	      "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12435 	return (false);
12436 }
12437 
12438 
mixer_indication_coefs_set(dword Id,PLCI * plci)12439 static void mixer_indication_coefs_set(dword Id, PLCI *plci)
12440 {
12441 	dword d;
12442 	byte result[12];
12443 
12444 	dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_coefs_set",
12445 			UnMapId(Id), (char *)(FILE_), __LINE__));
12446 
12447 	if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12448 	{
12449 		do
12450 		{
12451 			d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12452 			if (!(d & LI_PLCI_B_SKIP_FLAG))
12453 			{
12454 				if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12455 				{
12456 					if (d & LI_PLCI_B_DISC_FLAG)
12457 					{
12458 						result[0] = 5;
12459 						PUT_WORD(&result[1], LI_IND_DISCONNECT);
12460 						result[3] = 2;
12461 						PUT_WORD(&result[4], _LI_USER_INITIATED);
12462 					}
12463 					else
12464 					{
12465 						result[0] = 7;
12466 						PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12467 						result[3] = 4;
12468 						PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12469 					}
12470 				}
12471 				else
12472 				{
12473 					if (d & LI_PLCI_B_DISC_FLAG)
12474 					{
12475 						result[0] = 9;
12476 						PUT_WORD(&result[1], LI_IND_DISCONNECT);
12477 						result[3] = 6;
12478 						PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12479 						PUT_WORD(&result[8], _LI_USER_INITIATED);
12480 					}
12481 					else
12482 					{
12483 						result[0] = 7;
12484 						PUT_WORD(&result[1], LI_IND_CONNECT_ACTIVE);
12485 						result[3] = 4;
12486 						PUT_DWORD(&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12487 					}
12488 				}
12489 				sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12490 				      "ws", SELECTOR_LINE_INTERCONNECT, result);
12491 			}
12492 			plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ?
12493 				0 : plci->li_plci_b_read_pos + 1;
12494 		} while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12495 	}
12496 }
12497 
12498 
mixer_indication_xconnect_from(dword Id,PLCI * plci,byte * msg,word length)12499 static void mixer_indication_xconnect_from(dword Id, PLCI *plci, byte *msg, word length)
12500 {
12501 	word i, j, ch;
12502 	struct xconnect_transfer_address_s s,   *p;
12503 	DIVA_CAPI_ADAPTER *a;
12504 
12505 	dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12506 			UnMapId(Id), (char *)(FILE_), __LINE__, (int)length));
12507 
12508 	a = plci->adapter;
12509 	i = 1;
12510 	for (i = 1; i < length; i += 16)
12511 	{
12512 		s.card_address.low = msg[i] | (msg[i + 1] << 8) | (((dword)(msg[i + 2])) << 16) | (((dword)(msg[i + 3])) << 24);
12513 		s.card_address.high = msg[i + 4] | (msg[i + 5] << 8) | (((dword)(msg[i + 6])) << 16) | (((dword)(msg[i + 7])) << 24);
12514 		s.offset = msg[i + 8] | (msg[i + 9] << 8) | (((dword)(msg[i + 10])) << 16) | (((dword)(msg[i + 11])) << 24);
12515 		ch = msg[i + 12] | (msg[i + 13] << 8);
12516 		j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12517 		if (!a->li_pri && (plci->li_bchannel_id == 2))
12518 			j = 1 - j;
12519 		j += a->li_base;
12520 		if (ch & XCONNECT_CHANNEL_PORT_PC)
12521 			p = &(li_config_table[j].send_pc);
12522 		else
12523 			p = &(li_config_table[j].send_b);
12524 		p->card_address.low = s.card_address.low;
12525 		p->card_address.high = s.card_address.high;
12526 		p->offset = s.offset;
12527 		li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12528 	}
12529 	if (plci->internal_command_queue[0]
12530 	    && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12531 		|| (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12532 		|| (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12533 	{
12534 		(*(plci->internal_command_queue[0]))(Id, plci, 0);
12535 		if (!plci->internal_command)
12536 			next_internal_command(Id, plci);
12537 	}
12538 	mixer_notify_update(plci, true);
12539 }
12540 
12541 
mixer_indication_xconnect_to(dword Id,PLCI * plci,byte * msg,word length)12542 static void mixer_indication_xconnect_to(dword Id, PLCI *plci, byte *msg, word length)
12543 {
12544 
12545 	dbug(1, dprintf("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12546 			UnMapId(Id), (char *)(FILE_), __LINE__, (int) length));
12547 
12548 }
12549 
12550 
mixer_notify_source_removed(PLCI * plci,dword plci_b_id)12551 static byte mixer_notify_source_removed(PLCI *plci, dword plci_b_id)
12552 {
12553 	word plci_b_write_pos;
12554 
12555 	plci_b_write_pos = plci->li_plci_b_write_pos;
12556 	if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12557 	     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12558 	{
12559 		dbug(1, dprintf("[%06lx] %s,%d: LI request overrun",
12560 				(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12561 				(char *)(FILE_), __LINE__));
12562 		return (false);
12563 	}
12564 	plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12565 	plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES - 1) ? 0 : plci_b_write_pos + 1;
12566 	plci->li_plci_b_write_pos = plci_b_write_pos;
12567 	return (true);
12568 }
12569 
12570 
mixer_remove(PLCI * plci)12571 static void mixer_remove(PLCI *plci)
12572 {
12573 	DIVA_CAPI_ADAPTER *a;
12574 	PLCI *notify_plci;
12575 	dword plci_b_id;
12576 	word i, j;
12577 
12578 	dbug(1, dprintf("[%06lx] %s,%d: mixer_remove",
12579 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12580 			(char *)(FILE_), __LINE__));
12581 
12582 	a = plci->adapter;
12583 	plci_b_id = (plci->Id << 8) | UnMapController(plci->adapter->Id);
12584 	if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12585 	{
12586 		if ((plci->li_bchannel_id != 0)
12587 		    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12588 		{
12589 			i = a->li_base + (plci->li_bchannel_id - 1);
12590 			if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12591 			{
12592 				for (j = 0; j < li_total_channels; j++)
12593 				{
12594 					if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12595 					    || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12596 					{
12597 						notify_plci = li_config_table[j].plci;
12598 						if ((notify_plci != NULL)
12599 						    && (notify_plci != plci)
12600 						    && (notify_plci->appl != NULL)
12601 						    && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12602 						    && (notify_plci->State)
12603 						    && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12604 						{
12605 							mixer_notify_source_removed(notify_plci, plci_b_id);
12606 						}
12607 					}
12608 				}
12609 				mixer_clear_config(plci);
12610 				mixer_calculate_coefs(a);
12611 				mixer_notify_update(plci, true);
12612 			}
12613 			li_config_table[i].plci = NULL;
12614 			plci->li_bchannel_id = 0;
12615 		}
12616 	}
12617 }
12618 
12619 
12620 /*------------------------------------------------------------------*/
12621 /* Echo canceller facilities                                        */
12622 /*------------------------------------------------------------------*/
12623 
12624 
ec_write_parameters(PLCI * plci)12625 static void ec_write_parameters(PLCI *plci)
12626 {
12627 	word w;
12628 	byte parameter_buffer[6];
12629 
12630 	dbug(1, dprintf("[%06lx] %s,%d: ec_write_parameters",
12631 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12632 			(char *)(FILE_), __LINE__));
12633 
12634 	parameter_buffer[0] = 5;
12635 	parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12636 	PUT_WORD(&parameter_buffer[2], plci->ec_idi_options);
12637 	plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12638 	w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12639 	PUT_WORD(&parameter_buffer[4], w);
12640 	add_p(plci, FTY, parameter_buffer);
12641 	sig_req(plci, TEL_CTRL, 0);
12642 	send_req(plci);
12643 }
12644 
12645 
ec_clear_config(PLCI * plci)12646 static void ec_clear_config(PLCI *plci)
12647 {
12648 
12649 	dbug(1, dprintf("[%06lx] %s,%d: ec_clear_config",
12650 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
12651 			(char *)(FILE_), __LINE__));
12652 
12653 	plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12654 		LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12655 	plci->ec_tail_length = 0;
12656 }
12657 
12658 
ec_prepare_switch(dword Id,PLCI * plci)12659 static void ec_prepare_switch(dword Id, PLCI *plci)
12660 {
12661 
12662 	dbug(1, dprintf("[%06lx] %s,%d: ec_prepare_switch",
12663 			UnMapId(Id), (char *)(FILE_), __LINE__));
12664 
12665 }
12666 
12667 
ec_save_config(dword Id,PLCI * plci,byte Rc)12668 static word ec_save_config(dword Id, PLCI *plci, byte Rc)
12669 {
12670 
12671 	dbug(1, dprintf("[%06lx] %s,%d: ec_save_config %02x %d",
12672 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12673 
12674 	return (GOOD);
12675 }
12676 
12677 
ec_restore_config(dword Id,PLCI * plci,byte Rc)12678 static word ec_restore_config(dword Id, PLCI *plci, byte Rc)
12679 {
12680 	word Info;
12681 
12682 	dbug(1, dprintf("[%06lx] %s,%d: ec_restore_config %02x %d",
12683 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12684 
12685 	Info = GOOD;
12686 	if (plci->B1_facilities & B1_FACILITY_EC)
12687 	{
12688 		switch (plci->adjust_b_state)
12689 		{
12690 		case ADJUST_B_RESTORE_EC_1:
12691 			plci->internal_command = plci->adjust_b_command;
12692 			if (plci->sig_req)
12693 			{
12694 				plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12695 				break;
12696 			}
12697 			ec_write_parameters(plci);
12698 			plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12699 			break;
12700 		case ADJUST_B_RESTORE_EC_2:
12701 			if ((Rc != OK) && (Rc != OK_FC))
12702 			{
12703 				dbug(1, dprintf("[%06lx] %s,%d: Restore EC failed %02x",
12704 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12705 				Info = _WRONG_STATE;
12706 				break;
12707 			}
12708 			break;
12709 		}
12710 	}
12711 	return (Info);
12712 }
12713 
12714 
ec_command(dword Id,PLCI * plci,byte Rc)12715 static void ec_command(dword Id, PLCI *plci, byte Rc)
12716 {
12717 	word internal_command, Info;
12718 	byte result[8];
12719 
12720 	dbug(1, dprintf("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12721 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
12722 			plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12723 
12724 	Info = GOOD;
12725 	if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12726 	{
12727 		result[0] = 2;
12728 		PUT_WORD(&result[1], EC_SUCCESS);
12729 	}
12730 	else
12731 	{
12732 		result[0] = 5;
12733 		PUT_WORD(&result[1], plci->ec_cmd);
12734 		result[3] = 2;
12735 		PUT_WORD(&result[4], GOOD);
12736 	}
12737 	internal_command = plci->internal_command;
12738 	plci->internal_command = 0;
12739 	switch (plci->ec_cmd)
12740 	{
12741 	case EC_ENABLE_OPERATION:
12742 	case EC_FREEZE_COEFFICIENTS:
12743 	case EC_RESUME_COEFFICIENT_UPDATE:
12744 	case EC_RESET_COEFFICIENTS:
12745 		switch (internal_command)
12746 		{
12747 		default:
12748 			adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities |
12749 								  B1_FACILITY_EC), EC_COMMAND_1);
12750 		case EC_COMMAND_1:
12751 			if (adjust_b_process(Id, plci, Rc) != GOOD)
12752 			{
12753 				dbug(1, dprintf("[%06lx] %s,%d: Load EC failed",
12754 						UnMapId(Id), (char *)(FILE_), __LINE__));
12755 				Info = _FACILITY_NOT_SUPPORTED;
12756 				break;
12757 			}
12758 			if (plci->internal_command)
12759 				return;
12760 		case EC_COMMAND_2:
12761 			if (plci->sig_req)
12762 			{
12763 				plci->internal_command = EC_COMMAND_2;
12764 				return;
12765 			}
12766 			plci->internal_command = EC_COMMAND_3;
12767 			ec_write_parameters(plci);
12768 			return;
12769 		case EC_COMMAND_3:
12770 			if ((Rc != OK) && (Rc != OK_FC))
12771 			{
12772 				dbug(1, dprintf("[%06lx] %s,%d: Enable EC failed %02x",
12773 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12774 				Info = _FACILITY_NOT_SUPPORTED;
12775 				break;
12776 			}
12777 			break;
12778 		}
12779 		break;
12780 
12781 	case EC_DISABLE_OPERATION:
12782 		switch (internal_command)
12783 		{
12784 		default:
12785 		case EC_COMMAND_1:
12786 			if (plci->B1_facilities & B1_FACILITY_EC)
12787 			{
12788 				if (plci->sig_req)
12789 				{
12790 					plci->internal_command = EC_COMMAND_1;
12791 					return;
12792 				}
12793 				plci->internal_command = EC_COMMAND_2;
12794 				ec_write_parameters(plci);
12795 				return;
12796 			}
12797 			Rc = OK;
12798 		case EC_COMMAND_2:
12799 			if ((Rc != OK) && (Rc != OK_FC))
12800 			{
12801 				dbug(1, dprintf("[%06lx] %s,%d: Disable EC failed %02x",
12802 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
12803 				Info = _FACILITY_NOT_SUPPORTED;
12804 				break;
12805 			}
12806 			adjust_b1_resource(Id, plci, NULL, (word)(plci->B1_facilities &
12807 								  ~B1_FACILITY_EC), EC_COMMAND_3);
12808 		case EC_COMMAND_3:
12809 			if (adjust_b_process(Id, plci, Rc) != GOOD)
12810 			{
12811 				dbug(1, dprintf("[%06lx] %s,%d: Unload EC failed",
12812 						UnMapId(Id), (char *)(FILE_), __LINE__));
12813 				Info = _FACILITY_NOT_SUPPORTED;
12814 				break;
12815 			}
12816 			if (plci->internal_command)
12817 				return;
12818 			break;
12819 		}
12820 		break;
12821 	}
12822 	sendf(plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12823 	      "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12824 	      PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12825 }
12826 
12827 
ec_request(dword Id,word Number,DIVA_CAPI_ADAPTER * a,PLCI * plci,APPL * appl,API_PARSE * msg)12828 static byte ec_request(dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL   *appl, API_PARSE *msg)
12829 {
12830 	word Info;
12831 	word opt;
12832 	API_PARSE ec_parms[3];
12833 	byte result[16];
12834 
12835 	dbug(1, dprintf("[%06lx] %s,%d: ec_request",
12836 			UnMapId(Id), (char *)(FILE_), __LINE__));
12837 
12838 	Info = GOOD;
12839 	result[0] = 0;
12840 	if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12841 	{
12842 		dbug(1, dprintf("[%06lx] %s,%d: Facility not supported",
12843 				UnMapId(Id), (char *)(FILE_), __LINE__));
12844 		Info = _FACILITY_NOT_SUPPORTED;
12845 	}
12846 	else
12847 	{
12848 		if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12849 		{
12850 			if (api_parse(&msg[1].info[1], msg[1].length, "w", ec_parms))
12851 			{
12852 				dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12853 						UnMapId(Id), (char *)(FILE_), __LINE__));
12854 				Info = _WRONG_MESSAGE_FORMAT;
12855 			}
12856 			else
12857 			{
12858 				if (plci == NULL)
12859 				{
12860 					dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12861 							UnMapId(Id), (char *)(FILE_), __LINE__));
12862 					Info = _WRONG_IDENTIFIER;
12863 				}
12864 				else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12865 				{
12866 					dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12867 							UnMapId(Id), (char *)(FILE_), __LINE__));
12868 					Info = _WRONG_STATE;
12869 				}
12870 				else
12871 				{
12872 					plci->command = 0;
12873 					plci->ec_cmd = GET_WORD(ec_parms[0].info);
12874 					plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12875 					result[0] = 2;
12876 					PUT_WORD(&result[1], EC_SUCCESS);
12877 					if (msg[1].length >= 4)
12878 					{
12879 						opt = GET_WORD(&ec_parms[0].info[2]);
12880 						plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12881 									  LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12882 						if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12883 							plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12884 						if (opt & EC_DETECT_DISABLE_TONE)
12885 							plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12886 						if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12887 							plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12888 						if (msg[1].length >= 6)
12889 						{
12890 							plci->ec_tail_length = GET_WORD(&ec_parms[0].info[4]);
12891 						}
12892 					}
12893 					switch (plci->ec_cmd)
12894 					{
12895 					case EC_ENABLE_OPERATION:
12896 						plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12897 						start_internal_command(Id, plci, ec_command);
12898 						return (false);
12899 
12900 					case EC_DISABLE_OPERATION:
12901 						plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12902 							LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12903 							LEC_RESET_COEFFICIENTS;
12904 						start_internal_command(Id, plci, ec_command);
12905 						return (false);
12906 
12907 					case EC_FREEZE_COEFFICIENTS:
12908 						plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12909 						start_internal_command(Id, plci, ec_command);
12910 						return (false);
12911 
12912 					case EC_RESUME_COEFFICIENT_UPDATE:
12913 						plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12914 						start_internal_command(Id, plci, ec_command);
12915 						return (false);
12916 
12917 					case EC_RESET_COEFFICIENTS:
12918 						plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12919 						start_internal_command(Id, plci, ec_command);
12920 						return (false);
12921 
12922 					default:
12923 						dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
12924 								UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
12925 						PUT_WORD(&result[1], EC_UNSUPPORTED_OPERATION);
12926 					}
12927 				}
12928 			}
12929 		}
12930 		else
12931 		{
12932 			if (api_parse(&msg[1].info[1], msg[1].length, "ws", ec_parms))
12933 			{
12934 				dbug(1, dprintf("[%06lx] %s,%d: Wrong message format",
12935 						UnMapId(Id), (char *)(FILE_), __LINE__));
12936 				Info = _WRONG_MESSAGE_FORMAT;
12937 			}
12938 			else
12939 			{
12940 				if (GET_WORD(ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12941 				{
12942 					result[0] = 11;
12943 					PUT_WORD(&result[1], EC_GET_SUPPORTED_SERVICES);
12944 					result[3] = 8;
12945 					PUT_WORD(&result[4], GOOD);
12946 					PUT_WORD(&result[6], 0x0007);
12947 					PUT_WORD(&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12948 					PUT_WORD(&result[10], 0);
12949 				}
12950 				else if (plci == NULL)
12951 				{
12952 					dbug(1, dprintf("[%06lx] %s,%d: Wrong PLCI",
12953 							UnMapId(Id), (char *)(FILE_), __LINE__));
12954 					Info = _WRONG_IDENTIFIER;
12955 				}
12956 				else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12957 				{
12958 					dbug(1, dprintf("[%06lx] %s,%d: Wrong state",
12959 							UnMapId(Id), (char *)(FILE_), __LINE__));
12960 					Info = _WRONG_STATE;
12961 				}
12962 				else
12963 				{
12964 					plci->command = 0;
12965 					plci->ec_cmd = GET_WORD(ec_parms[0].info);
12966 					plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12967 					result[0] = 5;
12968 					PUT_WORD(&result[1], plci->ec_cmd);
12969 					result[3] = 2;
12970 					PUT_WORD(&result[4], GOOD);
12971 					plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12972 								  LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12973 					plci->ec_tail_length = 0;
12974 					if (ec_parms[1].length >= 2)
12975 					{
12976 						opt = GET_WORD(&ec_parms[1].info[1]);
12977 						if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12978 							plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12979 						if (opt & EC_DETECT_DISABLE_TONE)
12980 							plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12981 						if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12982 							plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12983 						if (ec_parms[1].length >= 4)
12984 						{
12985 							plci->ec_tail_length = GET_WORD(&ec_parms[1].info[3]);
12986 						}
12987 					}
12988 					switch (plci->ec_cmd)
12989 					{
12990 					case EC_ENABLE_OPERATION:
12991 						plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12992 						start_internal_command(Id, plci, ec_command);
12993 						return (false);
12994 
12995 					case EC_DISABLE_OPERATION:
12996 						plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12997 							LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12998 							LEC_RESET_COEFFICIENTS;
12999 						start_internal_command(Id, plci, ec_command);
13000 						return (false);
13001 
13002 					default:
13003 						dbug(1, dprintf("[%06lx] %s,%d: EC unknown request %04x",
13004 								UnMapId(Id), (char *)(FILE_), __LINE__, plci->ec_cmd));
13005 						PUT_WORD(&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13006 					}
13007 				}
13008 			}
13009 		}
13010 	}
13011 	sendf(appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13012 	      "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13013 	      PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13014 	return (false);
13015 }
13016 
13017 
ec_indication(dword Id,PLCI * plci,byte * msg,word length)13018 static void ec_indication(dword Id, PLCI *plci, byte *msg, word length)
13019 {
13020 	byte result[8];
13021 
13022 	dbug(1, dprintf("[%06lx] %s,%d: ec_indication",
13023 			UnMapId(Id), (char *)(FILE_), __LINE__));
13024 
13025 	if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13026 	{
13027 		if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13028 		{
13029 			result[0] = 2;
13030 			PUT_WORD(&result[1], 0);
13031 			switch (msg[1])
13032 			{
13033 			case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13034 				PUT_WORD(&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13035 				break;
13036 			case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13037 				PUT_WORD(&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13038 				break;
13039 			case LEC_DISABLE_RELEASED:
13040 				PUT_WORD(&result[1], EC_BYPASS_RELEASED);
13041 				break;
13042 			}
13043 		}
13044 		else
13045 		{
13046 			result[0] = 5;
13047 			PUT_WORD(&result[1], EC_BYPASS_INDICATION);
13048 			result[3] = 2;
13049 			PUT_WORD(&result[4], 0);
13050 			switch (msg[1])
13051 			{
13052 			case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13053 				PUT_WORD(&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13054 				break;
13055 			case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13056 				PUT_WORD(&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13057 				break;
13058 			case LEC_DISABLE_RELEASED:
13059 				PUT_WORD(&result[4], EC_BYPASS_RELEASED);
13060 				break;
13061 			}
13062 		}
13063 		sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13064 		      PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13065 	}
13066 }
13067 
13068 
13069 
13070 /*------------------------------------------------------------------*/
13071 /* Advanced voice                                                   */
13072 /*------------------------------------------------------------------*/
13073 
adv_voice_write_coefs(PLCI * plci,word write_command)13074 static void adv_voice_write_coefs(PLCI *plci, word write_command)
13075 {
13076 	DIVA_CAPI_ADAPTER *a;
13077 	word i;
13078 	byte *p;
13079 
13080 	word w, n, j, k;
13081 	byte ch_map[MIXER_CHANNELS_BRI];
13082 
13083 	byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13084 
13085 	dbug(1, dprintf("[%06lx] %s,%d: adv_voice_write_coefs %d",
13086 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13087 			(char *)(FILE_), __LINE__, write_command));
13088 
13089 	a = plci->adapter;
13090 	p = coef_buffer + 1;
13091 	*(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13092 	i = 0;
13093 	while (i + sizeof(word) <= a->adv_voice_coef_length)
13094 	{
13095 		PUT_WORD(p, GET_WORD(a->adv_voice_coef_buffer + i));
13096 		p += 2;
13097 		i += 2;
13098 	}
13099 	while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13100 	{
13101 		PUT_WORD(p, 0x8000);
13102 		p += 2;
13103 		i += 2;
13104 	}
13105 
13106 	if (!a->li_pri && (plci->li_bchannel_id == 0))
13107 	{
13108 		if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13109 		{
13110 			plci->li_bchannel_id = 1;
13111 			li_config_table[a->li_base].plci = plci;
13112 			dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13113 					(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13114 					(char *)(FILE_), __LINE__, plci->li_bchannel_id));
13115 		}
13116 		else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13117 		{
13118 			plci->li_bchannel_id = 2;
13119 			li_config_table[a->li_base + 1].plci = plci;
13120 			dbug(1, dprintf("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13121 					(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13122 					(char *)(FILE_), __LINE__, plci->li_bchannel_id));
13123 		}
13124 	}
13125 	if (!a->li_pri && (plci->li_bchannel_id != 0)
13126 	    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13127 	{
13128 		i = a->li_base + (plci->li_bchannel_id - 1);
13129 		switch (write_command)
13130 		{
13131 		case ADV_VOICE_WRITE_ACTIVATION:
13132 			j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13133 			k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13134 			if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13135 			{
13136 				li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13137 				li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13138 			}
13139 			if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13140 			{
13141 				li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13142 				li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13143 				li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13144 				li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13145 			}
13146 			mixer_calculate_coefs(a);
13147 			li_config_table[i].curchnl = li_config_table[i].channel;
13148 			li_config_table[j].curchnl = li_config_table[j].channel;
13149 			if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13150 				li_config_table[k].curchnl = li_config_table[k].channel;
13151 			break;
13152 
13153 		case ADV_VOICE_WRITE_DEACTIVATION:
13154 			for (j = 0; j < li_total_channels; j++)
13155 			{
13156 				li_config_table[i].flag_table[j] = 0;
13157 				li_config_table[j].flag_table[i] = 0;
13158 			}
13159 			k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13160 			for (j = 0; j < li_total_channels; j++)
13161 			{
13162 				li_config_table[k].flag_table[j] = 0;
13163 				li_config_table[j].flag_table[k] = 0;
13164 			}
13165 			if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13166 			{
13167 				k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13168 				for (j = 0; j < li_total_channels; j++)
13169 				{
13170 					li_config_table[k].flag_table[j] = 0;
13171 					li_config_table[j].flag_table[k] = 0;
13172 				}
13173 			}
13174 			mixer_calculate_coefs(a);
13175 			break;
13176 		}
13177 		if (plci->B1_facilities & B1_FACILITY_MIXER)
13178 		{
13179 			w = 0;
13180 			if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13181 				w = GET_WORD(a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13182 			if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13183 				w |= MIXER_FEATURE_ENABLE_TX_DATA;
13184 			if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13185 				w |= MIXER_FEATURE_ENABLE_RX_DATA;
13186 			*(p++) = (byte) w;
13187 			*(p++) = (byte)(w >> 8);
13188 			for (j = 0; j < sizeof(ch_map); j += 2)
13189 			{
13190 				ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13191 				ch_map[j + 1] = (byte)(j + (2 - plci->li_bchannel_id));
13192 			}
13193 			for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13194 			{
13195 				i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13196 				j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13197 				if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13198 				{
13199 					*(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13200 					w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13201 					li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13202 				}
13203 				else
13204 				{
13205 					*(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13206 						a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13207 				}
13208 			}
13209 		}
13210 		else
13211 		{
13212 			for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13213 				*(p++) = a->adv_voice_coef_buffer[i];
13214 		}
13215 	}
13216 	else
13217 
13218 	{
13219 		for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13220 			*(p++) = a->adv_voice_coef_buffer[i];
13221 	}
13222 	coef_buffer[0] = (p - coef_buffer) - 1;
13223 	add_p(plci, FTY, coef_buffer);
13224 	sig_req(plci, TEL_CTRL, 0);
13225 	send_req(plci);
13226 }
13227 
13228 
adv_voice_clear_config(PLCI * plci)13229 static void adv_voice_clear_config(PLCI *plci)
13230 {
13231 	DIVA_CAPI_ADAPTER *a;
13232 
13233 	word i, j;
13234 
13235 
13236 	dbug(1, dprintf("[%06lx] %s,%d: adv_voice_clear_config",
13237 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13238 			(char *)(FILE_), __LINE__));
13239 
13240 	a = plci->adapter;
13241 	if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13242 	{
13243 		a->adv_voice_coef_length = 0;
13244 
13245 		if (!a->li_pri && (plci->li_bchannel_id != 0)
13246 		    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13247 		{
13248 			i = a->li_base + (plci->li_bchannel_id - 1);
13249 			li_config_table[i].curchnl = 0;
13250 			li_config_table[i].channel = 0;
13251 			li_config_table[i].chflags = 0;
13252 			for (j = 0; j < li_total_channels; j++)
13253 			{
13254 				li_config_table[i].flag_table[j] = 0;
13255 				li_config_table[j].flag_table[i] = 0;
13256 				li_config_table[i].coef_table[j] = 0;
13257 				li_config_table[j].coef_table[i] = 0;
13258 			}
13259 			li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13260 			i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13261 			li_config_table[i].curchnl = 0;
13262 			li_config_table[i].channel = 0;
13263 			li_config_table[i].chflags = 0;
13264 			for (j = 0; j < li_total_channels; j++)
13265 			{
13266 				li_config_table[i].flag_table[j] = 0;
13267 				li_config_table[j].flag_table[i] = 0;
13268 				li_config_table[i].coef_table[j] = 0;
13269 				li_config_table[j].coef_table[i] = 0;
13270 			}
13271 			if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13272 			{
13273 				i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13274 				li_config_table[i].curchnl = 0;
13275 				li_config_table[i].channel = 0;
13276 				li_config_table[i].chflags = 0;
13277 				for (j = 0; j < li_total_channels; j++)
13278 				{
13279 					li_config_table[i].flag_table[j] = 0;
13280 					li_config_table[j].flag_table[i] = 0;
13281 					li_config_table[i].coef_table[j] = 0;
13282 					li_config_table[j].coef_table[i] = 0;
13283 				}
13284 			}
13285 		}
13286 
13287 	}
13288 }
13289 
13290 
adv_voice_prepare_switch(dword Id,PLCI * plci)13291 static void adv_voice_prepare_switch(dword Id, PLCI *plci)
13292 {
13293 
13294 	dbug(1, dprintf("[%06lx] %s,%d: adv_voice_prepare_switch",
13295 			UnMapId(Id), (char *)(FILE_), __LINE__));
13296 
13297 }
13298 
13299 
adv_voice_save_config(dword Id,PLCI * plci,byte Rc)13300 static word adv_voice_save_config(dword Id, PLCI *plci, byte Rc)
13301 {
13302 
13303 	dbug(1, dprintf("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13304 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13305 
13306 	return (GOOD);
13307 }
13308 
13309 
adv_voice_restore_config(dword Id,PLCI * plci,byte Rc)13310 static word adv_voice_restore_config(dword Id, PLCI *plci, byte Rc)
13311 {
13312 	DIVA_CAPI_ADAPTER *a;
13313 	word Info;
13314 
13315 	dbug(1, dprintf("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13316 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13317 
13318 	Info = GOOD;
13319 	a = plci->adapter;
13320 	if ((plci->B1_facilities & B1_FACILITY_VOICE)
13321 	    && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13322 	{
13323 		switch (plci->adjust_b_state)
13324 		{
13325 		case ADJUST_B_RESTORE_VOICE_1:
13326 			plci->internal_command = plci->adjust_b_command;
13327 			if (plci->sig_req)
13328 			{
13329 				plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13330 				break;
13331 			}
13332 			adv_voice_write_coefs(plci, ADV_VOICE_WRITE_UPDATE);
13333 			plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13334 			break;
13335 		case ADJUST_B_RESTORE_VOICE_2:
13336 			if ((Rc != OK) && (Rc != OK_FC))
13337 			{
13338 				dbug(1, dprintf("[%06lx] %s,%d: Restore voice config failed %02x",
13339 						UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13340 				Info = _WRONG_STATE;
13341 				break;
13342 			}
13343 			break;
13344 		}
13345 	}
13346 	return (Info);
13347 }
13348 
13349 
13350 
13351 
13352 /*------------------------------------------------------------------*/
13353 /* B1 resource switching                                            */
13354 /*------------------------------------------------------------------*/
13355 
13356 static byte b1_facilities_table[] =
13357 {
13358 	0x00,  /* 0  No bchannel resources      */
13359 	0x00,  /* 1  Codec (automatic law)      */
13360 	0x00,  /* 2  Codec (A-law)              */
13361 	0x00,  /* 3  Codec (y-law)              */
13362 	0x00,  /* 4  HDLC for X.21              */
13363 	0x00,  /* 5  HDLC                       */
13364 	0x00,  /* 6  External Device 0          */
13365 	0x00,  /* 7  External Device 1          */
13366 	0x00,  /* 8  HDLC 56k                   */
13367 	0x00,  /* 9  Transparent                */
13368 	0x00,  /* 10 Loopback to network        */
13369 	0x00,  /* 11 Test pattern to net        */
13370 	0x00,  /* 12 Rate adaptation sync       */
13371 	0x00,  /* 13 Rate adaptation async      */
13372 	0x00,  /* 14 R-Interface                */
13373 	0x00,  /* 15 HDLC 128k leased line      */
13374 	0x00,  /* 16 FAX                        */
13375 	0x00,  /* 17 Modem async                */
13376 	0x00,  /* 18 Modem sync HDLC            */
13377 	0x00,  /* 19 V.110 async HDLC           */
13378 	0x12,  /* 20 Adv voice (Trans,mixer)    */
13379 	0x00,  /* 21 Codec connected to IC      */
13380 	0x0c,  /* 22 Trans,DTMF                 */
13381 	0x1e,  /* 23 Trans,DTMF+mixer           */
13382 	0x1f,  /* 24 Trans,DTMF+mixer+local     */
13383 	0x13,  /* 25 Trans,mixer+local          */
13384 	0x12,  /* 26 HDLC,mixer                 */
13385 	0x12,  /* 27 HDLC 56k,mixer             */
13386 	0x2c,  /* 28 Trans,LEC+DTMF             */
13387 	0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13388 	0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13389 	0x2c,  /* 31 RTP,LEC+DTMF               */
13390 	0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13391 	0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13392 	0x00,  /* 34 Signaling task             */
13393 	0x00,  /* 35 PIAFS                      */
13394 	0x0c,  /* 36 Trans,DTMF+TONE            */
13395 	0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13396 	0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13397 };
13398 
13399 
get_b1_facilities(PLCI * plci,byte b1_resource)13400 static word get_b1_facilities(PLCI *plci, byte b1_resource)
13401 {
13402 	word b1_facilities;
13403 
13404 	b1_facilities = b1_facilities_table[b1_resource];
13405 	if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13406 	{
13407 
13408 		if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13409 		      || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13410 
13411 		{
13412 			if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13413 				b1_facilities |= B1_FACILITY_DTMFX;
13414 			if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13415 				b1_facilities |= B1_FACILITY_DTMFR;
13416 		}
13417 	}
13418 	if ((b1_resource == 17) || (b1_resource == 18))
13419 	{
13420 		if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13421 			b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13422 	}
13423 /*
13424   dbug (1, dprintf("[%06lx] %s,%d: get_b1_facilities %d %04x",
13425   (dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13426   (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13427 */
13428 	return (b1_facilities);
13429 }
13430 
13431 
add_b1_facilities(PLCI * plci,byte b1_resource,word b1_facilities)13432 static byte add_b1_facilities(PLCI *plci, byte b1_resource, word b1_facilities)
13433 {
13434 	byte b;
13435 
13436 	switch (b1_resource)
13437 	{
13438 	case 5:
13439 	case 26:
13440 		if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13441 			b = 26;
13442 		else
13443 			b = 5;
13444 		break;
13445 
13446 	case 8:
13447 	case 27:
13448 		if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13449 			b = 27;
13450 		else
13451 			b = 8;
13452 		break;
13453 
13454 	case 9:
13455 	case 20:
13456 	case 22:
13457 	case 23:
13458 	case 24:
13459 	case 25:
13460 	case 28:
13461 	case 29:
13462 	case 30:
13463 	case 36:
13464 	case 37:
13465 	case 38:
13466 		if (b1_facilities & B1_FACILITY_EC)
13467 		{
13468 			if (b1_facilities & B1_FACILITY_LOCAL)
13469 				b = 30;
13470 			else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13471 				b = 29;
13472 			else
13473 				b = 28;
13474 		}
13475 
13476 		else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13477 			 && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13478 			     || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id - 1] & (1L << PRIVATE_DTMF_TONE)))))
13479 		{
13480 			if (b1_facilities & B1_FACILITY_LOCAL)
13481 				b = 38;
13482 			else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13483 				b = 37;
13484 			else
13485 				b = 36;
13486 		}
13487 
13488 		else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13489 			  && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13490 			 || ((b1_facilities & B1_FACILITY_DTMFR)
13491 			     && ((b1_facilities & B1_FACILITY_MIXER)
13492 				 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13493 			 || ((b1_facilities & B1_FACILITY_DTMFX)
13494 			     && ((b1_facilities & B1_FACILITY_MIXER)
13495 				 || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13496 		{
13497 			if (b1_facilities & B1_FACILITY_LOCAL)
13498 				b = 24;
13499 			else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13500 				b = 23;
13501 			else
13502 				b = 22;
13503 		}
13504 		else
13505 		{
13506 			if (b1_facilities & B1_FACILITY_LOCAL)
13507 				b = 25;
13508 			else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13509 				b = 20;
13510 			else
13511 				b = 9;
13512 		}
13513 		break;
13514 
13515 	case 31:
13516 	case 32:
13517 	case 33:
13518 		if (b1_facilities & B1_FACILITY_LOCAL)
13519 			b = 33;
13520 		else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13521 			b = 32;
13522 		else
13523 			b = 31;
13524 		break;
13525 
13526 	default:
13527 		b = b1_resource;
13528 	}
13529 	dbug(1, dprintf("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13530 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13531 			(char *)(FILE_), __LINE__,
13532 			b1_resource, b1_facilities, b, get_b1_facilities(plci, b)));
13533 	return (b);
13534 }
13535 
13536 
adjust_b1_facilities(PLCI * plci,byte new_b1_resource,word new_b1_facilities)13537 static void adjust_b1_facilities(PLCI *plci, byte new_b1_resource, word new_b1_facilities)
13538 {
13539 	word removed_facilities;
13540 
13541 	dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13542 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13543 			(char *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13544 			new_b1_facilities & get_b1_facilities(plci, new_b1_resource)));
13545 
13546 	new_b1_facilities &= get_b1_facilities(plci, new_b1_resource);
13547 	removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13548 
13549 	if (removed_facilities & B1_FACILITY_EC)
13550 		ec_clear_config(plci);
13551 
13552 
13553 	if (removed_facilities & B1_FACILITY_DTMFR)
13554 	{
13555 		dtmf_rec_clear_config(plci);
13556 		dtmf_parameter_clear_config(plci);
13557 	}
13558 	if (removed_facilities & B1_FACILITY_DTMFX)
13559 		dtmf_send_clear_config(plci);
13560 
13561 
13562 	if (removed_facilities & B1_FACILITY_MIXER)
13563 		mixer_clear_config(plci);
13564 
13565 	if (removed_facilities & B1_FACILITY_VOICE)
13566 		adv_voice_clear_config(plci);
13567 	plci->B1_facilities = new_b1_facilities;
13568 }
13569 
13570 
adjust_b_clear(PLCI * plci)13571 static void adjust_b_clear(PLCI *plci)
13572 {
13573 
13574 	dbug(1, dprintf("[%06lx] %s,%d: adjust_b_clear",
13575 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
13576 			(char *)(FILE_), __LINE__));
13577 
13578 	plci->adjust_b_restore = false;
13579 }
13580 
13581 
adjust_b_process(dword Id,PLCI * plci,byte Rc)13582 static word adjust_b_process(dword Id, PLCI *plci, byte Rc)
13583 {
13584 	word Info;
13585 	byte b1_resource;
13586 	NCCI *ncci_ptr;
13587 	API_PARSE bp[2];
13588 
13589 	dbug(1, dprintf("[%06lx] %s,%d: adjust_b_process %02x %d",
13590 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13591 
13592 	Info = GOOD;
13593 	switch (plci->adjust_b_state)
13594 	{
13595 	case ADJUST_B_START:
13596 		if ((plci->adjust_b_parms_msg == NULL)
13597 		    && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13598 		    && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13599 						 ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13600 		{
13601 			b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13602 				0 : add_b1_facilities(plci, plci->B1_resource, plci->adjust_b_facilities);
13603 			if (b1_resource == plci->B1_resource)
13604 			{
13605 				adjust_b1_facilities(plci, b1_resource, plci->adjust_b_facilities);
13606 				break;
13607 			}
13608 			if (plci->adjust_b_facilities & ~get_b1_facilities(plci, b1_resource))
13609 			{
13610 				dbug(1, dprintf("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13611 						UnMapId(Id), (char *)(FILE_), __LINE__,
13612 						plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13613 				Info = _WRONG_STATE;
13614 				break;
13615 			}
13616 		}
13617 		if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13618 		{
13619 
13620 			mixer_prepare_switch(Id, plci);
13621 
13622 
13623 			dtmf_prepare_switch(Id, plci);
13624 			dtmf_parameter_prepare_switch(Id, plci);
13625 
13626 
13627 			ec_prepare_switch(Id, plci);
13628 
13629 			adv_voice_prepare_switch(Id, plci);
13630 		}
13631 		plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13632 		Rc = OK;
13633 	case ADJUST_B_SAVE_MIXER_1:
13634 		if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13635 		{
13636 
13637 			Info = mixer_save_config(Id, plci, Rc);
13638 			if ((Info != GOOD) || plci->internal_command)
13639 				break;
13640 
13641 		}
13642 		plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13643 		Rc = OK;
13644 	case ADJUST_B_SAVE_DTMF_1:
13645 		if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13646 		{
13647 
13648 			Info = dtmf_save_config(Id, plci, Rc);
13649 			if ((Info != GOOD) || plci->internal_command)
13650 				break;
13651 
13652 		}
13653 		plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13654 	case ADJUST_B_REMOVE_L23_1:
13655 		if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13656 		    && plci->NL.Id && !plci->nl_remove_id)
13657 		{
13658 			plci->internal_command = plci->adjust_b_command;
13659 			if (plci->adjust_b_ncci != 0)
13660 			{
13661 				ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13662 				while (ncci_ptr->data_pending)
13663 				{
13664 					plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13665 					data_rc(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13666 				}
13667 				while (ncci_ptr->data_ack_pending)
13668 					data_ack(plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13669 			}
13670 			nl_req_ncci(plci, REMOVE,
13671 				    (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13672 			send_req(plci);
13673 			plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13674 			break;
13675 		}
13676 		plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13677 		Rc = OK;
13678 	case ADJUST_B_REMOVE_L23_2:
13679 		if ((Rc != OK) && (Rc != OK_FC))
13680 		{
13681 			dbug(1, dprintf("[%06lx] %s,%d: Adjust B remove failed %02x",
13682 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13683 			Info = _WRONG_STATE;
13684 			break;
13685 		}
13686 		if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13687 		{
13688 			if (plci_nl_busy(plci))
13689 			{
13690 				plci->internal_command = plci->adjust_b_command;
13691 				break;
13692 			}
13693 		}
13694 		plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13695 		Rc = OK;
13696 	case ADJUST_B_SAVE_EC_1:
13697 		if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13698 		{
13699 
13700 			Info = ec_save_config(Id, plci, Rc);
13701 			if ((Info != GOOD) || plci->internal_command)
13702 				break;
13703 
13704 		}
13705 		plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13706 		Rc = OK;
13707 	case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13708 		if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13709 		{
13710 
13711 			Info = dtmf_parameter_save_config(Id, plci, Rc);
13712 			if ((Info != GOOD) || plci->internal_command)
13713 				break;
13714 
13715 		}
13716 		plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13717 		Rc = OK;
13718 	case ADJUST_B_SAVE_VOICE_1:
13719 		if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13720 		{
13721 			Info = adv_voice_save_config(Id, plci, Rc);
13722 			if ((Info != GOOD) || plci->internal_command)
13723 				break;
13724 		}
13725 		plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13726 	case ADJUST_B_SWITCH_L1_1:
13727 		if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13728 		{
13729 			if (plci->sig_req)
13730 			{
13731 				plci->internal_command = plci->adjust_b_command;
13732 				break;
13733 			}
13734 			if (plci->adjust_b_parms_msg != NULL)
13735 				api_load_msg(plci->adjust_b_parms_msg, bp);
13736 			else
13737 				api_load_msg(&plci->B_protocol, bp);
13738 			Info = add_b1(plci, bp,
13739 				      (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13740 				      plci->adjust_b_facilities);
13741 			if (Info != GOOD)
13742 			{
13743 				dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13744 						UnMapId(Id), (char *)(FILE_), __LINE__,
13745 						plci->B1_resource, plci->adjust_b_facilities));
13746 				break;
13747 			}
13748 			plci->internal_command = plci->adjust_b_command;
13749 			sig_req(plci, RESOURCES, 0);
13750 			send_req(plci);
13751 			plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13752 			break;
13753 		}
13754 		plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13755 		Rc = OK;
13756 	case ADJUST_B_SWITCH_L1_2:
13757 		if ((Rc != OK) && (Rc != OK_FC))
13758 		{
13759 			dbug(1, dprintf("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13760 					UnMapId(Id), (char *)(FILE_), __LINE__,
13761 					Rc, plci->B1_resource, plci->adjust_b_facilities));
13762 			Info = _WRONG_STATE;
13763 			break;
13764 		}
13765 		plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13766 		Rc = OK;
13767 	case ADJUST_B_RESTORE_VOICE_1:
13768 	case ADJUST_B_RESTORE_VOICE_2:
13769 		if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13770 		{
13771 			Info = adv_voice_restore_config(Id, plci, Rc);
13772 			if ((Info != GOOD) || plci->internal_command)
13773 				break;
13774 		}
13775 		plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13776 		Rc = OK;
13777 	case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13778 	case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13779 		if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13780 		{
13781 
13782 			Info = dtmf_parameter_restore_config(Id, plci, Rc);
13783 			if ((Info != GOOD) || plci->internal_command)
13784 				break;
13785 
13786 		}
13787 		plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13788 		Rc = OK;
13789 	case ADJUST_B_RESTORE_EC_1:
13790 	case ADJUST_B_RESTORE_EC_2:
13791 		if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13792 		{
13793 
13794 			Info = ec_restore_config(Id, plci, Rc);
13795 			if ((Info != GOOD) || plci->internal_command)
13796 				break;
13797 
13798 		}
13799 		plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13800 	case ADJUST_B_ASSIGN_L23_1:
13801 		if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13802 		{
13803 			if (plci_nl_busy(plci))
13804 			{
13805 				plci->internal_command = plci->adjust_b_command;
13806 				break;
13807 			}
13808 			if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13809 				plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13810 			if (plci->adjust_b_parms_msg != NULL)
13811 				api_load_msg(plci->adjust_b_parms_msg, bp);
13812 			else
13813 				api_load_msg(&plci->B_protocol, bp);
13814 			Info = add_b23(plci, bp);
13815 			if (Info != GOOD)
13816 			{
13817 				dbug(1, dprintf("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13818 						UnMapId(Id), (char *)(FILE_), __LINE__, Info));
13819 				break;
13820 			}
13821 			plci->internal_command = plci->adjust_b_command;
13822 			nl_req_ncci(plci, ASSIGN, 0);
13823 			send_req(plci);
13824 			plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13825 			break;
13826 		}
13827 		plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13828 		Rc = ASSIGN_OK;
13829 	case ADJUST_B_ASSIGN_L23_2:
13830 		if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13831 		{
13832 			dbug(1, dprintf("[%06lx] %s,%d: Adjust B assign failed %02x",
13833 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13834 			Info = _WRONG_STATE;
13835 			break;
13836 		}
13837 		if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13838 		{
13839 			if (Rc != ASSIGN_OK)
13840 			{
13841 				plci->internal_command = plci->adjust_b_command;
13842 				break;
13843 			}
13844 		}
13845 		if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13846 		{
13847 			plci->adjust_b_restore = true;
13848 			break;
13849 		}
13850 		plci->adjust_b_state = ADJUST_B_CONNECT_1;
13851 	case ADJUST_B_CONNECT_1:
13852 		if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13853 		{
13854 			plci->internal_command = plci->adjust_b_command;
13855 			if (plci_nl_busy(plci))
13856 				break;
13857 			nl_req_ncci(plci, N_CONNECT, 0);
13858 			send_req(plci);
13859 			plci->adjust_b_state = ADJUST_B_CONNECT_2;
13860 			break;
13861 		}
13862 		plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13863 		Rc = OK;
13864 	case ADJUST_B_CONNECT_2:
13865 	case ADJUST_B_CONNECT_3:
13866 	case ADJUST_B_CONNECT_4:
13867 		if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13868 		{
13869 			dbug(1, dprintf("[%06lx] %s,%d: Adjust B connect failed %02x",
13870 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13871 			Info = _WRONG_STATE;
13872 			break;
13873 		}
13874 		if (Rc == OK)
13875 		{
13876 			if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13877 			{
13878 				get_ncci(plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13879 				Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13880 			}
13881 			if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13882 				plci->adjust_b_state = ADJUST_B_CONNECT_3;
13883 			else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13884 				plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13885 		}
13886 		else if (Rc == 0)
13887 		{
13888 			if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13889 				plci->adjust_b_state = ADJUST_B_CONNECT_4;
13890 			else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13891 				plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13892 		}
13893 		if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13894 		{
13895 			plci->internal_command = plci->adjust_b_command;
13896 			break;
13897 		}
13898 		Rc = OK;
13899 	case ADJUST_B_RESTORE_DTMF_1:
13900 	case ADJUST_B_RESTORE_DTMF_2:
13901 		if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13902 		{
13903 
13904 			Info = dtmf_restore_config(Id, plci, Rc);
13905 			if ((Info != GOOD) || plci->internal_command)
13906 				break;
13907 
13908 		}
13909 		plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13910 		Rc = OK;
13911 	case ADJUST_B_RESTORE_MIXER_1:
13912 	case ADJUST_B_RESTORE_MIXER_2:
13913 	case ADJUST_B_RESTORE_MIXER_3:
13914 	case ADJUST_B_RESTORE_MIXER_4:
13915 	case ADJUST_B_RESTORE_MIXER_5:
13916 	case ADJUST_B_RESTORE_MIXER_6:
13917 	case ADJUST_B_RESTORE_MIXER_7:
13918 		if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13919 		{
13920 
13921 			Info = mixer_restore_config(Id, plci, Rc);
13922 			if ((Info != GOOD) || plci->internal_command)
13923 				break;
13924 
13925 		}
13926 		plci->adjust_b_state = ADJUST_B_END;
13927 	case ADJUST_B_END:
13928 		break;
13929 	}
13930 	return (Info);
13931 }
13932 
13933 
adjust_b1_resource(dword Id,PLCI * plci,API_SAVE * bp_msg,word b1_facilities,word internal_command)13934 static void adjust_b1_resource(dword Id, PLCI *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13935 {
13936 
13937 	dbug(1, dprintf("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13938 			UnMapId(Id), (char *)(FILE_), __LINE__,
13939 			plci->B1_resource, b1_facilities));
13940 
13941 	plci->adjust_b_parms_msg = bp_msg;
13942 	plci->adjust_b_facilities = b1_facilities;
13943 	plci->adjust_b_command = internal_command;
13944 	plci->adjust_b_ncci = (word)(Id >> 16);
13945 	if ((bp_msg == NULL) && (plci->B1_resource == 0))
13946 		plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13947 	else
13948 		plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13949 	plci->adjust_b_state = ADJUST_B_START;
13950 	dbug(1, dprintf("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13951 			UnMapId(Id), (char *)(FILE_), __LINE__,
13952 			plci->B1_resource, b1_facilities));
13953 }
13954 
13955 
adjust_b_restore(dword Id,PLCI * plci,byte Rc)13956 static void adjust_b_restore(dword Id, PLCI *plci, byte Rc)
13957 {
13958 	word internal_command;
13959 
13960 	dbug(1, dprintf("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13961 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
13962 
13963 	internal_command = plci->internal_command;
13964 	plci->internal_command = 0;
13965 	switch (internal_command)
13966 	{
13967 	default:
13968 		plci->command = 0;
13969 		if (plci->req_in != 0)
13970 		{
13971 			plci->internal_command = ADJUST_B_RESTORE_1;
13972 			break;
13973 		}
13974 		Rc = OK;
13975 	case ADJUST_B_RESTORE_1:
13976 		if ((Rc != OK) && (Rc != OK_FC))
13977 		{
13978 			dbug(1, dprintf("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13979 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
13980 		}
13981 		plci->adjust_b_parms_msg = NULL;
13982 		plci->adjust_b_facilities = plci->B1_facilities;
13983 		plci->adjust_b_command = ADJUST_B_RESTORE_2;
13984 		plci->adjust_b_ncci = (word)(Id >> 16);
13985 		plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13986 		plci->adjust_b_state = ADJUST_B_START;
13987 		dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore...",
13988 				UnMapId(Id), (char *)(FILE_), __LINE__));
13989 	case ADJUST_B_RESTORE_2:
13990 		if (adjust_b_process(Id, plci, Rc) != GOOD)
13991 		{
13992 			dbug(1, dprintf("[%06lx] %s,%d: Adjust B restore failed",
13993 					UnMapId(Id), (char *)(FILE_), __LINE__));
13994 		}
13995 		if (plci->internal_command)
13996 			break;
13997 		break;
13998 	}
13999 }
14000 
14001 
reset_b3_command(dword Id,PLCI * plci,byte Rc)14002 static void reset_b3_command(dword Id, PLCI *plci, byte Rc)
14003 {
14004 	word Info;
14005 	word internal_command;
14006 
14007 	dbug(1, dprintf("[%06lx] %s,%d: reset_b3_command %02x %04x",
14008 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14009 
14010 	Info = GOOD;
14011 	internal_command = plci->internal_command;
14012 	plci->internal_command = 0;
14013 	switch (internal_command)
14014 	{
14015 	default:
14016 		plci->command = 0;
14017 		plci->adjust_b_parms_msg = NULL;
14018 		plci->adjust_b_facilities = plci->B1_facilities;
14019 		plci->adjust_b_command = RESET_B3_COMMAND_1;
14020 		plci->adjust_b_ncci = (word)(Id >> 16);
14021 		plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14022 		plci->adjust_b_state = ADJUST_B_START;
14023 		dbug(1, dprintf("[%06lx] %s,%d: Reset B3...",
14024 				UnMapId(Id), (char *)(FILE_), __LINE__));
14025 	case RESET_B3_COMMAND_1:
14026 		Info = adjust_b_process(Id, plci, Rc);
14027 		if (Info != GOOD)
14028 		{
14029 			dbug(1, dprintf("[%06lx] %s,%d: Reset failed",
14030 					UnMapId(Id), (char *)(FILE_), __LINE__));
14031 			break;
14032 		}
14033 		if (plci->internal_command)
14034 			return;
14035 		break;
14036 	}
14037 /*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14038 	sendf(plci->appl, _RESET_B3_I, Id, 0, "s", "");
14039 }
14040 
14041 
select_b_command(dword Id,PLCI * plci,byte Rc)14042 static void select_b_command(dword Id, PLCI *plci, byte Rc)
14043 {
14044 	word Info;
14045 	word internal_command;
14046 	byte esc_chi[3];
14047 
14048 	dbug(1, dprintf("[%06lx] %s,%d: select_b_command %02x %04x",
14049 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14050 
14051 	Info = GOOD;
14052 	internal_command = plci->internal_command;
14053 	plci->internal_command = 0;
14054 	switch (internal_command)
14055 	{
14056 	default:
14057 		plci->command = 0;
14058 		plci->adjust_b_parms_msg = &plci->saved_msg;
14059 		if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14060 			plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14061 		else
14062 			plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14063 		plci->adjust_b_command = SELECT_B_COMMAND_1;
14064 		plci->adjust_b_ncci = (word)(Id >> 16);
14065 		if (plci->saved_msg.parms[0].length == 0)
14066 		{
14067 			plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14068 				ADJUST_B_MODE_NO_RESOURCE;
14069 		}
14070 		else
14071 		{
14072 			plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14073 				ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14074 		}
14075 		plci->adjust_b_state = ADJUST_B_START;
14076 		dbug(1, dprintf("[%06lx] %s,%d: Select B protocol...",
14077 				UnMapId(Id), (char *)(FILE_), __LINE__));
14078 	case SELECT_B_COMMAND_1:
14079 		Info = adjust_b_process(Id, plci, Rc);
14080 		if (Info != GOOD)
14081 		{
14082 			dbug(1, dprintf("[%06lx] %s,%d: Select B protocol failed",
14083 					UnMapId(Id), (char *)(FILE_), __LINE__));
14084 			break;
14085 		}
14086 		if (plci->internal_command)
14087 			return;
14088 		if (plci->tel == ADV_VOICE)
14089 		{
14090 			esc_chi[0] = 0x02;
14091 			esc_chi[1] = 0x18;
14092 			esc_chi[2] = plci->b_channel;
14093 			SetVoiceChannel(plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14094 		}
14095 		break;
14096 	}
14097 	sendf(plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14098 }
14099 
14100 
fax_connect_ack_command(dword Id,PLCI * plci,byte Rc)14101 static void fax_connect_ack_command(dword Id, PLCI *plci, byte Rc)
14102 {
14103 	word internal_command;
14104 
14105 	dbug(1, dprintf("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14106 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14107 
14108 	internal_command = plci->internal_command;
14109 	plci->internal_command = 0;
14110 	switch (internal_command)
14111 	{
14112 	default:
14113 		plci->command = 0;
14114 	case FAX_CONNECT_ACK_COMMAND_1:
14115 		if (plci_nl_busy(plci))
14116 		{
14117 			plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14118 			return;
14119 		}
14120 		plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14121 		plci->NData[0].P = plci->fax_connect_info_buffer;
14122 		plci->NData[0].PLength = plci->fax_connect_info_length;
14123 		plci->NL.X = plci->NData;
14124 		plci->NL.ReqCh = 0;
14125 		plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14126 		plci->adapter->request(&plci->NL);
14127 		return;
14128 	case FAX_CONNECT_ACK_COMMAND_2:
14129 		if ((Rc != OK) && (Rc != OK_FC))
14130 		{
14131 			dbug(1, dprintf("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14132 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14133 			break;
14134 		}
14135 	}
14136 	if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14137 	    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14138 	{
14139 		if (plci->B3_prot == 4)
14140 			sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14141 		else
14142 			sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "S", plci->ncpi_buffer);
14143 		plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14144 	}
14145 }
14146 
14147 
fax_edata_ack_command(dword Id,PLCI * plci,byte Rc)14148 static void fax_edata_ack_command(dword Id, PLCI *plci, byte Rc)
14149 {
14150 	word internal_command;
14151 
14152 	dbug(1, dprintf("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14153 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14154 
14155 	internal_command = plci->internal_command;
14156 	plci->internal_command = 0;
14157 	switch (internal_command)
14158 	{
14159 	default:
14160 		plci->command = 0;
14161 	case FAX_EDATA_ACK_COMMAND_1:
14162 		if (plci_nl_busy(plci))
14163 		{
14164 			plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14165 			return;
14166 		}
14167 		plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14168 		plci->NData[0].P = plci->fax_connect_info_buffer;
14169 		plci->NData[0].PLength = plci->fax_edata_ack_length;
14170 		plci->NL.X = plci->NData;
14171 		plci->NL.ReqCh = 0;
14172 		plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14173 		plci->adapter->request(&plci->NL);
14174 		return;
14175 	case FAX_EDATA_ACK_COMMAND_2:
14176 		if ((Rc != OK) && (Rc != OK_FC))
14177 		{
14178 			dbug(1, dprintf("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14179 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14180 			break;
14181 		}
14182 	}
14183 }
14184 
14185 
fax_connect_info_command(dword Id,PLCI * plci,byte Rc)14186 static void fax_connect_info_command(dword Id, PLCI *plci, byte Rc)
14187 {
14188 	word Info;
14189 	word internal_command;
14190 
14191 	dbug(1, dprintf("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14192 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14193 
14194 	Info = GOOD;
14195 	internal_command = plci->internal_command;
14196 	plci->internal_command = 0;
14197 	switch (internal_command)
14198 	{
14199 	default:
14200 		plci->command = 0;
14201 	case FAX_CONNECT_INFO_COMMAND_1:
14202 		if (plci_nl_busy(plci))
14203 		{
14204 			plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14205 			return;
14206 		}
14207 		plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14208 		plci->NData[0].P = plci->fax_connect_info_buffer;
14209 		plci->NData[0].PLength = plci->fax_connect_info_length;
14210 		plci->NL.X = plci->NData;
14211 		plci->NL.ReqCh = 0;
14212 		plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14213 		plci->adapter->request(&plci->NL);
14214 		return;
14215 	case FAX_CONNECT_INFO_COMMAND_2:
14216 		if ((Rc != OK) && (Rc != OK_FC))
14217 		{
14218 			dbug(1, dprintf("[%06lx] %s,%d: FAX setting connect info failed %02x",
14219 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14220 			Info = _WRONG_STATE;
14221 			break;
14222 		}
14223 		if (plci_nl_busy(plci))
14224 		{
14225 			plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14226 			return;
14227 		}
14228 		plci->command = _CONNECT_B3_R;
14229 		nl_req_ncci(plci, N_CONNECT, 0);
14230 		send_req(plci);
14231 		return;
14232 	}
14233 	sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14234 }
14235 
14236 
fax_adjust_b23_command(dword Id,PLCI * plci,byte Rc)14237 static void fax_adjust_b23_command(dword Id, PLCI *plci, byte Rc)
14238 {
14239 	word Info;
14240 	word internal_command;
14241 
14242 	dbug(1, dprintf("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14243 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14244 
14245 	Info = GOOD;
14246 	internal_command = plci->internal_command;
14247 	plci->internal_command = 0;
14248 	switch (internal_command)
14249 	{
14250 	default:
14251 		plci->command = 0;
14252 		plci->adjust_b_parms_msg = NULL;
14253 		plci->adjust_b_facilities = plci->B1_facilities;
14254 		plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14255 		plci->adjust_b_ncci = (word)(Id >> 16);
14256 		plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14257 		plci->adjust_b_state = ADJUST_B_START;
14258 		dbug(1, dprintf("[%06lx] %s,%d: FAX adjust B23...",
14259 				UnMapId(Id), (char *)(FILE_), __LINE__));
14260 	case FAX_ADJUST_B23_COMMAND_1:
14261 		Info = adjust_b_process(Id, plci, Rc);
14262 		if (Info != GOOD)
14263 		{
14264 			dbug(1, dprintf("[%06lx] %s,%d: FAX adjust failed",
14265 					UnMapId(Id), (char *)(FILE_), __LINE__));
14266 			break;
14267 		}
14268 		if (plci->internal_command)
14269 			return;
14270 	case FAX_ADJUST_B23_COMMAND_2:
14271 		if (plci_nl_busy(plci))
14272 		{
14273 			plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14274 			return;
14275 		}
14276 		plci->command = _CONNECT_B3_R;
14277 		nl_req_ncci(plci, N_CONNECT, 0);
14278 		send_req(plci);
14279 		return;
14280 	}
14281 	sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14282 }
14283 
14284 
fax_disconnect_command(dword Id,PLCI * plci,byte Rc)14285 static void fax_disconnect_command(dword Id, PLCI *plci, byte Rc)
14286 {
14287 	word internal_command;
14288 
14289 	dbug(1, dprintf("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14290 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14291 
14292 	internal_command = plci->internal_command;
14293 	plci->internal_command = 0;
14294 	switch (internal_command)
14295 	{
14296 	default:
14297 		plci->command = 0;
14298 		plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14299 		return;
14300 	case FAX_DISCONNECT_COMMAND_1:
14301 	case FAX_DISCONNECT_COMMAND_2:
14302 	case FAX_DISCONNECT_COMMAND_3:
14303 		if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14304 		{
14305 			dbug(1, dprintf("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14306 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14307 			break;
14308 		}
14309 		if (Rc == OK)
14310 		{
14311 			if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14312 			    || (internal_command == FAX_DISCONNECT_COMMAND_2))
14313 			{
14314 				plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14315 			}
14316 		}
14317 		else if (Rc == 0)
14318 		{
14319 			if (internal_command == FAX_DISCONNECT_COMMAND_1)
14320 				plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14321 		}
14322 		return;
14323 	}
14324 }
14325 
14326 
14327 
rtp_connect_b3_req_command(dword Id,PLCI * plci,byte Rc)14328 static void rtp_connect_b3_req_command(dword Id, PLCI *plci, byte Rc)
14329 {
14330 	word Info;
14331 	word internal_command;
14332 
14333 	dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14334 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14335 
14336 	Info = GOOD;
14337 	internal_command = plci->internal_command;
14338 	plci->internal_command = 0;
14339 	switch (internal_command)
14340 	{
14341 	default:
14342 		plci->command = 0;
14343 	case RTP_CONNECT_B3_REQ_COMMAND_1:
14344 		if (plci_nl_busy(plci))
14345 		{
14346 			plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14347 			return;
14348 		}
14349 		plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14350 		nl_req_ncci(plci, N_CONNECT, 0);
14351 		send_req(plci);
14352 		return;
14353 	case RTP_CONNECT_B3_REQ_COMMAND_2:
14354 		if ((Rc != OK) && (Rc != OK_FC))
14355 		{
14356 			dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect info failed %02x",
14357 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14358 			Info = _WRONG_STATE;
14359 			break;
14360 		}
14361 		if (plci_nl_busy(plci))
14362 		{
14363 			plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14364 			return;
14365 		}
14366 		plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14367 		plci->NData[0].PLength = plci->internal_req_buffer[0];
14368 		plci->NData[0].P = plci->internal_req_buffer + 1;
14369 		plci->NL.X = plci->NData;
14370 		plci->NL.ReqCh = 0;
14371 		plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14372 		plci->adapter->request(&plci->NL);
14373 		break;
14374 	case RTP_CONNECT_B3_REQ_COMMAND_3:
14375 		return;
14376 	}
14377 	sendf(plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14378 }
14379 
14380 
rtp_connect_b3_res_command(dword Id,PLCI * plci,byte Rc)14381 static void rtp_connect_b3_res_command(dword Id, PLCI *plci, byte Rc)
14382 {
14383 	word internal_command;
14384 
14385 	dbug(1, dprintf("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14386 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14387 
14388 	internal_command = plci->internal_command;
14389 	plci->internal_command = 0;
14390 	switch (internal_command)
14391 	{
14392 	default:
14393 		plci->command = 0;
14394 	case RTP_CONNECT_B3_RES_COMMAND_1:
14395 		if (plci_nl_busy(plci))
14396 		{
14397 			plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14398 			return;
14399 		}
14400 		plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14401 		nl_req_ncci(plci, N_CONNECT_ACK, (byte)(Id >> 16));
14402 		send_req(plci);
14403 		return;
14404 	case RTP_CONNECT_B3_RES_COMMAND_2:
14405 		if ((Rc != OK) && (Rc != OK_FC))
14406 		{
14407 			dbug(1, dprintf("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14408 					UnMapId(Id), (char *)(FILE_), __LINE__, Rc));
14409 			break;
14410 		}
14411 		if (plci_nl_busy(plci))
14412 		{
14413 			plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14414 			return;
14415 		}
14416 		sendf(plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14417 		plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14418 		plci->NData[0].PLength = plci->internal_req_buffer[0];
14419 		plci->NData[0].P = plci->internal_req_buffer + 1;
14420 		plci->NL.X = plci->NData;
14421 		plci->NL.ReqCh = 0;
14422 		plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14423 		plci->adapter->request(&plci->NL);
14424 		return;
14425 	case RTP_CONNECT_B3_RES_COMMAND_3:
14426 		return;
14427 	}
14428 }
14429 
14430 
14431 
hold_save_command(dword Id,PLCI * plci,byte Rc)14432 static void hold_save_command(dword Id, PLCI *plci, byte Rc)
14433 {
14434 	byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14435 	word Info;
14436 	word internal_command;
14437 
14438 	dbug(1, dprintf("[%06lx] %s,%d: hold_save_command %02x %04x",
14439 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14440 
14441 	Info = GOOD;
14442 	internal_command = plci->internal_command;
14443 	plci->internal_command = 0;
14444 	switch (internal_command)
14445 	{
14446 	default:
14447 		if (!plci->NL.Id)
14448 			break;
14449 		plci->command = 0;
14450 		plci->adjust_b_parms_msg = NULL;
14451 		plci->adjust_b_facilities = plci->B1_facilities;
14452 		plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14453 		plci->adjust_b_ncci = (word)(Id >> 16);
14454 		plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14455 		plci->adjust_b_state = ADJUST_B_START;
14456 		dbug(1, dprintf("[%06lx] %s,%d: HOLD save...",
14457 				UnMapId(Id), (char *)(FILE_), __LINE__));
14458 	case HOLD_SAVE_COMMAND_1:
14459 		Info = adjust_b_process(Id, plci, Rc);
14460 		if (Info != GOOD)
14461 		{
14462 			dbug(1, dprintf("[%06lx] %s,%d: HOLD save failed",
14463 					UnMapId(Id), (char *)(FILE_), __LINE__));
14464 			break;
14465 		}
14466 		if (plci->internal_command)
14467 			return;
14468 	}
14469 	sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14470 }
14471 
14472 
retrieve_restore_command(dword Id,PLCI * plci,byte Rc)14473 static void retrieve_restore_command(dword Id, PLCI *plci, byte Rc)
14474 {
14475 	byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14476 	word Info;
14477 	word internal_command;
14478 
14479 	dbug(1, dprintf("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14480 			UnMapId(Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
14481 
14482 	Info = GOOD;
14483 	internal_command = plci->internal_command;
14484 	plci->internal_command = 0;
14485 	switch (internal_command)
14486 	{
14487 	default:
14488 		plci->command = 0;
14489 		plci->adjust_b_parms_msg = NULL;
14490 		plci->adjust_b_facilities = plci->B1_facilities;
14491 		plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14492 		plci->adjust_b_ncci = (word)(Id >> 16);
14493 		plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14494 		plci->adjust_b_state = ADJUST_B_START;
14495 		dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore...",
14496 				UnMapId(Id), (char *)(FILE_), __LINE__));
14497 	case RETRIEVE_RESTORE_COMMAND_1:
14498 		Info = adjust_b_process(Id, plci, Rc);
14499 		if (Info != GOOD)
14500 		{
14501 			dbug(1, dprintf("[%06lx] %s,%d: RETRIEVE restore failed",
14502 					UnMapId(Id), (char *)(FILE_), __LINE__));
14503 			break;
14504 		}
14505 		if (plci->internal_command)
14506 			return;
14507 	}
14508 	sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14509 }
14510 
14511 
init_b1_config(PLCI * plci)14512 static void init_b1_config(PLCI *plci)
14513 {
14514 
14515 	dbug(1, dprintf("[%06lx] %s,%d: init_b1_config",
14516 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14517 			(char *)(FILE_), __LINE__));
14518 
14519 	plci->B1_resource = 0;
14520 	plci->B1_facilities = 0;
14521 
14522 	plci->li_bchannel_id = 0;
14523 	mixer_clear_config(plci);
14524 
14525 
14526 	ec_clear_config(plci);
14527 
14528 
14529 	dtmf_rec_clear_config(plci);
14530 	dtmf_send_clear_config(plci);
14531 	dtmf_parameter_clear_config(plci);
14532 
14533 	adv_voice_clear_config(plci);
14534 	adjust_b_clear(plci);
14535 }
14536 
14537 
clear_b1_config(PLCI * plci)14538 static void clear_b1_config(PLCI *plci)
14539 {
14540 
14541 	dbug(1, dprintf("[%06lx] %s,%d: clear_b1_config",
14542 			(dword)((plci->Id << 8) | UnMapController(plci->adapter->Id)),
14543 			(char *)(FILE_), __LINE__));
14544 
14545 	adv_voice_clear_config(plci);
14546 	adjust_b_clear(plci);
14547 
14548 	ec_clear_config(plci);
14549 
14550 
14551 	dtmf_rec_clear_config(plci);
14552 	dtmf_send_clear_config(plci);
14553 	dtmf_parameter_clear_config(plci);
14554 
14555 
14556 	if ((plci->li_bchannel_id != 0)
14557 	    && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14558 	{
14559 		mixer_clear_config(plci);
14560 		li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14561 		plci->li_bchannel_id = 0;
14562 	}
14563 
14564 	plci->B1_resource = 0;
14565 	plci->B1_facilities = 0;
14566 }
14567 
14568 
14569 /* -----------------------------------------------------------------
14570    XON protocol local helpers
14571    ----------------------------------------------------------------- */
channel_flow_control_remove(PLCI * plci)14572 static void channel_flow_control_remove(PLCI *plci) {
14573 	DIVA_CAPI_ADAPTER *a = plci->adapter;
14574 	word i;
14575 	for (i = 1; i < MAX_NL_CHANNEL + 1; i++) {
14576 		if (a->ch_flow_plci[i] == plci->Id) {
14577 			a->ch_flow_plci[i] = 0;
14578 			a->ch_flow_control[i] = 0;
14579 		}
14580 	}
14581 }
14582 
channel_x_on(PLCI * plci,byte ch)14583 static void channel_x_on(PLCI *plci, byte ch) {
14584 	DIVA_CAPI_ADAPTER *a = plci->adapter;
14585 	if (a->ch_flow_control[ch] & N_XON_SENT) {
14586 		a->ch_flow_control[ch] &= ~N_XON_SENT;
14587 	}
14588 }
14589 
channel_x_off(PLCI * plci,byte ch,byte flag)14590 static void channel_x_off(PLCI *plci, byte ch, byte flag) {
14591 	DIVA_CAPI_ADAPTER *a = plci->adapter;
14592 	if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14593 		a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14594 		a->ch_flow_plci[ch] = plci->Id;
14595 		a->ch_flow_control_pending++;
14596 	}
14597 }
14598 
channel_request_xon(PLCI * plci,byte ch)14599 static void channel_request_xon(PLCI *plci, byte ch) {
14600 	DIVA_CAPI_ADAPTER *a = plci->adapter;
14601 
14602 	if (a->ch_flow_control[ch] & N_CH_XOFF) {
14603 		a->ch_flow_control[ch] |= N_XON_REQ;
14604 		a->ch_flow_control[ch] &= ~N_CH_XOFF;
14605 		a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14606 	}
14607 }
14608 
channel_xmit_extended_xon(PLCI * plci)14609 static void channel_xmit_extended_xon(PLCI *plci) {
14610 	DIVA_CAPI_ADAPTER *a;
14611 	int max_ch = ARRAY_SIZE(a->ch_flow_control);
14612 	int i, one_requested = 0;
14613 
14614 	if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14615 		return;
14616 	}
14617 
14618 	for (i = 0; i < max_ch; i++) {
14619 		if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14620 		    (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14621 		    (plci->Id == a->ch_flow_plci[i])) {
14622 			channel_request_xon(plci, (byte)i);
14623 			one_requested = 1;
14624 		}
14625 	}
14626 
14627 	if (one_requested) {
14628 		channel_xmit_xon(plci);
14629 	}
14630 }
14631 
14632 /*
14633   Try to xmit next X_ON
14634 */
find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER * a,PLCI * plci)14635 static int find_channel_with_pending_x_on(DIVA_CAPI_ADAPTER *a, PLCI *plci) {
14636 	int max_ch = ARRAY_SIZE(a->ch_flow_control);
14637 	int i;
14638 
14639 	if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14640 		return (0);
14641 	}
14642 
14643 	if (a->last_flow_control_ch >= max_ch) {
14644 		a->last_flow_control_ch = 1;
14645 	}
14646 	for (i = a->last_flow_control_ch; i < max_ch; i++) {
14647 		if ((a->ch_flow_control[i] & N_XON_REQ) &&
14648 		    (plci->Id == a->ch_flow_plci[i])) {
14649 			a->last_flow_control_ch = i + 1;
14650 			return (i);
14651 		}
14652 	}
14653 
14654 	for (i = 1; i < a->last_flow_control_ch; i++) {
14655 		if ((a->ch_flow_control[i] & N_XON_REQ) &&
14656 		    (plci->Id == a->ch_flow_plci[i])) {
14657 			a->last_flow_control_ch = i + 1;
14658 			return (i);
14659 		}
14660 	}
14661 
14662 	return (0);
14663 }
14664 
channel_xmit_xon(PLCI * plci)14665 static void channel_xmit_xon(PLCI *plci) {
14666 	DIVA_CAPI_ADAPTER *a = plci->adapter;
14667 	byte ch;
14668 
14669 	if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14670 		return;
14671 	}
14672 	if ((ch = (byte)find_channel_with_pending_x_on(a, plci)) == 0) {
14673 		return;
14674 	}
14675 	a->ch_flow_control[ch] &= ~N_XON_REQ;
14676 	a->ch_flow_control[ch] |= N_XON_SENT;
14677 
14678 	plci->NL.Req = plci->nl_req = (byte)N_XON;
14679 	plci->NL.ReqCh         = ch;
14680 	plci->NL.X             = plci->NData;
14681 	plci->NL.XNum          = 1;
14682 	plci->NData[0].P       = &plci->RBuffer[0];
14683 	plci->NData[0].PLength = 0;
14684 
14685 	plci->adapter->request(&plci->NL);
14686 }
14687 
channel_can_xon(PLCI * plci,byte ch)14688 static int channel_can_xon(PLCI *plci, byte ch) {
14689 	APPL *APPLptr;
14690 	DIVA_CAPI_ADAPTER *a;
14691 	word NCCIcode;
14692 	dword count;
14693 	word Num;
14694 	word i;
14695 
14696 	APPLptr = plci->appl;
14697 	a = plci->adapter;
14698 
14699 	if (!APPLptr)
14700 		return (0);
14701 
14702 	NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14703 
14704 	/* count all buffers within the Application pool    */
14705 	/* belonging to the same NCCI. XON if a first is    */
14706 	/* used.                                            */
14707 	count = 0;
14708 	Num = 0xffff;
14709 	for (i = 0; i < APPLptr->MaxBuffer; i++) {
14710 		if (NCCIcode == APPLptr->DataNCCI[i]) count++;
14711 		if (!APPLptr->DataNCCI[i] && Num == 0xffff) Num = i;
14712 	}
14713 	if ((count > 2) || (Num == 0xffff)) {
14714 		return (0);
14715 	}
14716 	return (1);
14717 }
14718 
14719 
14720 /*------------------------------------------------------------------*/
14721 
CPN_filter_ok(byte * cpn,DIVA_CAPI_ADAPTER * a,word offset)14722 static word CPN_filter_ok(byte *cpn, DIVA_CAPI_ADAPTER *a, word offset)
14723 {
14724 	return 1;
14725 }
14726 
14727 
14728 
14729 /**********************************************************************************/
14730 /* function groups the listening applications according to the CIP mask and the   */
14731 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14732 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14733 /* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14734 /* function must be enabled by setting "a->group_optimization_enabled" from the   */
14735 /* OS specific part (per adapter).                                                */
14736 /**********************************************************************************/
group_optimization(DIVA_CAPI_ADAPTER * a,PLCI * plci)14737 static void group_optimization(DIVA_CAPI_ADAPTER *a, PLCI *plci)
14738 {
14739 	word i, j, k, busy, group_found;
14740 	dword info_mask_group[MAX_CIP_TYPES];
14741 	dword cip_mask_group[MAX_CIP_TYPES];
14742 	word appl_number_group_type[MAX_APPL];
14743 	PLCI *auxplci;
14744 
14745 	set_group_ind_mask(plci); /* all APPLs within this inc. call are allowed to dial in */
14746 
14747 	if (!a->group_optimization_enabled)
14748 	{
14749 		dbug(1, dprintf("No group optimization"));
14750 		return;
14751 	}
14752 
14753 	dbug(1, dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14754 
14755 	for (i = 0; i < MAX_CIP_TYPES; i++)
14756 	{
14757 		info_mask_group[i] = 0;
14758 		cip_mask_group[i] = 0;
14759 	}
14760 	for (i = 0; i < MAX_APPL; i++)
14761 	{
14762 		appl_number_group_type[i] = 0;
14763 	}
14764 	for (i = 0; i < max_appl; i++) /* check if any multi instance capable application is present */
14765 	{  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14766 		if (application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i]) && (a->group_optimization_enabled == 1))
14767 		{
14768 			dbug(1, dprintf("Multi-Instance capable, no optimization required"));
14769 			return; /* allow good application unfiltered access */
14770 		}
14771 	}
14772 	for (i = 0; i < max_appl; i++) /* Build CIP Groups */
14773 	{
14774 		if (application[i].Id && a->CIP_Mask[i])
14775 		{
14776 			for (k = 0, busy = false; k < a->max_plci; k++)
14777 			{
14778 				if (a->plci[k].Id)
14779 				{
14780 					auxplci = &a->plci[k];
14781 					if (auxplci->appl == &application[i]) /* application has a busy PLCI */
14782 					{
14783 						busy = true;
14784 						dbug(1, dprintf("Appl 0x%x is busy", i + 1));
14785 					}
14786 					else if (test_c_ind_mask_bit(auxplci, i)) /* application has an incoming call pending */
14787 					{
14788 						busy = true;
14789 						dbug(1, dprintf("Appl 0x%x has inc. call pending", i + 1));
14790 					}
14791 				}
14792 			}
14793 
14794 			for (j = 0, group_found = 0; j <= (MAX_CIP_TYPES) && !busy && !group_found; j++)     /* build groups with free applications only */
14795 			{
14796 				if (j == MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14797 				{                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14798 					appl_number_group_type[i] = MAX_CIP_TYPES;
14799 					group_found = true;
14800 					dbug(1, dprintf("Field overflow appl 0x%x", i + 1));
14801 				}
14802 				else if ((info_mask_group[j] == a->CIP_Mask[i]) && (cip_mask_group[j] == a->Info_Mask[i]))
14803 				{                                      /* is group already present ?                  */
14804 					appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14805 					group_found = true;
14806 					dbug(1, dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx", appl_number_group_type[i], i + 1, info_mask_group[j]));
14807 				}
14808 				else if (!info_mask_group[j])
14809 				{                                      /* establish a new group                       */
14810 					appl_number_group_type[i] = j | 0x80;  /* store the group number for each application */
14811 					info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14812 					cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14813 					group_found = true;
14814 					dbug(1, dprintf("New Group 0x%x established with appl 0x%x, CIP=0x%lx", appl_number_group_type[i], i + 1, info_mask_group[j]));
14815 				}
14816 			}
14817 		}
14818 	}
14819 
14820 	for (i = 0; i < max_appl; i++) /* Build group_optimization_mask_table */
14821 	{
14822 		if (appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14823 		{
14824 			if (appl_number_group_type[i] == MAX_CIP_TYPES)
14825 			{
14826 				dbug(1, dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled", appl_number_group_type[i], i + 1));
14827 			}
14828 			else
14829 			{
14830 				dbug(1, dprintf("Group 0x%x, valid appl = 0x%x", appl_number_group_type[i], i + 1));
14831 				for (j = i + 1; j < max_appl; j++)   /* search other group members and mark them as busy        */
14832 				{
14833 					if (appl_number_group_type[i] == appl_number_group_type[j])
14834 					{
14835 						dbug(1, dprintf("Appl 0x%x is member of group 0x%x, no call", j + 1, appl_number_group_type[j]));
14836 						clear_group_ind_mask_bit(plci, j);           /* disable call on other group members */
14837 						appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14838 					}
14839 				}
14840 			}
14841 		}
14842 		else                                                 /* application should not get a call */
14843 		{
14844 			clear_group_ind_mask_bit(plci, i);
14845 		}
14846 	}
14847 
14848 }
14849 
14850 
14851 
14852 /* OS notifies the driver about a application Capi_Register */
CapiRegister(word id)14853 word CapiRegister(word id)
14854 {
14855 	word i, j, appls_found;
14856 
14857 	PLCI *plci;
14858 	DIVA_CAPI_ADAPTER *a;
14859 
14860 	for (i = 0, appls_found = 0; i < max_appl; i++)
14861 	{
14862 		if (application[i].Id && (application[i].Id != id))
14863 		{
14864 			appls_found++;                       /* an application has been found */
14865 		}
14866 	}
14867 
14868 	if (appls_found) return true;
14869 	for (i = 0; i < max_adapter; i++)                   /* scan all adapters...    */
14870 	{
14871 		a = &adapter[i];
14872 		if (a->request)
14873 		{
14874 			if (a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14875 			{
14876 				if (!appls_found)           /* first application does a capi register   */
14877 				{
14878 					if ((j = get_plci(a)))                    /* activate L1 of all adapters */
14879 					{
14880 						plci = &a->plci[j - 1];
14881 						plci->command = 0;
14882 						add_p(plci, OAD, "\x01\xfd");
14883 						add_p(plci, CAI, "\x01\x80");
14884 						add_p(plci, UID, "\x06\x43\x61\x70\x69\x32\x30");
14885 						add_p(plci, SHIFT | 6, NULL);
14886 						add_p(plci, SIN, "\x02\x00\x00");
14887 						plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14888 						sig_req(plci, ASSIGN, DSIG_ID);
14889 						add_p(plci, FTY, "\x02\xff\x07"); /* l1 start */
14890 						sig_req(plci, SIG_CTRL, 0);
14891 						send_req(plci);
14892 					}
14893 				}
14894 			}
14895 		}
14896 	}
14897 	return false;
14898 }
14899 
14900 /*------------------------------------------------------------------*/
14901 
14902 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14903 
VSwitchReqInd(PLCI * plci,dword Id,byte ** parms)14904 static void VSwitchReqInd(PLCI *plci, dword Id, byte **parms)
14905 {
14906 	word i;
14907 	/* Format of vswitch_t:
14908 	   0 byte length
14909 	   1 byte VSWITCHIE
14910 	   2 byte VSWITCH_REQ/VSWITCH_IND
14911 	   3 byte reserved
14912 	   4 word VSwitchcommand
14913 	   6 word returnerror
14914 	   8... Params
14915 	*/
14916 	if (!plci ||
14917 	    !plci->appl ||
14918 	    !plci->State ||
14919 	    plci->Sig.Ind == NCR_FACILITY
14920 		)
14921 		return;
14922 
14923 	for (i = 0; i < MAX_MULTI_IE; i++)
14924 	{
14925 		if (!parms[i][0]) continue;
14926 		if (parms[i][0] < 7)
14927 		{
14928 			parms[i][0] = 0; /* kill it */
14929 			continue;
14930 		}
14931 		dbug(1, dprintf("VSwitchReqInd(%d)", parms[i][4]));
14932 		switch (parms[i][4])
14933 		{
14934 		case VSJOIN:
14935 			if (!plci->relatedPTYPLCI ||
14936 			    (plci->ptyState != S_ECT && plci->relatedPTYPLCI->ptyState != S_ECT))
14937 			{ /* Error */
14938 				break;
14939 			}
14940 			/* remember all necessary informations */
14941 			if (parms[i][0] != 11 || parms[i][8] != 3) /* Length Test */
14942 			{
14943 				break;
14944 			}
14945 			if (parms[i][2] == VSWITCH_IND && parms[i][9] == 1)
14946 			{   /* first indication after ECT-Request on Consultation Call */
14947 				plci->vswitchstate = parms[i][9];
14948 				parms[i][9] = 2; /* State */
14949 				/* now ask first Call to join */
14950 			}
14951 			else if (parms[i][2] == VSWITCH_REQ && parms[i][9] == 3)
14952 			{ /* Answer of VSWITCH_REQ from first Call */
14953 				plci->vswitchstate = parms[i][9];
14954 				/* tell consultation call to join
14955 				   and the protocol capabilities of the first call */
14956 			}
14957 			else
14958 			{ /* Error */
14959 				break;
14960 			}
14961 			plci->vsprot = parms[i][10]; /* protocol */
14962 			plci->vsprotdialect = parms[i][11]; /* protocoldialect */
14963 			/* send join request to related PLCI */
14964 			parms[i][1] = VSWITCHIE;
14965 			parms[i][2] = VSWITCH_REQ;
14966 
14967 			plci->relatedPTYPLCI->command = 0;
14968 			plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14969 			add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14970 			sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14971 			send_req(plci->relatedPTYPLCI);
14972 			break;
14973 		case VSTRANSPORT:
14974 		default:
14975 			if (plci->relatedPTYPLCI &&
14976 			    plci->vswitchstate == 3 &&
14977 			    plci->relatedPTYPLCI->vswitchstate == 3)
14978 			{
14979 				add_p(plci->relatedPTYPLCI, ESC, &parms[i][0]);
14980 				sig_req(plci->relatedPTYPLCI, VSWITCH_REQ, 0);
14981 				send_req(plci->relatedPTYPLCI);
14982 			}
14983 			break;
14984 		}
14985 		parms[i][0] = 0; /* kill it */
14986 	}
14987 }
14988 
14989 
14990 /*------------------------------------------------------------------*/
14991 
diva_get_dma_descriptor(PLCI * plci,dword * dma_magic)14992 static int diva_get_dma_descriptor(PLCI *plci, dword   *dma_magic) {
14993 	ENTITY e;
14994 	IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
14995 
14996 	if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14997 		return (-1);
14998 	}
14999 
15000 	pReq->xdi_dma_descriptor_operation.Req = 0;
15001 	pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15002 
15003 	pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
15004 	pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
15005 	pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15006 	pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15007 
15008 	e.user[0] = plci->adapter->Id - 1;
15009 	plci->adapter->request((ENTITY *)pReq);
15010 
15011 	if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15012 	    (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15013 	    pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15014 		*dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15015 		dbug(3, dprintf("dma_alloc, a:%d (%d-%08x)",
15016 				plci->adapter->Id,
15017 				pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15018 				*dma_magic));
15019 		return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15020 	} else {
15021 		dbug(1, dprintf("dma_alloc failed"));
15022 		return (-1);
15023 	}
15024 }
15025 
diva_free_dma_descriptor(PLCI * plci,int nr)15026 static void diva_free_dma_descriptor(PLCI *plci, int nr) {
15027 	ENTITY e;
15028 	IDI_SYNC_REQ *pReq = (IDI_SYNC_REQ *)&e;
15029 
15030 	if (nr < 0) {
15031 		return;
15032 	}
15033 
15034 	pReq->xdi_dma_descriptor_operation.Req = 0;
15035 	pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15036 
15037 	pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15038 	pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
15039 	pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15040 	pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15041 
15042 	e.user[0] = plci->adapter->Id - 1;
15043 	plci->adapter->request((ENTITY *)pReq);
15044 
15045 	if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15046 		dbug(1, dprintf("dma_free(%d)", nr));
15047 	} else {
15048 		dbug(1, dprintf("dma_free failed (%d)", nr));
15049 	}
15050 }
15051 
15052 /*------------------------------------------------------------------*/
15053