Merge branch 'linux-next' of git://git.infradead.org/ubifs-2.6
[linux-2.6] / drivers / isdn / hardware / eicon / message.c
1 /*
2  *
3   Copyright (c) Eicon Networks, 2002.
4  *
5   This source file is supplied for the use with
6   Eicon Networks range of DIVA Server Adapters.
7  *
8   Eicon File Revision :    2.1
9  *
10   This program is free software; you can redistribute it and/or modify
11   it under the terms of the GNU General Public License as published by
12   the Free Software Foundation; either version 2, or (at your option)
13   any later version.
14  *
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
17   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18   See the GNU General Public License for more details.
19  *
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25
26
27
28
29
30 #include "platform.h"
31 #include "di_defs.h"
32 #include "pc.h"
33 #include "capi20.h"
34 #include "divacapi.h"
35 #include "mdm_msg.h"
36 #include "divasync.h"
37
38
39
40 #define FILE_ "MESSAGE.C"
41 #define dprintf
42
43
44
45
46
47
48
49
50
51 /*------------------------------------------------------------------*/
52 /* This is options supported for all adapters that are server by    */
53 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
54 /* and it is not necessary to save it separate for every adapter    */
55 /* Macrose defined here have only local meaning                     */
56 /*------------------------------------------------------------------*/
57 static dword diva_xdi_extended_features = 0;
58
59 #define DIVA_CAPI_USE_CMA                 0x00000001
60 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR  0x00000002
61 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL  0x00000004
62 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA     0x00000008
63
64 /*
65   CAPI can request to process all return codes self only if:
66   protocol code supports this && xdi supports this
67  */
68 #define DIVA_CAPI_SUPPORTS_NO_CANCEL(__a__)   (((__a__)->manufacturer_features&MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)&&    ((__a__)->manufacturer_features & MANUFACTURER_FEATURE_OK_FC_LABEL) &&     (diva_xdi_extended_features   & DIVA_CAPI_XDI_PROVIDES_NO_CANCEL))
69
70 /*------------------------------------------------------------------*/
71 /* local function prototypes                                        */
72 /*------------------------------------------------------------------*/
73
74 static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci);
75 static void set_group_ind_mask (PLCI   *plci);
76 static void clear_group_ind_mask_bit (PLCI   *plci, word b);
77 static byte test_group_ind_mask_bit (PLCI   *plci, word b);
78 void AutomaticLaw(DIVA_CAPI_ADAPTER   *);
79 word CapiRelease(word);
80 word CapiRegister(word);
81 word api_put(APPL   *, CAPI_MSG   *);
82 static word api_parse(byte   *, word, byte *, API_PARSE *);
83 static void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out);
84 static void api_load_msg(API_SAVE   *in, API_PARSE   *out);
85
86 word api_remove_start(void);
87 void api_remove_complete(void);
88
89 static void plci_remove(PLCI   *);
90 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a);
91 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  *, IDI_SYNC_REQ  *);
92
93 void   callback(ENTITY   *);
94
95 static void control_rc(PLCI   *, byte, byte, byte, byte, byte);
96 static void data_rc(PLCI   *, byte);
97 static void data_ack(PLCI   *, byte);
98 static void sig_ind(PLCI   *);
99 static void SendInfo(PLCI   *, dword, byte   * *, byte);
100 static void SendSetupInfo(APPL   *, PLCI   *, dword, byte   * *, byte);
101 static void SendSSExtInd(APPL   *, PLCI   * plci, dword Id, byte   * * parms);
102
103 static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms);
104
105 static void nl_ind(PLCI   *);
106
107 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
108 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
109 static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
110 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
111 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
112 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
113 static byte info_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
114 static byte info_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
115 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
116 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
117 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
118 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
119 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
120 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
121 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
122 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
123 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
124 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
125 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
126 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
127 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
128 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
129 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
130 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
131
132 static word get_plci(DIVA_CAPI_ADAPTER   *);
133 static void add_p(PLCI   *, byte, byte   *);
134 static void add_s(PLCI   * plci, byte code, API_PARSE * p);
135 static void add_ss(PLCI   * plci, byte code, API_PARSE * p);
136 static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length);
137 static void add_d(PLCI   *, word, byte   *);
138 static void add_ai(PLCI   *, API_PARSE *);
139 static word add_b1(PLCI   *, API_PARSE *, word, word);
140 static word add_b23(PLCI   *, API_PARSE *);
141 static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms);
142 static void sig_req(PLCI   *, byte, byte);
143 static void nl_req_ncci(PLCI   *, byte, byte);
144 static void send_req(PLCI   *);
145 static void send_data(PLCI   *);
146 static word plci_remove_check(PLCI   *);
147 static void listen_check(DIVA_CAPI_ADAPTER   *);
148 static byte AddInfo(byte   **, byte   **, byte   *, byte *);
149 static byte getChannel(API_PARSE *);
150 static void IndParse(PLCI   *, word *, byte   **, byte);
151 static byte ie_compare(byte   *, byte *);
152 static word find_cip(DIVA_CAPI_ADAPTER   *, byte   *, byte   *);
153 static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   *,word);
154
155 /*
156   XON protocol helpers
157   */
158 static void channel_flow_control_remove (PLCI   * plci);
159 static void channel_x_off (PLCI   * plci, byte ch, byte flag);
160 static void channel_x_on (PLCI   * plci, byte ch);
161 static void channel_request_xon (PLCI   * plci, byte ch);
162 static void channel_xmit_xon (PLCI   * plci);
163 static int channel_can_xon (PLCI   * plci, byte ch);
164 static void channel_xmit_extended_xon (PLCI   * plci);
165
166 static byte SendMultiIE(PLCI   * plci, dword Id, byte   * * parms, byte ie_type, dword info_mask, byte setupParse);
167 static word AdvCodecSupport(DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, byte);
168 static void CodecIdCheck(DIVA_CAPI_ADAPTER   *, PLCI   *);
169 static void SetVoiceChannel(PLCI   *, byte   *, DIVA_CAPI_ADAPTER   * );
170 static void VoiceChannelOff(PLCI   *plci);
171 static void adv_voice_write_coefs (PLCI   *plci, word write_command);
172 static void adv_voice_clear_config (PLCI   *plci);
173
174 static word get_b1_facilities (PLCI   * plci, byte b1_resource);
175 static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities);
176 static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities);
177 static word adjust_b_process (dword Id, PLCI   *plci, byte Rc);
178 static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command);
179 static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc);
180 static void reset_b3_command (dword Id, PLCI   *plci, byte Rc);
181 static void select_b_command (dword Id, PLCI   *plci, byte Rc);
182 static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc);
183 static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc);
184 static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc);
185 static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc);
186 static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc);
187 static void hold_save_command (dword Id, PLCI   *plci, byte Rc);
188 static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc);
189 static void init_b1_config (PLCI   *plci);
190 static void clear_b1_config (PLCI   *plci);
191
192 static void dtmf_command (dword Id, PLCI   *plci, byte Rc);
193 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
194 static void dtmf_confirmation (dword Id, PLCI   *plci);
195 static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length);
196 static void dtmf_parameter_write (PLCI   *plci);
197
198
199 static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id);
200 static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi);
201 static void mixer_clear_config (PLCI   *plci);
202 static void mixer_notify_update (PLCI   *plci, byte others);
203 static void mixer_command (dword Id, PLCI   *plci, byte Rc);
204 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
205 static void mixer_indication_coefs_set (dword Id, PLCI   *plci);
206 static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length);
207 static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length);
208 static void mixer_remove (PLCI   *plci);
209
210
211 static void ec_command (dword Id, PLCI   *plci, byte Rc);
212 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
213 static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length);
214
215
216 static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc);
217 static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc);
218
219
220 static int  diva_get_dma_descriptor  (PLCI   *plci, dword   *dma_magic);
221 static void diva_free_dma_descriptor (PLCI   *plci, int nr);
222
223 /*------------------------------------------------------------------*/
224 /* external function prototypes                                     */
225 /*------------------------------------------------------------------*/
226
227 extern byte MapController (byte);
228 extern byte UnMapController (byte);
229 #define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id)))
230 #define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id)))
231
232 void   sendf(APPL   *, word, dword, word, byte *, ...);
233 void   * TransmitBufferSet(APPL   * appl, dword ref);
234 void   * TransmitBufferGet(APPL   * appl, void   * p);
235 void TransmitBufferFree(APPL   * appl, void   * p);
236 void   * ReceiveBufferGet(APPL   * appl, int Num);
237
238 int fax_head_line_time (char *buffer);
239
240
241 /*------------------------------------------------------------------*/
242 /* Global data definitions                                          */
243 /*------------------------------------------------------------------*/
244 extern byte max_adapter;
245 extern byte max_appl;
246 extern DIVA_CAPI_ADAPTER   * adapter;
247 extern APPL   * application;
248
249
250
251
252
253
254
255 static byte remove_started = false;
256 static PLCI dummy_plci;
257
258
259 static struct _ftable {
260   word command;
261   byte * format;
262   byte (* function)(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
263 } ftable[] = {
264   {_DATA_B3_R,                          "dwww",         data_b3_req},
265   {_DATA_B3_I|RESPONSE,                 "w",            data_b3_res},
266   {_INFO_R,                             "ss",           info_req},
267   {_INFO_I|RESPONSE,                    "",             info_res},
268   {_CONNECT_R,                          "wsssssssss",   connect_req},
269   {_CONNECT_I|RESPONSE,                 "wsssss",       connect_res},
270   {_CONNECT_ACTIVE_I|RESPONSE,          "",             connect_a_res},
271   {_DISCONNECT_R,                       "s",            disconnect_req},
272   {_DISCONNECT_I|RESPONSE,              "",             disconnect_res},
273   {_LISTEN_R,                           "dddss",        listen_req},
274   {_ALERT_R,                            "s",            alert_req},
275   {_FACILITY_R,                         "ws",           facility_req},
276   {_FACILITY_I|RESPONSE,                "ws",           facility_res},
277   {_CONNECT_B3_R,                       "s",            connect_b3_req},
278   {_CONNECT_B3_I|RESPONSE,              "ws",           connect_b3_res},
279   {_CONNECT_B3_ACTIVE_I|RESPONSE,       "",             connect_b3_a_res},
280   {_DISCONNECT_B3_R,                    "s",            disconnect_b3_req},
281   {_DISCONNECT_B3_I|RESPONSE,           "",             disconnect_b3_res},
282   {_RESET_B3_R,                         "s",            reset_b3_req},
283   {_RESET_B3_I|RESPONSE,                "",             reset_b3_res},
284   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "ws",           connect_b3_t90_a_res},
285   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "",             connect_b3_t90_a_res},
286   {_SELECT_B_REQ,                       "s",            select_b_req},
287   {_MANUFACTURER_R,                     "dws",          manufacturer_req},
288   {_MANUFACTURER_I|RESPONSE,            "dws",          manufacturer_res},
289   {_MANUFACTURER_I|RESPONSE,            "",             manufacturer_res}
290 };
291
292 static byte * cip_bc[29][2] = {
293   { "",                     ""                     }, /* 0 */
294   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 1 */
295   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 2 */
296   { "\x02\x89\x90",         "\x02\x89\x90"         }, /* 3 */
297   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 4 */
298   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 5 */
299   { "\x02\x98\x90",         "\x02\x98\x90"         }, /* 6 */
300   { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
301   { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
302   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 9 */
303   { "",                     ""                     }, /* 10 */
304   { "",                     ""                     }, /* 11 */
305   { "",                     ""                     }, /* 12 */
306   { "",                     ""                     }, /* 13 */
307   { "",                     ""                     }, /* 14 */
308   { "",                     ""                     }, /* 15 */
309
310   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 16 */
311   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 17 */
312   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 18 */
313   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 19 */
314   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 20 */
315   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 21 */
316   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 22 */
317   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 23 */
318   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 24 */
319   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 25 */
320   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 26 */
321   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 27 */
322   { "\x02\x88\x90",         "\x02\x88\x90"         }  /* 28 */
323 };
324
325 static byte * cip_hlc[29] = {
326   "",                           /* 0 */
327   "",                           /* 1 */
328   "",                           /* 2 */
329   "",                           /* 3 */
330   "",                           /* 4 */
331   "",                           /* 5 */
332   "",                           /* 6 */
333   "",                           /* 7 */
334   "",                           /* 8 */
335   "",                           /* 9 */
336   "",                           /* 10 */
337   "",                           /* 11 */
338   "",                           /* 12 */
339   "",                           /* 13 */
340   "",                           /* 14 */
341   "",                           /* 15 */
342
343   "\x02\x91\x81",               /* 16 */
344   "\x02\x91\x84",               /* 17 */
345   "\x02\x91\xa1",               /* 18 */
346   "\x02\x91\xa4",               /* 19 */
347   "\x02\x91\xa8",               /* 20 */
348   "\x02\x91\xb1",               /* 21 */
349   "\x02\x91\xb2",               /* 22 */
350   "\x02\x91\xb5",               /* 23 */
351   "\x02\x91\xb8",               /* 24 */
352   "\x02\x91\xc1",               /* 25 */
353   "\x02\x91\x81",               /* 26 */
354   "\x03\x91\xe0\x01",           /* 27 */
355   "\x03\x91\xe0\x02"            /* 28 */
356 };
357
358 /*------------------------------------------------------------------*/
359
360 #define V120_HEADER_LENGTH 1
361 #define V120_HEADER_EXTEND_BIT  0x80
362 #define V120_HEADER_BREAK_BIT   0x40
363 #define V120_HEADER_C1_BIT      0x04
364 #define V120_HEADER_C2_BIT      0x08
365 #define V120_HEADER_FLUSH_COND  (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
366
367 static byte v120_default_header[] =
368 {
369
370   0x83                          /*  Ext, BR , res, res, C2 , C1 , B  , F   */
371
372 };
373
374 static byte v120_break_header[] =
375 {
376
377   0xc3 | V120_HEADER_BREAK_BIT  /*  Ext, BR , res, res, C2 , C1 , B  , F   */
378
379 };
380
381
382 /*------------------------------------------------------------------*/
383 /* API_PUT function                                                 */
384 /*------------------------------------------------------------------*/
385
386 word api_put(APPL   * appl, CAPI_MSG   * msg)
387 {
388   word i, j, k, l, n;
389   word ret;
390   byte c;
391   byte controller;
392   DIVA_CAPI_ADAPTER   * a;
393   PLCI   * plci;
394   NCCI   * ncci_ptr;
395   word ncci;
396   CAPI_MSG   *m;
397     API_PARSE msg_parms[MAX_MSG_PARMS+1];
398
399   if (msg->header.length < sizeof (msg->header) ||
400       msg->header.length > MAX_MSG_SIZE) {
401     dbug(1,dprintf("bad len"));
402     return _BAD_MSG;
403   }
404
405   controller = (byte)((msg->header.controller &0x7f)-1);
406
407   /* controller starts with 0 up to (max_adapter - 1) */
408   if ( controller >= max_adapter )
409   {
410     dbug(1,dprintf("invalid ctrl"));
411     return _BAD_MSG;
412   }
413   
414   a = &adapter[controller];
415   plci = NULL;
416   if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
417   {
418     dbug(1,dprintf("plci=%x",msg->header.plci));
419     plci = &a->plci[msg->header.plci-1];
420     ncci = GET_WORD(&msg->header.ncci);
421     if (plci->Id
422      && (plci->appl
423       || (plci->State == INC_CON_PENDING)
424       || (plci->State == INC_CON_ALERT)
425       || (msg->header.command == (_DISCONNECT_I|RESPONSE)))
426      && ((ncci == 0)
427       || (msg->header.command == (_DISCONNECT_B3_I|RESPONSE))
428       || ((ncci < MAX_NCCI+1) && (a->ncci_plci[ncci] == plci->Id))))
429     {
430       i = plci->msg_in_read_pos;
431       j = plci->msg_in_write_pos;
432       if (j >= i)
433       {
434         if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
435           i += MSG_IN_QUEUE_SIZE - j;
436         else
437           j = 0;
438       }
439       else
440       {
441
442         n = (((CAPI_MSG   *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
443
444         if (i > MSG_IN_QUEUE_SIZE - n)
445           i = MSG_IN_QUEUE_SIZE - n + 1;
446         i -= j;
447       }
448
449       if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
450
451       {
452         dbug(0,dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
453           msg->header.length, plci->msg_in_write_pos,
454           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
455
456         return _QUEUE_FULL;
457       }
458       c = false;
459       if ((((byte   *) msg) < ((byte   *)(plci->msg_in_queue)))
460        || (((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
461       {
462         if (plci->msg_in_write_pos != plci->msg_in_read_pos)
463           c = true;
464       }
465       if (msg->header.command == _DATA_B3_R)
466       {
467         if (msg->header.length < 20)
468         {
469           dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
470           return _BAD_MSG;
471         }
472         ncci_ptr = &(a->ncci[ncci]);
473         n = ncci_ptr->data_pending;
474         l = ncci_ptr->data_ack_pending;
475         k = plci->msg_in_read_pos;
476         while (k != plci->msg_in_write_pos)
477         {
478           if (k == plci->msg_in_wrap_pos)
479             k = 0;
480           if ((((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
481            && (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
482           {
483             n++;
484             if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
485               l++;
486           }
487
488           k += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.length +
489             MSG_IN_OVERHEAD + 3) & 0xfffc;
490
491         }
492         if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
493         {
494           dbug(0,dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
495                           ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
496
497           return _QUEUE_FULL;
498         }
499         if (plci->req_in || plci->internal_command)
500         {
501           if ((((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)))
502            && (((byte   *) msg) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
503           {
504             dbug(0,dprintf("Q-FULL3(requeue)"));
505
506             return _QUEUE_FULL;
507           }
508           c = true;
509         }
510       }
511       else
512       {
513         if (plci->req_in || plci->internal_command)
514           c = true;
515         else
516         {
517           plci->command = msg->header.command;
518           plci->number = msg->header.number;
519         }
520       }
521       if (c)
522       {
523         dbug(1,dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
524           msg->header.command, plci->req_in, plci->internal_command,
525           msg->header.length, plci->msg_in_write_pos,
526           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
527         if (j == 0)
528           plci->msg_in_wrap_pos = plci->msg_in_write_pos;
529         m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
530         for (i = 0; i < msg->header.length; i++)
531           ((byte   *)(plci->msg_in_queue))[j++] = ((byte   *) msg)[i];
532         if (m->header.command == _DATA_B3_R)
533         {
534
535           m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
536
537         }
538
539         j = (j + 3) & 0xfffc;
540
541         *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j])) = appl;
542         plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
543         return 0;
544       }
545     }
546     else
547     {
548       plci = NULL;
549     }
550   }
551   dbug(1,dprintf("com=%x",msg->header.command));
552
553   for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
554   for(i=0, ret = _BAD_MSG;
555       i<(sizeof(ftable)/sizeof(struct _ftable));
556       i++) {
557
558     if(ftable[i].command==msg->header.command) {
559       /* break loop if the message is correct, otherwise continue scan  */
560       /* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */
561       if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
562         ret = 0;
563         break;
564       }
565       for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
566     }
567   }
568   if(ret) {
569     dbug(1,dprintf("BAD_MSG"));
570     if(plci) plci->command = 0;
571     return ret;
572   }
573
574
575   c = ftable[i].function(GET_DWORD(&msg->header.controller),
576                          msg->header.number,
577                          a,
578                          plci,
579                          appl,
580                          msg_parms);
581
582   channel_xmit_extended_xon (plci);
583
584   if(c==1) send_req(plci);
585   if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
586   if(plci && !plci->req_in) plci->command = 0;
587   return 0;
588 }
589
590
591 /*------------------------------------------------------------------*/
592 /* api_parse function, check the format of api messages             */
593 /*------------------------------------------------------------------*/
594
595 static word api_parse(byte *msg, word length, byte *format, API_PARSE *parms)
596 {
597   word i;
598   word p;
599
600   for(i=0,p=0; format[i]; i++) {
601     if(parms)
602     {
603       parms[i].info = &msg[p];
604     }
605     switch(format[i]) {
606     case 'b':
607       p +=1;
608       break;
609     case 'w':
610       p +=2;
611       break;
612     case 'd':
613       p +=4;
614       break;
615     case 's':
616       if(msg[p]==0xff) {
617         parms[i].info +=2;
618         parms[i].length = msg[p+1] + (msg[p+2]<<8);
619         p +=(parms[i].length +3);
620       }
621       else {
622         parms[i].length = msg[p];
623         p +=(parms[i].length +1);
624       }
625       break;
626     }
627
628     if(p>length) return true;
629   }
630   if(parms) parms[i].info = NULL;
631   return false;
632 }
633
634 static void api_save_msg(API_PARSE *in, byte *format, API_SAVE *out)
635 {
636   word i, j, n = 0;
637   byte   *p;
638
639   p = out->info;
640   for (i = 0; format[i] != '\0'; i++)
641   {
642     out->parms[i].info = p;
643     out->parms[i].length = in[i].length;
644     switch (format[i])
645     {
646     case 'b':
647       n = 1;
648       break;
649     case 'w':
650       n = 2;
651       break;
652     case 'd':
653       n = 4;
654       break;
655     case 's':
656       n = in[i].length + 1;
657       break;
658     }
659     for (j = 0; j < n; j++)
660       *(p++) = in[i].info[j];
661   }
662   out->parms[i].info = NULL;
663   out->parms[i].length = 0;
664 }
665
666 static void api_load_msg(API_SAVE *in, API_PARSE *out)
667 {
668   word i;
669
670   i = 0;
671   do
672   {
673     out[i].info = in->parms[i].info;
674     out[i].length = in->parms[i].length;
675   } while (in->parms[i++].info);
676 }
677
678
679 /*------------------------------------------------------------------*/
680 /* CAPI remove function                                             */
681 /*------------------------------------------------------------------*/
682
683 word api_remove_start(void)
684 {
685   word i;
686   word j;
687
688   if(!remove_started) {
689     remove_started = true;
690     for(i=0;i<max_adapter;i++) {
691       if(adapter[i].request) {
692         for(j=0;j<adapter[i].max_plci;j++) {
693           if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
694         }
695       }
696     }
697     return 1;
698   }
699   else {
700     for(i=0;i<max_adapter;i++) {
701       if(adapter[i].request) {
702         for(j=0;j<adapter[i].max_plci;j++) {
703           if(adapter[i].plci[j].Sig.Id) return 1;
704         }
705       }
706     }
707   }
708   api_remove_complete();
709   return 0;
710 }
711
712
713 /*------------------------------------------------------------------*/
714 /* internal command queue                                           */
715 /*------------------------------------------------------------------*/
716
717 static void init_internal_command_queue (PLCI   *plci)
718 {
719   word i;
720
721   dbug (1, dprintf ("%s,%d: init_internal_command_queue",
722     (char   *)(FILE_), __LINE__));
723
724   plci->internal_command = 0;
725   for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
726     plci->internal_command_queue[i] = NULL;
727 }
728
729
730 static void start_internal_command (dword Id, PLCI   *plci, t_std_internal_command command_function)
731 {
732   word i;
733
734   dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
735     UnMapId (Id), (char   *)(FILE_), __LINE__));
736
737   if (plci->internal_command == 0)
738   {
739     plci->internal_command_queue[0] = command_function;
740     (* command_function)(Id, plci, OK);
741   }
742   else
743   {
744     i = 1;
745     while (plci->internal_command_queue[i] != NULL)
746       i++;
747     plci->internal_command_queue[i] = command_function;
748   }
749 }
750
751
752 static void next_internal_command (dword Id, PLCI   *plci)
753 {
754   word i;
755
756   dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
757     UnMapId (Id), (char   *)(FILE_), __LINE__));
758
759   plci->internal_command = 0;
760   plci->internal_command_queue[0] = NULL;
761   while (plci->internal_command_queue[1] != NULL)
762   {
763     for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
764       plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
765     plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
766     (*(plci->internal_command_queue[0]))(Id, plci, OK);
767     if (plci->internal_command != 0)
768       return;
769     plci->internal_command_queue[0] = NULL;
770   }
771 }
772
773
774 /*------------------------------------------------------------------*/
775 /* NCCI allocate/remove function                                    */
776 /*------------------------------------------------------------------*/
777
778 static dword ncci_mapping_bug = 0;
779
780 static word get_ncci (PLCI   *plci, byte ch, word force_ncci)
781 {
782   DIVA_CAPI_ADAPTER   *a;
783   word ncci, i, j, k;
784
785   a = plci->adapter;
786   if (!ch || a->ch_ncci[ch])
787   {
788     ncci_mapping_bug++;
789     dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
790       ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
791     ncci = ch;
792   }
793   else
794   {
795     if (force_ncci)
796       ncci = force_ncci;
797     else
798     {
799       if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
800         ncci = ch;
801       else
802       {
803         ncci = 1;
804         while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
805           ncci++;
806         if (ncci == MAX_NCCI+1)
807         {
808           ncci_mapping_bug++;
809           i = 1;
810           do
811           {
812             j = 1;
813             while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
814               j++;
815             k = j;
816             if (j < MAX_NCCI+1)
817             {
818               do
819               {
820                 j++;
821               } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
822             }
823           } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
824           if (i < MAX_NL_CHANNEL+1)
825           {
826             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
827               ncci_mapping_bug, ch, force_ncci, i, k, j));
828           }
829           else
830           {
831             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
832               ncci_mapping_bug, ch, force_ncci));
833           }
834           ncci = ch;
835         }
836       }
837       a->ncci_plci[ncci] = plci->Id;
838       a->ncci_state[ncci] = IDLE;
839       if (!plci->ncci_ring_list)
840         plci->ncci_ring_list = ncci;
841       else
842         a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
843       a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
844     }
845     a->ncci_ch[ncci] = ch;
846     a->ch_ncci[ch] = (byte) ncci;
847     dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
848       ncci_mapping_bug, ch, force_ncci, ch, ncci));
849   }
850   return (ncci);
851 }
852
853
854 static void ncci_free_receive_buffers (PLCI   *plci, word ncci)
855 {
856   DIVA_CAPI_ADAPTER   *a;
857   APPL   *appl;
858   word i, ncci_code;
859   dword Id;
860
861   a = plci->adapter;
862   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
863   if (ncci)
864   {
865     if (a->ncci_plci[ncci] == plci->Id)
866     {
867       if (!plci->appl)
868       {
869         ncci_mapping_bug++;
870         dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
871           ncci_mapping_bug, Id));
872       }
873       else
874       {
875         appl = plci->appl;
876         ncci_code = ncci | (((word) a->Id) << 8);
877         for (i = 0; i < appl->MaxBuffer; i++)
878         {
879           if ((appl->DataNCCI[i] == ncci_code)
880            && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
881           {
882             appl->DataNCCI[i] = 0;
883           }
884         }
885       }
886     }
887   }
888   else
889   {
890     for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
891     {
892       if (a->ncci_plci[ncci] == plci->Id)
893       {
894         if (!plci->appl)
895         {
896           ncci_mapping_bug++;
897           dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
898             ncci_mapping_bug, Id));
899         }
900         else
901         {
902           appl = plci->appl;
903           ncci_code = ncci | (((word) a->Id) << 8);
904           for (i = 0; i < appl->MaxBuffer; i++)
905           {
906             if ((appl->DataNCCI[i] == ncci_code)
907              && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
908             {
909               appl->DataNCCI[i] = 0;
910             }
911           }
912         }
913       }
914     }
915   }
916 }
917
918
919 static void cleanup_ncci_data (PLCI   *plci, word ncci)
920 {
921   NCCI   *ncci_ptr;
922
923   if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
924   {
925     ncci_ptr = &(plci->adapter->ncci[ncci]);
926     if (plci->appl)
927     {
928       while (ncci_ptr->data_pending != 0)
929       {
930         if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
931           TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
932         (ncci_ptr->data_out)++;
933         if (ncci_ptr->data_out == MAX_DATA_B3)
934           ncci_ptr->data_out = 0;
935         (ncci_ptr->data_pending)--;
936       }
937     }
938     ncci_ptr->data_out = 0;
939     ncci_ptr->data_pending = 0;
940     ncci_ptr->data_ack_out = 0;
941     ncci_ptr->data_ack_pending = 0;
942   }
943 }
944
945
946 static void ncci_remove (PLCI   *plci, word ncci, byte preserve_ncci)
947 {
948   DIVA_CAPI_ADAPTER   *a;
949   dword Id;
950   word i;
951
952   a = plci->adapter;
953   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
954   if (!preserve_ncci)
955     ncci_free_receive_buffers (plci, ncci);
956   if (ncci)
957   {
958     if (a->ncci_plci[ncci] != plci->Id)
959     {
960       ncci_mapping_bug++;
961       dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
962         ncci_mapping_bug, Id, preserve_ncci));
963     }
964     else
965     {
966       cleanup_ncci_data (plci, ncci);
967       dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
968         ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
969       a->ch_ncci[a->ncci_ch[ncci]] = 0;
970       if (!preserve_ncci)
971       {
972         a->ncci_ch[ncci] = 0;
973         a->ncci_plci[ncci] = 0;
974         a->ncci_state[ncci] = IDLE;
975         i = plci->ncci_ring_list;
976         while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
977           i = a->ncci_next[i];
978         if ((i != 0) && (a->ncci_next[i] == ncci))
979         {
980           if (i == ncci)
981             plci->ncci_ring_list = 0;
982           else if (plci->ncci_ring_list == ncci)
983             plci->ncci_ring_list = i;
984           a->ncci_next[i] = a->ncci_next[ncci];
985         }
986         a->ncci_next[ncci] = 0;
987       }
988     }
989   }
990   else
991   {
992     for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
993     {
994       if (a->ncci_plci[ncci] == plci->Id)
995       {
996         cleanup_ncci_data (plci, ncci);
997         dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
998           ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
999         a->ch_ncci[a->ncci_ch[ncci]] = 0;
1000         if (!preserve_ncci)
1001         {
1002           a->ncci_ch[ncci] = 0;
1003           a->ncci_plci[ncci] = 0;
1004           a->ncci_state[ncci] = IDLE;
1005           a->ncci_next[ncci] = 0;
1006         }
1007       }
1008     }
1009     if (!preserve_ncci)
1010       plci->ncci_ring_list = 0;
1011   }
1012 }
1013
1014
1015 /*------------------------------------------------------------------*/
1016 /* PLCI remove function                                             */
1017 /*------------------------------------------------------------------*/
1018
1019 static void plci_free_msg_in_queue (PLCI   *plci)
1020 {
1021   word i;
1022
1023   if (plci->appl)
1024   {
1025     i = plci->msg_in_read_pos;
1026     while (i != plci->msg_in_write_pos)
1027     {
1028       if (i == plci->msg_in_wrap_pos)
1029         i = 0;
1030       if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1031       {
1032
1033         TransmitBufferFree (plci->appl,
1034           (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1035
1036       }
1037
1038       i += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.length +
1039         MSG_IN_OVERHEAD + 3) & 0xfffc;
1040
1041     }
1042   }
1043   plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1044   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1045   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1046 }
1047
1048
1049 static void plci_remove(PLCI   * plci)
1050 {
1051
1052   if(!plci) {
1053     dbug(1,dprintf("plci_remove(no plci)"));
1054     return;
1055   }
1056   init_internal_command_queue (plci);
1057   dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1058   if(plci_remove_check(plci))
1059   {
1060     return;
1061   }
1062   if (plci->Sig.Id == 0xff)
1063   {
1064     dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1065     if (plci->NL.Id && !plci->nl_remove_id)
1066     {
1067       nl_req_ncci(plci,REMOVE,0);
1068       send_req(plci);
1069     }
1070   }
1071   else
1072   {
1073     if (!plci->sig_remove_id
1074      && (plci->Sig.Id
1075       || (plci->req_in!=plci->req_out)
1076       || (plci->nl_req || plci->sig_req)))
1077     {
1078       sig_req(plci,HANGUP,0);
1079       send_req(plci);
1080     }
1081   }
1082   ncci_remove (plci, 0, false);
1083   plci_free_msg_in_queue (plci);
1084
1085   plci->channels = 0;
1086   plci->appl = NULL;
1087   if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1088     plci->State = OUTG_DIS_PENDING;
1089 }
1090
1091 /*------------------------------------------------------------------*/
1092 /* Application Group function helpers                               */
1093 /*------------------------------------------------------------------*/
1094
1095 static void set_group_ind_mask (PLCI   *plci)
1096 {
1097   word i;
1098
1099   for (i = 0; i < C_IND_MASK_DWORDS; i++)
1100     plci->group_optimization_mask_table[i] = 0xffffffffL;
1101 }
1102
1103 static void clear_group_ind_mask_bit (PLCI   *plci, word b)
1104 {
1105   plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1106 }
1107
1108 static byte test_group_ind_mask_bit (PLCI   *plci, word b)
1109 {
1110   return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1111 }
1112
1113 /*------------------------------------------------------------------*/
1114 /* c_ind_mask operations for arbitrary MAX_APPL                     */
1115 /*------------------------------------------------------------------*/
1116
1117 static void clear_c_ind_mask (PLCI   *plci)
1118 {
1119   word i;
1120
1121   for (i = 0; i < C_IND_MASK_DWORDS; i++)
1122     plci->c_ind_mask_table[i] = 0;
1123 }
1124
1125 static byte c_ind_mask_empty (PLCI   *plci)
1126 {
1127   word i;
1128
1129   i = 0;
1130   while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1131     i++;
1132   return (i == C_IND_MASK_DWORDS);
1133 }
1134
1135 static void set_c_ind_mask_bit (PLCI   *plci, word b)
1136 {
1137   plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1138 }
1139
1140 static void clear_c_ind_mask_bit (PLCI   *plci, word b)
1141 {
1142   plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1143 }
1144
1145 static byte test_c_ind_mask_bit (PLCI   *plci, word b)
1146 {
1147   return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1148 }
1149
1150 static void dump_c_ind_mask (PLCI   *plci)
1151 {
1152 static char hex_digit_table[0x10] =
1153   {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1154   word i, j, k;
1155   dword d;
1156     char *p;
1157     char buf[40];
1158
1159   for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1160   {
1161     p = buf + 36;
1162     *p = '\0';
1163     for (j = 0; j < 4; j++)
1164     {
1165       if (i+j < C_IND_MASK_DWORDS)
1166       {
1167         d = plci->c_ind_mask_table[i+j];
1168         for (k = 0; k < 8; k++)
1169         {
1170           *(--p) = hex_digit_table[d & 0xf];
1171           d >>= 4;
1172         }
1173       }
1174       else if (i != 0)
1175       {
1176         for (k = 0; k < 8; k++)
1177           *(--p) = ' ';
1178       }
1179       *(--p) = ' ';
1180     }
1181     dbug(1,dprintf ("c_ind_mask =%s", (char   *) p));
1182   }
1183 }
1184
1185
1186
1187
1188
1189 #define dump_plcis(a)
1190
1191
1192
1193 /*------------------------------------------------------------------*/
1194 /* translation function for each message                            */
1195 /*------------------------------------------------------------------*/
1196
1197 static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1198                         PLCI *plci, APPL *appl, API_PARSE *parms)
1199 {
1200   word ch;
1201   word i;
1202   word Info;
1203   word CIP;
1204   byte LinkLayer;
1205   API_PARSE * ai;
1206   API_PARSE * bp;
1207     API_PARSE ai_parms[5];
1208   word channel = 0;
1209   dword ch_mask;
1210   byte m;
1211   static byte esc_chi[35] = {0x02,0x18,0x01};
1212   static byte lli[2] = {0x01,0x00};
1213   byte noCh = 0;
1214   word dir = 0;
1215   byte   *p_chi = "";
1216
1217   for(i=0;i<5;i++) ai_parms[i].length = 0;
1218
1219   dbug(1,dprintf("connect_req(%d)",parms->length));
1220   Info = _WRONG_IDENTIFIER;
1221   if(a)
1222   {
1223     if(a->adapter_disabled)
1224     {
1225       dbug(1,dprintf("adapter disabled"));
1226       Id = ((word)1<<8)|a->Id;
1227       sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
1228       sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
1229       return false;
1230     }
1231     Info = _OUT_OF_PLCI;
1232     if((i=get_plci(a)))
1233     {
1234       Info = 0;
1235       plci = &a->plci[i-1];
1236       plci->appl = appl;
1237       plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
1238       /* check 'external controller' bit for codec support */
1239       if(Id & EXT_CONTROLLER)
1240       {
1241         if(AdvCodecSupport(a, plci, appl, 0) )
1242         {
1243           plci->Id = 0;
1244           sendf(appl, _CONNECT_R|CONFIRM, Id, Number, "w", _WRONG_IDENTIFIER);
1245           return 2;
1246         }
1247       }
1248       ai = &parms[9];
1249       bp = &parms[5];
1250       ch = 0;
1251       if(bp->length)LinkLayer = bp->info[3];
1252       else LinkLayer = 0;
1253       if(ai->length)
1254       {
1255         ch=0xffff;
1256         if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1257         {
1258           ch = 0;
1259           if(ai_parms[0].length)
1260           {
1261             ch = GET_WORD(ai_parms[0].info+1);
1262             if(ch>4) ch=0; /* safety -> ignore ChannelID */
1263             if(ch==4) /* explizit CHI in message */
1264             {
1265               /* check length of B-CH struct */
1266               if((ai_parms[0].info)[3]>=1)
1267               {
1268                 if((ai_parms[0].info)[4]==CHI)
1269                 {
1270                   p_chi = &((ai_parms[0].info)[5]);
1271                 }
1272                 else
1273                 {
1274                   p_chi = &((ai_parms[0].info)[3]);
1275                 }
1276                 if(p_chi[0]>35) /* check length of channel ID */
1277                 {
1278                   Info = _WRONG_MESSAGE_FORMAT;    
1279                 }
1280               }
1281               else Info = _WRONG_MESSAGE_FORMAT;    
1282             }
1283
1284             if(ch==3 && ai_parms[0].length>=7 && ai_parms[0].length<=36)
1285             {
1286               dir = GET_WORD(ai_parms[0].info+3);
1287               ch_mask = 0;
1288               m = 0x3f;
1289               for(i=0; i+5<=ai_parms[0].length; i++)
1290               {
1291                 if(ai_parms[0].info[i+5]!=0)
1292                 {
1293                   if((ai_parms[0].info[i+5] | m) != 0xff)
1294                     Info = _WRONG_MESSAGE_FORMAT;
1295                   else
1296                   {
1297                     if (ch_mask == 0)
1298                       channel = i;
1299                     ch_mask |= 1L << i;
1300                   }
1301                 }
1302                 m = 0;
1303               }
1304               if (ch_mask == 0)
1305                 Info = _WRONG_MESSAGE_FORMAT;
1306               if (!Info)
1307               {
1308                 if ((ai_parms[0].length == 36) || (ch_mask != ((dword)(1L << channel))))
1309                 {
1310                   esc_chi[0] = (byte)(ai_parms[0].length - 2);
1311                   for(i=0; i+5<=ai_parms[0].length; i++)
1312                     esc_chi[i+3] = ai_parms[0].info[i+5];
1313                 }
1314                 else
1315                   esc_chi[0] = 2;
1316                 esc_chi[2] = (byte)channel;
1317                 plci->b_channel = (byte)channel; /* not correct for ETSI ch 17..31 */
1318                 add_p(plci,LLI,lli);
1319                 add_p(plci,ESC,esc_chi);
1320                 plci->State = LOCAL_CONNECT;
1321                 if(!dir) plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;     /* dir 0=DTE, 1=DCE */
1322               }
1323             }
1324           }
1325         }
1326         else  Info = _WRONG_MESSAGE_FORMAT;
1327       }
1328
1329       dbug(1,dprintf("ch=%x,dir=%x,p_ch=%d",ch,dir,channel));
1330       plci->command = _CONNECT_R;
1331       plci->number = Number;
1332       /* x.31 or D-ch free SAPI in LinkLayer? */
1333       if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
1334       if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
1335       {
1336         /* B-channel used for B3 connections (ch==0), or no B channel    */
1337         /* is used (ch==2) or perm. connection (3) is used  do a CALL    */
1338         if(noCh) Info = add_b1(plci,&parms[5],2,0);    /* no resource    */
1339         else     Info = add_b1(plci,&parms[5],ch,0); 
1340         add_s(plci,OAD,&parms[2]);
1341         add_s(plci,OSA,&parms[4]);
1342         add_s(plci,BC,&parms[6]);
1343         add_s(plci,LLC,&parms[7]);
1344         add_s(plci,HLC,&parms[8]);
1345         CIP = GET_WORD(parms[0].info);
1346         if (a->Info_Mask[appl->Id-1] & 0x200)
1347         {
1348           /* early B3 connect (CIP mask bit 9) no release after a disc */
1349           add_p(plci,LLI,"\x01\x01");
1350         }
1351         if(GET_WORD(parms[0].info)<29) {
1352           add_p(plci,BC,cip_bc[GET_WORD(parms[0].info)][a->u_law]);
1353           add_p(plci,HLC,cip_hlc[GET_WORD(parms[0].info)]);
1354         }
1355         add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1356         sig_req(plci,ASSIGN,DSIG_ID);
1357       }
1358       else if(ch==1) {
1359
1360         /* D-Channel used for B3 connections */
1361         plci->Sig.Id = 0xff;
1362         Info = 0;
1363       }
1364
1365       if(!Info && ch!=2 && !noCh ) {
1366         Info = add_b23(plci,&parms[5]);
1367         if(!Info) {
1368           if(!(plci->tel && !plci->adv_nl))nl_req_ncci(plci,ASSIGN,0);
1369         }
1370       }
1371
1372       if(!Info)
1373       {
1374         if(ch==0 || ch==2 || ch==3 || noCh || ch==4)
1375         {
1376           if(plci->spoofed_msg==SPOOFING_REQUIRED)
1377           {
1378             api_save_msg(parms, "wsssssssss", &plci->saved_msg);
1379             plci->spoofed_msg = CALL_REQ;
1380             plci->internal_command = BLOCK_PLCI;
1381             plci->command = 0;
1382             dbug(1,dprintf("Spoof"));
1383             send_req(plci);
1384             return false;
1385           }
1386           if(ch==4)add_p(plci,CHI,p_chi);
1387           add_s(plci,CPN,&parms[1]);
1388           add_s(plci,DSA,&parms[3]);
1389           if(noCh) add_p(plci,ESC,"\x02\x18\xfd");  /* D-channel, no B-L3 */
1390           add_ai(plci,&parms[9]);
1391           if(!dir)sig_req(plci,CALL_REQ,0);
1392           else
1393           {
1394             plci->command = PERM_LIST_REQ;
1395             plci->appl = appl;
1396             sig_req(plci,LISTEN_REQ,0);
1397             send_req(plci);
1398             return false;
1399           }
1400         }
1401         send_req(plci);
1402         return false;
1403       }
1404       plci->Id = 0;
1405     }
1406   }
1407   sendf(appl,
1408         _CONNECT_R|CONFIRM,
1409         Id,
1410         Number,
1411         "w",Info);
1412   return 2;
1413 }
1414
1415 static byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1416                         PLCI *plci, APPL *appl, API_PARSE *parms)
1417 {
1418   word i, Info;
1419   word Reject;
1420   static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
1421   static byte esc_t[] = {0x03,0x08,0x00,0x00};
1422   API_PARSE * ai;
1423     API_PARSE ai_parms[5];
1424   word ch=0;
1425
1426   if(!plci) {
1427     dbug(1,dprintf("connect_res(no plci)"));
1428     return 0;  /* no plci, no send */
1429   }
1430
1431   dbug(1,dprintf("connect_res(State=0x%x)",plci->State));
1432   for(i=0;i<5;i++) ai_parms[i].length = 0;
1433   ai = &parms[5];
1434   dbug(1,dprintf("ai->length=%d",ai->length));
1435
1436   if(ai->length)
1437   {
1438     if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1439     {
1440       dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1)));
1441       ch = 0;
1442       if(ai_parms[0].length)
1443       {
1444         ch = GET_WORD(ai_parms[0].info+1);
1445         dbug(1,dprintf("BCH-I=0x%x",ch));
1446       }
1447     }
1448   }
1449
1450   if(plci->State==INC_CON_CONNECTED_ALERT)
1451   {
1452     dbug(1,dprintf("Connected Alert Call_Res"));
1453     if (a->Info_Mask[appl->Id-1] & 0x200)
1454     {
1455     /* early B3 connect (CIP mask bit 9) no release after a disc */
1456       add_p(plci,LLI,"\x01\x01");
1457     }
1458     add_s(plci, CONN_NR, &parms[2]);
1459     add_s(plci, LLC, &parms[4]);
1460     add_ai(plci, &parms[5]);
1461     plci->State = INC_CON_ACCEPT;
1462     sig_req(plci, CALL_RES,0);
1463     return 1;
1464   }
1465   else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) {
1466     clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1467     dump_c_ind_mask (plci);
1468     Reject = GET_WORD(parms[0].info);
1469     dbug(1,dprintf("Reject=0x%x",Reject));
1470     if(Reject) 
1471     {
1472       if(c_ind_mask_empty (plci)) 
1473       {
1474         if((Reject&0xff00)==0x3400) 
1475         {
1476           esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80;
1477           add_p(plci,ESC,esc_t);
1478           add_ai(plci, &parms[5]);
1479           sig_req(plci,REJECT,0);
1480         }      
1481         else if(Reject==1 || Reject>9) 
1482         {
1483           add_ai(plci, &parms[5]);
1484           sig_req(plci,HANGUP,0);
1485         }
1486         else 
1487         {
1488           esc_t[2] = cau_t[(Reject&0x000f)];
1489           add_p(plci,ESC,esc_t);
1490           add_ai(plci, &parms[5]);
1491           sig_req(plci,REJECT,0);
1492         }
1493         plci->appl = appl;
1494       }
1495       else 
1496       {
1497         sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1498       }
1499     }
1500     else {
1501       plci->appl = appl;
1502       if(Id & EXT_CONTROLLER){
1503         if(AdvCodecSupport(a, plci, appl, 0)){
1504           dbug(1,dprintf("connect_res(error from AdvCodecSupport)"));
1505           sig_req(plci,HANGUP,0);
1506           return 1;
1507         }
1508         if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1509         {
1510           Info = add_b23(plci, &parms[1]);
1511           if (Info)
1512           {
1513             dbug(1,dprintf("connect_res(error from add_b23)"));
1514             sig_req(plci,HANGUP,0);
1515             return 1;
1516           }
1517           if(plci->adv_nl)
1518           {
1519             nl_req_ncci(plci, ASSIGN, 0);
1520           }
1521         }
1522       }
1523       else
1524       {
1525         plci->tel = 0;
1526         if(ch!=2)
1527         {
1528           Info = add_b23(plci, &parms[1]);
1529           if (Info)
1530           {
1531             dbug(1,dprintf("connect_res(error from add_b23 2)"));
1532             sig_req(plci,HANGUP,0);
1533             return 1;
1534           }
1535         }
1536         nl_req_ncci(plci, ASSIGN, 0);
1537       }
1538
1539       if(plci->spoofed_msg==SPOOFING_REQUIRED)
1540       {
1541         api_save_msg(parms, "wsssss", &plci->saved_msg);
1542         plci->spoofed_msg = CALL_RES;
1543         plci->internal_command = BLOCK_PLCI;
1544         plci->command = 0;
1545         dbug(1,dprintf("Spoof"));
1546       }
1547       else
1548       {
1549         add_b1 (plci, &parms[1], ch, plci->B1_facilities);
1550         if (a->Info_Mask[appl->Id-1] & 0x200)
1551         {
1552           /* early B3 connect (CIP mask bit 9) no release after a disc */
1553           add_p(plci,LLI,"\x01\x01");
1554         }
1555         add_s(plci, CONN_NR, &parms[2]);
1556         add_s(plci, LLC, &parms[4]);
1557         add_ai(plci, &parms[5]);
1558         plci->State = INC_CON_ACCEPT;
1559         sig_req(plci, CALL_RES,0);
1560       }
1561
1562       for(i=0; i<max_appl; i++) {
1563         if(test_c_ind_mask_bit (plci, i)) {
1564           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1565         }
1566       }
1567     }
1568   }
1569   return 1;
1570 }
1571
1572 static byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1573                           PLCI *plci, APPL *appl, API_PARSE *msg)
1574 {
1575   dbug(1,dprintf("connect_a_res"));
1576   return false;
1577 }
1578
1579 static byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1580                            PLCI *plci, APPL *appl, API_PARSE *msg)
1581 {
1582   word Info;
1583   word i;
1584
1585   dbug(1,dprintf("disconnect_req"));
1586
1587   Info = _WRONG_IDENTIFIER;
1588
1589   if(plci)
1590   {
1591     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1592     {
1593       clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1594       plci->appl = appl;
1595       for(i=0; i<max_appl; i++)
1596       {
1597         if(test_c_ind_mask_bit (plci, i))
1598           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1599       }
1600       plci->State = OUTG_DIS_PENDING;
1601     }
1602     if(plci->Sig.Id && plci->appl)
1603     {
1604       Info = 0;
1605         if(plci->Sig.Id!=0xff)
1606         {
1607           if(plci->State!=INC_DIS_PENDING)
1608           {
1609             add_ai(plci, &msg[0]);
1610             sig_req(plci,HANGUP,0);
1611             plci->State = OUTG_DIS_PENDING;
1612             return 1;
1613           }
1614         }
1615         else
1616         {
1617           if (plci->NL.Id && !plci->nl_remove_id)
1618           {
1619             mixer_remove (plci);
1620             nl_req_ncci(plci,REMOVE,0);
1621           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1622           sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1623           plci->State = INC_DIS_PENDING;
1624           }
1625           return 1;
1626         }
1627       }
1628     }
1629
1630   if(!appl)  return false;
1631   sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
1632   return false;
1633 }
1634
1635 static byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1636                            PLCI *plci, APPL *appl, API_PARSE *msg)
1637 {
1638   dbug(1,dprintf("disconnect_res"));
1639   if(plci)
1640   {
1641         /* clear ind mask bit, just in case of collsion of          */
1642         /* DISCONNECT_IND and CONNECT_RES                           */
1643     clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1644     ncci_free_receive_buffers (plci, 0);
1645     if(plci_remove_check(plci))
1646     {
1647       return 0;
1648     }
1649     if(plci->State==INC_DIS_PENDING
1650     || plci->State==SUSPENDING) {
1651       if(c_ind_mask_empty (plci)) {
1652         if(plci->State!=SUSPENDING)plci->State = IDLE;
1653         dbug(1,dprintf("chs=%d",plci->channels));
1654         if(!plci->channels) {
1655           plci_remove(plci);
1656         }
1657       }
1658     }
1659   }
1660   return 0;
1661 }
1662
1663 static byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1664                        PLCI *plci, APPL *appl, API_PARSE *parms)
1665 {
1666   word Info;
1667   byte i;
1668
1669   dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1670
1671   Info = _WRONG_IDENTIFIER;
1672   if(a) {
1673     Info = 0;
1674     a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
1675     a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
1676     dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
1677     if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1678       a->Info_Mask[appl->Id-1] |=  0x10;   /* call progression infos    */
1679     }
1680
1681     /* check if external controller listen and switch listen on or off*/
1682     if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
1683       if(a->profile.Global_Options & ON_BOARD_CODEC) {
1684         dummy_plci.State = IDLE;
1685         a->codec_listen[appl->Id-1] = &dummy_plci;
1686         a->TelOAD[0] = (byte)(parms[3].length);
1687         for(i=1;parms[3].length>=i && i<22;i++) {
1688           a->TelOAD[i] = parms[3].info[i];
1689         }
1690         a->TelOAD[i] = 0;
1691         a->TelOSA[0] = (byte)(parms[4].length);
1692         for(i=1;parms[4].length>=i && i<22;i++) {
1693           a->TelOSA[i] = parms[4].info[i];
1694         }
1695         a->TelOSA[i] = 0;
1696       }
1697       else Info = 0x2002; /* wrong controller, codec not supported */
1698     }
1699     else{               /* clear listen */
1700       a->codec_listen[appl->Id-1] = (PLCI   *)0;
1701     }
1702   }
1703   sendf(appl,
1704         _LISTEN_R|CONFIRM,
1705         Id,
1706         Number,
1707         "w",Info);
1708
1709   if (a) listen_check(a);
1710   return false;
1711 }
1712
1713 static byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1714                      PLCI *plci, APPL *appl, API_PARSE *msg)
1715 {
1716   word i;
1717   API_PARSE * ai;
1718   PLCI   * rc_plci = NULL;
1719     API_PARSE ai_parms[5];
1720   word Info = 0;
1721
1722   dbug(1,dprintf("info_req"));
1723   for(i=0;i<5;i++) ai_parms[i].length = 0;
1724
1725   ai = &msg[1];
1726
1727   if(ai->length)
1728   {
1729     if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1730     {
1731       dbug(1,dprintf("AddInfo wrong"));
1732       Info = _WRONG_MESSAGE_FORMAT;
1733     }
1734   }
1735   if(!a) Info = _WRONG_STATE;
1736
1737   if(!Info && plci)
1738   {                /* no fac, with CPN, or KEY */
1739     rc_plci = plci;
1740     if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1741     {
1742       /* overlap sending option */
1743       dbug(1,dprintf("OvlSnd"));
1744       add_s(plci,CPN,&msg[0]);
1745       add_s(plci,KEY,&ai_parms[1]);
1746       sig_req(plci,INFO_REQ,0);
1747       send_req(plci);
1748       return false;
1749     }
1750
1751     if(plci->State && ai_parms[2].length)
1752     {
1753       /* User_Info option */
1754       dbug(1,dprintf("UUI"));
1755       add_s(plci,UUI,&ai_parms[2]);
1756       sig_req(plci,USER_DATA,0);
1757     }
1758     else if(plci->State && ai_parms[3].length)
1759     {
1760       /* Facility option */
1761       dbug(1,dprintf("FAC"));
1762       add_s(plci,CPN,&msg[0]);
1763       add_ai(plci, &msg[1]);
1764       sig_req(plci,FACILITY_REQ,0);
1765     }
1766     else
1767     {
1768       Info = _WRONG_STATE;
1769     }
1770   }
1771   else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1772   {
1773     /* NCR_Facility option -> send UUI and Keypad too */
1774     dbug(1,dprintf("NCR_FAC"));
1775     if((i=get_plci(a)))
1776     {
1777       rc_plci = &a->plci[i-1];
1778       appl->NullCREnable  = true;
1779       rc_plci->internal_command = C_NCR_FAC_REQ;
1780       rc_plci->appl = appl;
1781       add_p(rc_plci,CAI,"\x01\x80");
1782       add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1783       sig_req(rc_plci,ASSIGN,DSIG_ID);
1784       send_req(rc_plci);
1785     }
1786     else
1787     {
1788       Info = _OUT_OF_PLCI;
1789     }
1790
1791     if(!Info)
1792     {
1793       add_s(rc_plci,CPN,&msg[0]);
1794       add_ai(rc_plci, &msg[1]);
1795       sig_req(rc_plci,NCR_FACILITY,0);
1796       send_req(rc_plci);
1797       return false;
1798      /* for application controlled supplementary services    */
1799     }
1800   }
1801
1802   if (!rc_plci)
1803   {
1804     Info = _WRONG_MESSAGE_FORMAT;
1805   }
1806
1807   if(!Info)
1808   {
1809     send_req(rc_plci);
1810   }
1811   else
1812   {  /* appl is not assigned to a PLCI or error condition */
1813     dbug(1,dprintf("localInfoCon"));
1814     sendf(appl,
1815           _INFO_R|CONFIRM,
1816           Id,
1817           Number,
1818           "w",Info);
1819   }
1820   return false;
1821 }
1822
1823 static byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1824                      PLCI *plci, APPL *appl, API_PARSE *msg)
1825 {
1826   dbug(1,dprintf("info_res"));
1827   return false;
1828 }
1829
1830 static byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1831                       PLCI *plci, APPL *appl, API_PARSE *msg)
1832 {
1833   word Info;
1834   byte ret;
1835
1836   dbug(1,dprintf("alert_req"));
1837
1838   Info = _WRONG_IDENTIFIER;
1839   ret = false;
1840   if(plci) {
1841     Info = _ALERT_IGNORED;
1842     if(plci->State!=INC_CON_ALERT) {
1843       Info = _WRONG_STATE;
1844       if(plci->State==INC_CON_PENDING) {
1845         Info = 0;
1846         plci->State=INC_CON_ALERT;
1847         add_ai(plci, &msg[0]);
1848         sig_req(plci,CALL_ALERT,0);
1849         ret = 1;
1850       }
1851     }
1852   }
1853   sendf(appl,
1854         _ALERT_R|CONFIRM,
1855         Id,
1856         Number,
1857         "w",Info);
1858   return ret;
1859 }
1860
1861 static byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
1862                          PLCI *plci, APPL *appl, API_PARSE *msg)
1863 {
1864   word Info = 0;
1865   word i    = 0;
1866
1867   word selector;
1868   word SSreq;
1869   long relatedPLCIvalue;
1870   DIVA_CAPI_ADAPTER   * relatedadapter;
1871   byte * SSparms  = "";
1872     byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1873     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1874   API_PARSE * parms;
1875     API_PARSE ss_parms[11];
1876   PLCI   *rplci;
1877     byte cai[15];
1878   dword d;
1879     API_PARSE dummy;
1880
1881   dbug(1,dprintf("facility_req"));
1882   for(i=0;i<9;i++) ss_parms[i].length = 0;
1883
1884   parms = &msg[1];
1885
1886   if(!a)
1887   {
1888     dbug(1,dprintf("wrong Ctrl"));
1889     Info = _WRONG_IDENTIFIER;
1890   }
1891
1892   selector = GET_WORD(msg[0].info);
1893
1894   if(!Info)
1895   {
1896     switch(selector)
1897     {
1898       case SELECTOR_HANDSET:
1899         Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1900         break;
1901
1902       case SELECTOR_SU_SERV:
1903         if(!msg[1].length)
1904         {
1905           Info = _WRONG_MESSAGE_FORMAT;
1906           break;
1907         }
1908         SSreq = GET_WORD(&(msg[1].info[1]));
1909         PUT_WORD(&RCparms[1],SSreq);
1910         SSparms = RCparms;
1911         switch(SSreq)
1912         {
1913           case S_GET_SUPPORTED_SERVICES:
1914             if((i=get_plci(a)))
1915             {
1916               rplci = &a->plci[i-1];
1917               rplci->appl = appl;
1918               add_p(rplci,CAI,"\x01\x80");
1919               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1920               sig_req(rplci,ASSIGN,DSIG_ID);
1921               send_req(rplci);
1922             }
1923             else
1924             {
1925               PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1926               SSparms = (byte *)SSstruct;
1927               break;
1928             }
1929             rplci->internal_command = GETSERV_REQ_PEND;
1930             rplci->number = Number;
1931             rplci->appl = appl;
1932             sig_req(rplci,S_SUPPORTED,0);
1933             send_req(rplci);
1934             return false;
1935             break;
1936
1937           case S_LISTEN:
1938             if(parms->length==7)
1939             {
1940               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1941               {
1942                 dbug(1,dprintf("format wrong"));
1943                 Info = _WRONG_MESSAGE_FORMAT;
1944                 break;
1945               }
1946             }
1947             else
1948             {
1949               Info = _WRONG_MESSAGE_FORMAT;
1950               break;
1951             }
1952             a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1953             if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1954             {
1955               if((i=get_plci(a)))
1956               {
1957                 rplci = &a->plci[i-1];
1958                 rplci->appl = appl;
1959                 add_p(rplci,CAI,"\x01\x80");
1960                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1961                 sig_req(rplci,ASSIGN,DSIG_ID);
1962                 send_req(rplci);
1963               }
1964               else
1965               {
1966                 break;
1967               }
1968               rplci->internal_command = GET_MWI_STATE;
1969               rplci->number = Number;
1970               sig_req(rplci,MWI_POLL,0);
1971               send_req(rplci);
1972             }
1973             break;
1974
1975           case S_HOLD:
1976             api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1977             if(plci && plci->State && plci->SuppState==IDLE)
1978             {
1979               plci->SuppState = HOLD_REQUEST;
1980               plci->command = C_HOLD_REQ;
1981               add_s(plci,CAI,&ss_parms[1]);
1982               sig_req(plci,CALL_HOLD,0);
1983               send_req(plci);
1984               return false;
1985             }
1986             else Info = 0x3010;                    /* wrong state           */
1987             break;
1988           case S_RETRIEVE:
1989             if(plci && plci->State && plci->SuppState==CALL_HELD)
1990             {
1991               if(Id & EXT_CONTROLLER)
1992               {
1993                 if(AdvCodecSupport(a, plci, appl, 0))
1994                 {
1995                   Info = 0x3010;                    /* wrong state           */
1996                   break;
1997                 }
1998               }
1999               else plci->tel = 0;
2000
2001               plci->SuppState = RETRIEVE_REQUEST;
2002               plci->command = C_RETRIEVE_REQ;
2003               if(plci->spoofed_msg==SPOOFING_REQUIRED)
2004               {
2005                 plci->spoofed_msg = CALL_RETRIEVE;
2006                 plci->internal_command = BLOCK_PLCI;
2007                 plci->command = 0;
2008                 dbug(1,dprintf("Spoof"));
2009                 return false;
2010               }
2011               else
2012               {
2013                 sig_req(plci,CALL_RETRIEVE,0);
2014                 send_req(plci);
2015                 return false;
2016               }
2017             }
2018             else Info = 0x3010;                    /* wrong state           */
2019             break;
2020           case S_SUSPEND:
2021             if(parms->length)
2022             {
2023               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2024               {
2025                 dbug(1,dprintf("format wrong"));
2026                 Info = _WRONG_MESSAGE_FORMAT;
2027                 break;
2028               }
2029             }
2030             if(plci && plci->State)
2031             {
2032               add_s(plci,CAI,&ss_parms[2]);
2033               plci->command = SUSPEND_REQ;
2034               sig_req(plci,SUSPEND,0);
2035               plci->State = SUSPENDING;
2036               send_req(plci);
2037             }
2038             else Info = 0x3010;                    /* wrong state           */
2039             break;
2040
2041           case S_RESUME:
2042             if(!(i=get_plci(a)) )
2043             {
2044               Info = _OUT_OF_PLCI;
2045               break;
2046             }
2047             rplci = &a->plci[i-1];
2048             rplci->appl = appl;
2049             rplci->number = Number;
2050             rplci->tel = 0;
2051             rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2052             /* check 'external controller' bit for codec support */
2053             if(Id & EXT_CONTROLLER)
2054             {
2055               if(AdvCodecSupport(a, rplci, appl, 0) )
2056               {
2057                 rplci->Id = 0;
2058                 Info = 0x300A;
2059                 break;
2060               }
2061             }
2062             if(parms->length)
2063             {
2064               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2065               {
2066                 dbug(1,dprintf("format wrong"));
2067                 rplci->Id = 0;
2068                 Info = _WRONG_MESSAGE_FORMAT;
2069                 break;
2070               }
2071             }
2072             dummy.length = 0;
2073             dummy.info = "\x00";
2074             add_b1(rplci, &dummy, 0, 0);
2075             if (a->Info_Mask[appl->Id-1] & 0x200)
2076             {
2077               /* early B3 connect (CIP mask bit 9) no release after a disc */
2078               add_p(rplci,LLI,"\x01\x01");
2079             }
2080             add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2081             sig_req(rplci,ASSIGN,DSIG_ID);
2082             send_req(rplci);
2083             add_s(rplci,CAI,&ss_parms[2]);
2084             rplci->command = RESUME_REQ;
2085             sig_req(rplci,RESUME,0);
2086             rplci->State = RESUMING;
2087             send_req(rplci);
2088             break;
2089
2090           case S_CONF_BEGIN: /* Request */
2091           case S_CONF_DROP:
2092           case S_CONF_ISOLATE:
2093           case S_CONF_REATTACH:
2094             if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2095             {
2096               dbug(1,dprintf("format wrong"));
2097               Info = _WRONG_MESSAGE_FORMAT;
2098               break;
2099             }
2100             if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2101             {
2102               d = GET_DWORD(ss_parms[2].info);     
2103               if(d>=0x80)
2104               {
2105                 dbug(1,dprintf("format wrong"));
2106                 Info = _WRONG_MESSAGE_FORMAT;
2107                 break;
2108               }
2109               plci->ptyState = (byte)SSreq;
2110               plci->command = 0;
2111               cai[0] = 2;
2112               switch(SSreq)
2113               {
2114               case S_CONF_BEGIN:
2115                   cai[1] = CONF_BEGIN;
2116                   plci->internal_command = CONF_BEGIN_REQ_PEND;
2117                   break;
2118               case S_CONF_DROP:
2119                   cai[1] = CONF_DROP;
2120                   plci->internal_command = CONF_DROP_REQ_PEND;
2121                   break;
2122               case S_CONF_ISOLATE:
2123                   cai[1] = CONF_ISOLATE;
2124                   plci->internal_command = CONF_ISOLATE_REQ_PEND;
2125                   break;
2126               case S_CONF_REATTACH:
2127                   cai[1] = CONF_REATTACH;
2128                   plci->internal_command = CONF_REATTACH_REQ_PEND;
2129                   break;
2130               }
2131               cai[2] = (byte)d; /* Conference Size resp. PartyId */
2132               add_p(plci,CAI,cai);
2133               sig_req(plci,S_SERVICE,0);
2134               send_req(plci);
2135               return false;
2136             }
2137             else Info = 0x3010;                    /* wrong state           */
2138             break;
2139
2140           case S_ECT:
2141           case S_3PTY_BEGIN:
2142           case S_3PTY_END:
2143           case S_CONF_ADD:
2144             if(parms->length==7)
2145             {
2146               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2147               {
2148                 dbug(1,dprintf("format wrong"));
2149                 Info = _WRONG_MESSAGE_FORMAT;
2150                 break;
2151               }
2152             }
2153             else if(parms->length==8) /* workaround for the T-View-S */
2154             {
2155               if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2156               {
2157                 dbug(1,dprintf("format wrong"));
2158                 Info = _WRONG_MESSAGE_FORMAT;
2159                 break;
2160               }
2161             }
2162             else
2163             {
2164               Info = _WRONG_MESSAGE_FORMAT;
2165               break;
2166             }
2167             if(!msg[1].length)
2168             {
2169               Info = _WRONG_MESSAGE_FORMAT;
2170               break;
2171             }
2172             if (!plci)
2173             {
2174               Info = _WRONG_IDENTIFIER;
2175               break;
2176             }
2177             relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2178             relatedPLCIvalue &= 0x0000FFFF;
2179             dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2180             /* controller starts with 0 up to (max_adapter - 1) */
2181             if (((relatedPLCIvalue & 0x7f) == 0)
2182              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2183              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2184             {
2185               if(SSreq==S_3PTY_END)
2186               {
2187                 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2188                 rplci = plci;
2189               }
2190               else
2191               {
2192                 Info = 0x3010;                    /* wrong state           */
2193                 break;
2194               }
2195             }
2196             else
2197             {  
2198               relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2199               relatedPLCIvalue >>=8;
2200               /* find PLCI PTR*/
2201               for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2202               {
2203                 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2204                 {
2205                   rplci = &relatedadapter->plci[i];
2206                 }
2207               }
2208               if(!rplci || !relatedPLCIvalue)
2209               {
2210                 if(SSreq==S_3PTY_END)
2211                 {
2212                   dbug(1, dprintf("use 2nd PLCI=PLCI"));
2213                   rplci = plci;
2214                 }
2215                 else
2216                 {
2217                   Info = 0x3010;                    /* wrong state           */
2218                   break;
2219                 }
2220               }
2221             }
2222 /*
2223             dbug(1,dprintf("rplci:%x",rplci));
2224             dbug(1,dprintf("plci:%x",plci));
2225             dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2226             dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2227             dbug(1,dprintf("SSreq:%x",SSreq));
2228             dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2229             dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2230             dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2231 */
2232             /* send PTY/ECT req, cannot check all states because of US stuff */
2233             if( !rplci->internal_command && rplci->appl )
2234             {
2235               plci->command = 0;
2236               rplci->relatedPTYPLCI = plci;
2237               plci->relatedPTYPLCI = rplci;
2238               rplci->ptyState = (byte)SSreq;
2239               if(SSreq==S_ECT)
2240               {
2241                 rplci->internal_command = ECT_REQ_PEND;
2242                 cai[1] = ECT_EXECUTE;
2243
2244                 rplci->vswitchstate=0;
2245                 rplci->vsprot=0;
2246                 rplci->vsprotdialect=0;
2247                 plci->vswitchstate=0;
2248                 plci->vsprot=0;
2249                 plci->vsprotdialect=0;
2250
2251               }
2252               else if(SSreq==S_CONF_ADD)
2253               {
2254                 rplci->internal_command = CONF_ADD_REQ_PEND;
2255                 cai[1] = CONF_ADD;
2256               }
2257               else
2258               {
2259                 rplci->internal_command = PTY_REQ_PEND;
2260                 cai[1] = (byte)(SSreq-3);
2261               }
2262               rplci->number = Number;
2263               if(plci!=rplci) /* explicit invocation */
2264               {
2265                 cai[0] = 2;
2266                 cai[2] = plci->Sig.Id;
2267                 dbug(1,dprintf("explicit invocation"));
2268               }
2269               else
2270               {
2271                 dbug(1,dprintf("implicit invocation"));
2272                 cai[0] = 1;
2273               }
2274               add_p(rplci,CAI,cai);
2275               sig_req(rplci,S_SERVICE,0);
2276               send_req(rplci);
2277               return false;
2278             }
2279             else
2280             {
2281               dbug(0,dprintf("Wrong line"));
2282               Info = 0x3010;                    /* wrong state           */
2283               break;
2284             }
2285             break;
2286
2287           case S_CALL_DEFLECTION:
2288             if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2289             {
2290               dbug(1,dprintf("format wrong"));
2291               Info = _WRONG_MESSAGE_FORMAT;
2292               break;
2293             }
2294             if (!plci)
2295             {
2296               Info = _WRONG_IDENTIFIER;
2297               break;
2298             }
2299             /* reuse unused screening indicator */
2300             ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2301             plci->command = 0;
2302             plci->internal_command = CD_REQ_PEND;
2303             appl->CDEnable = true;
2304             cai[0] = 1;
2305             cai[1] = CALL_DEFLECTION;
2306             add_p(plci,CAI,cai);
2307             add_p(plci,CPN,ss_parms[3].info);
2308             sig_req(plci,S_SERVICE,0);
2309             send_req(plci);
2310             return false;
2311             break;
2312
2313           case S_CALL_FORWARDING_START:
2314             if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2315             {
2316               dbug(1,dprintf("format wrong"));
2317               Info = _WRONG_MESSAGE_FORMAT;
2318               break;
2319             }
2320
2321             if((i=get_plci(a)))
2322             {
2323               rplci = &a->plci[i-1];
2324               rplci->appl = appl;
2325               add_p(rplci,CAI,"\x01\x80");
2326               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2327               sig_req(rplci,ASSIGN,DSIG_ID);
2328               send_req(rplci);
2329             }
2330             else
2331             {
2332               Info = _OUT_OF_PLCI;
2333               break;
2334             }
2335
2336             /* reuse unused screening indicator */
2337             rplci->internal_command = CF_START_PEND;
2338             rplci->appl = appl;
2339             rplci->number = Number;
2340             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2341             cai[0] = 2;
2342             cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2343             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2344             add_p(rplci,CAI,cai);
2345             add_p(rplci,OAD,ss_parms[5].info);
2346             add_p(rplci,CPN,ss_parms[6].info);
2347             sig_req(rplci,S_SERVICE,0);
2348             send_req(rplci);
2349             return false;
2350             break;
2351
2352           case S_INTERROGATE_DIVERSION:
2353           case S_INTERROGATE_NUMBERS:
2354           case S_CALL_FORWARDING_STOP:
2355           case S_CCBS_REQUEST:
2356           case S_CCBS_DEACTIVATE:
2357           case S_CCBS_INTERROGATE:
2358             switch(SSreq)
2359             {
2360             case S_INTERROGATE_NUMBERS:
2361                 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2362                 {
2363                   dbug(0,dprintf("format wrong"));
2364                   Info = _WRONG_MESSAGE_FORMAT;
2365                 }
2366                 break;
2367             case S_CCBS_REQUEST:
2368             case S_CCBS_DEACTIVATE:
2369                 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2370                 {
2371                   dbug(0,dprintf("format wrong"));
2372                   Info = _WRONG_MESSAGE_FORMAT;
2373                 }
2374                 break;
2375             case S_CCBS_INTERROGATE:
2376                 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2377                 {
2378                   dbug(0,dprintf("format wrong"));
2379                   Info = _WRONG_MESSAGE_FORMAT;
2380                 }
2381                 break;
2382             default:
2383             if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2384             {
2385               dbug(0,dprintf("format wrong"));
2386               Info = _WRONG_MESSAGE_FORMAT;
2387               break;
2388             }
2389                 break;
2390             }
2391
2392             if(Info) break;
2393             if((i=get_plci(a)))
2394             {
2395               rplci = &a->plci[i-1];
2396               switch(SSreq)
2397               {
2398                 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2399                   cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2400                   rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2401                   break;
2402                 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2403                   cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2404                   rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2405                   break;
2406                 case S_CALL_FORWARDING_STOP:
2407                   rplci->internal_command = CF_STOP_PEND;
2408                   cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2409                   break;
2410                 case S_CCBS_REQUEST:
2411                   cai[1] = CCBS_REQUEST;
2412                   rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2413                   break;
2414                 case S_CCBS_DEACTIVATE:
2415                   cai[1] = CCBS_DEACTIVATE;
2416                   rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2417                   break;
2418                 case S_CCBS_INTERROGATE:
2419                   cai[1] = CCBS_INTERROGATE;
2420                   rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2421                   break;
2422                 default:
2423                   cai[1] = 0;
2424                 break;
2425               }
2426               rplci->appl = appl;
2427               rplci->number = Number;
2428               add_p(rplci,CAI,"\x01\x80");
2429               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2430               sig_req(rplci,ASSIGN,DSIG_ID);
2431               send_req(rplci);
2432             }
2433             else
2434             {
2435               Info = _OUT_OF_PLCI;
2436               break;
2437             }
2438
2439             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2440             switch(SSreq)
2441             {
2442             case S_INTERROGATE_NUMBERS:
2443                 cai[0] = 1;
2444                 add_p(rplci,CAI,cai);
2445                 break;
2446             case S_CCBS_REQUEST:
2447             case S_CCBS_DEACTIVATE:
2448                 cai[0] = 3;
2449                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2450                 add_p(rplci,CAI,cai);
2451                 break;
2452             case S_CCBS_INTERROGATE:
2453                 cai[0] = 3;
2454                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2455                 add_p(rplci,CAI,cai);
2456                 add_p(rplci,OAD,ss_parms[4].info);
2457                 break;
2458             default:
2459             cai[0] = 2;
2460             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2461             add_p(rplci,CAI,cai);
2462             add_p(rplci,OAD,ss_parms[5].info);
2463                 break;
2464             }
2465                         
2466             sig_req(rplci,S_SERVICE,0);
2467             send_req(rplci);
2468             return false;
2469             break;
2470
2471           case S_MWI_ACTIVATE:
2472             if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2473             {
2474               dbug(1,dprintf("format wrong"));
2475               Info = _WRONG_MESSAGE_FORMAT;
2476               break;
2477             }
2478             if(!plci)
2479             {                               
2480               if((i=get_plci(a)))
2481               {
2482                 rplci = &a->plci[i-1];
2483                 rplci->appl = appl;
2484                 rplci->cr_enquiry=true;
2485                 add_p(rplci,CAI,"\x01\x80");
2486                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2487                 sig_req(rplci,ASSIGN,DSIG_ID);
2488                 send_req(rplci);
2489               }
2490               else
2491               {
2492                 Info = _OUT_OF_PLCI;
2493                 break;
2494               }
2495             }
2496             else
2497             {
2498               rplci = plci;
2499               rplci->cr_enquiry=false;
2500             }
2501
2502             rplci->command = 0;
2503             rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2504             rplci->appl = appl;
2505             rplci->number = Number;
2506
2507             cai[0] = 13;
2508             cai[1] = ACTIVATION_MWI; /* Function */
2509             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2510             PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2511             PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2512             PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2513             PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2514             add_p(rplci,CAI,cai);
2515             add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2516             add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2517             add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2518             add_p(rplci,UID,ss_parms[10].info); /* Time */
2519             sig_req(rplci,S_SERVICE,0);
2520             send_req(rplci);
2521             return false;
2522
2523           case S_MWI_DEACTIVATE:
2524             if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2525             {
2526               dbug(1,dprintf("format wrong"));
2527               Info = _WRONG_MESSAGE_FORMAT;
2528               break;
2529             }
2530             if(!plci)
2531             {                               
2532               if((i=get_plci(a)))
2533               {
2534                 rplci = &a->plci[i-1];
2535                 rplci->appl = appl;
2536                 rplci->cr_enquiry=true;
2537                 add_p(rplci,CAI,"\x01\x80");
2538                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2539                 sig_req(rplci,ASSIGN,DSIG_ID);
2540                 send_req(rplci);
2541               }
2542               else
2543               {
2544                 Info = _OUT_OF_PLCI;
2545                 break;
2546               }
2547             }
2548             else
2549             {
2550               rplci = plci;
2551               rplci->cr_enquiry=false;
2552             }
2553
2554             rplci->command = 0;
2555             rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2556             rplci->appl = appl;
2557             rplci->number = Number;
2558
2559             cai[0] = 5;
2560             cai[1] = DEACTIVATION_MWI; /* Function */
2561             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2562             PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2563             add_p(rplci,CAI,cai);
2564             add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2565             add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2566             sig_req(rplci,S_SERVICE,0);
2567             send_req(rplci);
2568             return false;
2569
2570           default:
2571             Info = 0x300E;  /* not supported */
2572             break;
2573         }
2574         break; /* case SELECTOR_SU_SERV: end */
2575
2576
2577       case SELECTOR_DTMF:
2578         return (dtmf_request (Id, Number, a, plci, appl, msg));
2579
2580
2581
2582       case SELECTOR_LINE_INTERCONNECT:
2583         return (mixer_request (Id, Number, a, plci, appl, msg));
2584
2585
2586
2587       case PRIV_SELECTOR_ECHO_CANCELLER:
2588         appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2589         return (ec_request (Id, Number, a, plci, appl, msg));
2590
2591       case SELECTOR_ECHO_CANCELLER:
2592         appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2593         return (ec_request (Id, Number, a, plci, appl, msg));
2594
2595
2596       case SELECTOR_V42BIS:
2597       default:
2598         Info = _FACILITY_NOT_SUPPORTED;
2599         break;
2600     } /* end of switch(selector) */
2601   }
2602
2603   dbug(1,dprintf("SendFacRc"));
2604   sendf(appl,
2605         _FACILITY_R|CONFIRM,
2606         Id,
2607         Number,
2608         "wws",Info,selector,SSparms);
2609   return false;
2610 }
2611
2612 static byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2613                          PLCI *plci, APPL *appl, API_PARSE *msg)
2614 {
2615   dbug(1,dprintf("facility_res"));
2616   return false;
2617 }
2618
2619 static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2620                            PLCI *plci, APPL *appl, API_PARSE *parms)
2621 {
2622   word Info = 0;
2623   byte req;
2624   byte len;
2625   word w;
2626   word fax_control_bits, fax_feature_bits, fax_info_change;
2627   API_PARSE * ncpi;
2628     byte pvc[2];
2629
2630     API_PARSE fax_parms[9];
2631   word i;
2632
2633
2634   dbug(1,dprintf("connect_b3_req"));
2635   if(plci)
2636   {
2637     if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2638      || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2639     {
2640       Info = _WRONG_STATE;
2641     }
2642     else
2643     {
2644       /* local reply if assign unsuccessfull
2645          or B3 protocol allows only one layer 3 connection
2646            and already connected
2647              or B2 protocol not any LAPD
2648                and connect_b3_req contradicts originate/answer direction */
2649       if (!plci->NL.Id
2650        || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2651         && ((plci->channels != 0)
2652          || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2653           && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2654       {
2655         dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2656                        plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2657         Info = _WRONG_STATE;
2658         sendf(appl,                                                        
2659               _CONNECT_B3_R|CONFIRM,
2660               Id,
2661               Number,
2662               "w",Info);
2663         return false;
2664       }
2665       plci->requested_options_conn = 0;
2666
2667       req = N_CONNECT;
2668       ncpi = &parms[0];
2669       if(plci->B3_prot==2 || plci->B3_prot==3)
2670       {
2671         if(ncpi->length>2)
2672         {
2673           /* check for PVC */
2674           if(ncpi->info[2] || ncpi->info[3])
2675           {
2676             pvc[0] = ncpi->info[3];
2677             pvc[1] = ncpi->info[2];
2678             add_d(plci,2,pvc);
2679             req = N_RESET;
2680           }
2681           else
2682           {
2683             if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2684             add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2685           }
2686         }
2687       }
2688       else if(plci->B3_prot==5)
2689       {
2690         if (plci->NL.Id && !plci->nl_remove_id)
2691         {
2692           fax_control_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low);
2693           fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low);
2694           if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2695            || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2696           {
2697             len = (byte)(&(((T30_INFO *) 0)->universal_6));
2698             fax_info_change = false;
2699             if (ncpi->length >= 4)
2700             {
2701               w = GET_WORD(&ncpi->info[3]);
2702               if ((w & 0x0001) != ((word)(((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2703               {
2704                 ((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution =
2705                   (byte)((((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2706                   ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2707                 fax_info_change = true;
2708               }
2709               fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2710               if (w & 0x0002)  /* Fax-polling request */
2711                 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2712               if ((w & 0x0004) /* Request to send / poll another document */
2713                && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2714               {
2715                 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2716               }
2717               if (ncpi->length >= 6)
2718               {
2719                 w = GET_WORD(&ncpi->info[5]);
2720                 if (((byte) w) != ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format)
2721                 {
2722                   ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2723                   fax_info_change = true;
2724                 }
2725
2726                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2727                  && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2728                 {
2729                   plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2730                 }
2731                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2732                  && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2733                 {
2734                   plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2735                 }
2736                 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2737                   T30_CONTROL_BIT_ACCEPT_PASSWORD);
2738                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2739                   & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2740                 {
2741                   if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2742                     Info = _WRONG_MESSAGE_FORMAT;
2743                   else
2744                   {
2745                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2746                       & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2747       {
2748                     fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2749                     if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2750                       fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2751       }
2752                     w = fax_parms[4].length;
2753                     if (w > 20)
2754                       w = 20;
2755                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2756                     for (i = 0; i < w; i++)
2757                       ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2758                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2759                     len = (byte)(((T30_INFO *) 0)->station_id + 20);
2760                     w = fax_parms[5].length;
2761                     if (w > 20)
2762                       w = 20;
2763                     plci->fax_connect_info_buffer[len++] = (byte) w;
2764                     for (i = 0; i < w; i++)
2765                       plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2766                     w = fax_parms[6].length;
2767                     if (w > 20)
2768                       w = 20;
2769                     plci->fax_connect_info_buffer[len++] = (byte) w;
2770                     for (i = 0; i < w; i++)
2771                       plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2772                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2773                       & (1L << PRIVATE_FAX_NONSTANDARD))
2774       {
2775                       if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2776         {
2777                         dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2778                         plci->fax_connect_info_buffer[len++] = 0;
2779         }
2780                       else
2781                       {
2782           if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2783             plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2784    plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2785           for (i = 0; i < fax_parms[7].length; i++)
2786      plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2787                       }
2788                     }
2789                   }
2790                 }
2791                 else
2792                 {
2793                   len = (byte)(&(((T30_INFO *) 0)->universal_6));
2794                 }
2795                 fax_info_change = true;
2796
2797               }
2798               if (fax_control_bits != GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low))
2799               {
2800                 PUT_WORD (&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2801                 fax_info_change = true;
2802               }
2803             }
2804             if (Info == GOOD)
2805             {
2806               plci->fax_connect_info_length = len;
2807               if (fax_info_change)
2808               {
2809                 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2810                 {
2811                   start_internal_command (Id, plci, fax_connect_info_command);
2812                   return false;
2813                 }
2814                 else
2815                 {
2816                   start_internal_command (Id, plci, fax_adjust_b23_command);
2817                   return false;
2818                 }
2819               }
2820             }
2821           }
2822           else  Info = _WRONG_STATE;
2823         }
2824         else  Info = _WRONG_STATE;
2825       }
2826
2827       else if (plci->B3_prot == B3_RTP)
2828       {
2829         plci->internal_req_buffer[0] = ncpi->length + 1;
2830         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2831         for (w = 0; w < ncpi->length; w++)
2832           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2833         start_internal_command (Id, plci, rtp_connect_b3_req_command);
2834         return false;
2835       }
2836
2837       if(!Info)
2838       {
2839         nl_req_ncci(plci,req,0);
2840         return 1;
2841       }
2842     }
2843   }
2844   else Info = _WRONG_IDENTIFIER;
2845
2846   sendf(appl,
2847         _CONNECT_B3_R|CONFIRM,
2848         Id,
2849         Number,
2850         "w",Info);
2851   return false;
2852 }
2853
2854 static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2855                            PLCI *plci, APPL *appl, API_PARSE *parms)
2856 {
2857   word ncci;
2858   API_PARSE * ncpi;
2859   byte req;
2860
2861   word w;
2862
2863
2864     API_PARSE fax_parms[9];
2865   word i;
2866   byte len;
2867
2868
2869   dbug(1,dprintf("connect_b3_res"));
2870
2871   ncci = (word)(Id>>16);
2872   if(plci && ncci) {
2873     if(a->ncci_state[ncci]==INC_CON_PENDING) {
2874       if (GET_WORD (&parms[0].info[0]) != 0)
2875       {
2876         a->ncci_state[ncci] = OUTG_REJ_PENDING;
2877         channel_request_xon (plci, a->ncci_ch[ncci]);
2878         channel_xmit_xon (plci);
2879         cleanup_ncci_data (plci, ncci);
2880         nl_req_ncci(plci,N_DISC,(byte)ncci);
2881         return 1;
2882       }
2883       a->ncci_state[ncci] = INC_ACT_PENDING;
2884
2885       req = N_CONNECT_ACK;
2886       ncpi = &parms[1];
2887       if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2888       {
2889
2890         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2891           & (1L << PRIVATE_FAX_NONSTANDARD))
2892  {
2893    if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2894     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2895     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2896    {
2897             len = ((byte)(((T30_INFO *) 0)->station_id + 20));
2898             if (plci->fax_connect_info_length < len)
2899             {
2900               ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2901               ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2902             }
2903             if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2904             {
2905               dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2906             }
2907             else
2908             {
2909               if (plci->fax_connect_info_length <= len)
2910                 plci->fax_connect_info_buffer[len] = 0;
2911               len += 1 + plci->fax_connect_info_buffer[len];
2912               if (plci->fax_connect_info_length <= len)
2913                 plci->fax_connect_info_buffer[len] = 0;
2914               len += 1 + plci->fax_connect_info_buffer[len];
2915               if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2916                 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2917               plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2918               for (i = 0; i < fax_parms[7].length; i++)
2919                 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2920             }
2921             plci->fax_connect_info_length = len;
2922             ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2923             start_internal_command (Id, plci, fax_connect_ack_command);
2924      return false;
2925           }
2926         }
2927
2928         nl_req_ncci(plci,req,(byte)ncci);
2929         if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2930          && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2931         {
2932           if (plci->B3_prot == 4)
2933             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2934           else
2935             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2936           plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2937         }
2938       }
2939
2940       else if (plci->B3_prot == B3_RTP)
2941       {
2942         plci->internal_req_buffer[0] = ncpi->length + 1;
2943         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2944         for (w = 0; w < ncpi->length; w++)
2945           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2946         start_internal_command (Id, plci, rtp_connect_b3_res_command);
2947         return false;
2948       }
2949
2950       else
2951       {
2952         if(ncpi->length>2) {
2953           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2954           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2955         }
2956         nl_req_ncci(plci,req,(byte)ncci);
2957         sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2958         if (plci->adjust_b_restore)
2959         {
2960           plci->adjust_b_restore = false;
2961           start_internal_command (Id, plci, adjust_b_restore);
2962         }
2963       }
2964       return 1;
2965     }
2966   }
2967   return false;
2968 }
2969
2970 static byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2971                              PLCI *plci, APPL *appl, API_PARSE *parms)
2972 {
2973   word ncci;
2974
2975   ncci = (word)(Id>>16);
2976   dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2977
2978   if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2979    && (plci->State != OUTG_DIS_PENDING))
2980   {
2981     if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2982       a->ncci_state[ncci] = CONNECTED;
2983       if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2984       channel_request_xon (plci, a->ncci_ch[ncci]);
2985       channel_xmit_xon (plci);
2986     }
2987   }
2988   return false;
2989 }
2990
2991 static byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
2992                               PLCI *plci, APPL *appl, API_PARSE *parms)
2993 {
2994   word Info;
2995   word ncci;
2996   API_PARSE * ncpi;
2997
2998   dbug(1,dprintf("disconnect_b3_req"));
2999
3000   Info = _WRONG_IDENTIFIER;
3001   ncci = (word)(Id>>16);
3002   if (plci && ncci)
3003   {
3004     Info = _WRONG_STATE;
3005     if ((a->ncci_state[ncci] == CONNECTED)
3006      || (a->ncci_state[ncci] == OUTG_CON_PENDING)
3007      || (a->ncci_state[ncci] == INC_CON_PENDING)
3008      || (a->ncci_state[ncci] == INC_ACT_PENDING))
3009     {
3010       a->ncci_state[ncci] = OUTG_DIS_PENDING;
3011       channel_request_xon (plci, a->ncci_ch[ncci]);
3012       channel_xmit_xon (plci);
3013
3014       if (a->ncci[ncci].data_pending
3015        && ((plci->B3_prot == B3_TRANSPARENT)
3016         || (plci->B3_prot == B3_T30)
3017         || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3018       {
3019         plci->send_disc = (byte)ncci;
3020         plci->command = 0;
3021         return false;
3022       }
3023       else
3024       {
3025         cleanup_ncci_data (plci, ncci);
3026
3027         if(plci->B3_prot==2 || plci->B3_prot==3)
3028         {
3029           ncpi = &parms[0];
3030           if(ncpi->length>3)
3031           {
3032             add_d(plci, (word)(ncpi->length - 3) ,(byte   *)&(ncpi->info[4]));
3033           }
3034         }
3035         nl_req_ncci(plci,N_DISC,(byte)ncci);
3036       }
3037       return 1;
3038     }
3039   }
3040   sendf(appl,
3041         _DISCONNECT_B3_R|CONFIRM,
3042         Id,
3043         Number,
3044         "w",Info);
3045   return false;
3046 }
3047
3048 static byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3049                               PLCI *plci, APPL *appl, API_PARSE *parms)
3050 {
3051   word ncci;
3052   word i;
3053
3054   ncci = (word)(Id>>16);
3055   dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3056   if(plci && ncci) {
3057     plci->requested_options_conn = 0;
3058     plci->fax_connect_info_length = 0;
3059     plci->ncpi_state = 0x00;
3060     if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3061       && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3062     {
3063       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3064     }
3065     for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3066     if(i<MAX_CHANNELS_PER_PLCI) {
3067       if(plci->channels)plci->channels--;
3068       for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3069       plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3070
3071       ncci_free_receive_buffers (plci, ncci);
3072
3073       if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3074         if(plci->State == SUSPENDING){
3075           sendf(plci->appl,
3076                 _FACILITY_I,
3077                 Id & 0xffffL,
3078                 0,
3079                 "ws", (word)3, "\x03\x04\x00\x00");
3080           sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3081         }
3082         plci_remove(plci);
3083         plci->State=IDLE;
3084       }
3085     }
3086     else
3087     {
3088       if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3089        && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3090        && (a->ncci_state[ncci] == INC_DIS_PENDING))
3091       {
3092         ncci_free_receive_buffers (plci, ncci);
3093
3094         nl_req_ncci(plci,N_EDATA,(byte)ncci);
3095
3096         plci->adapter->ncci_state[ncci] = IDLE;
3097         start_internal_command (Id, plci, fax_disconnect_command);
3098         return 1;
3099       }
3100     }
3101   }
3102   return false;
3103 }
3104
3105 static byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3106                         PLCI *plci, APPL *appl, API_PARSE *parms)
3107 {
3108   NCCI   *ncci_ptr;
3109   DATA_B3_DESC   *data;
3110   word Info;
3111   word ncci;
3112   word i;
3113
3114   dbug(1,dprintf("data_b3_req"));
3115
3116   Info = _WRONG_IDENTIFIER;
3117   ncci = (word)(Id>>16);
3118   dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3119
3120   if (plci && ncci)
3121   {
3122     Info = _WRONG_STATE;
3123     if ((a->ncci_state[ncci] == CONNECTED)
3124      || (a->ncci_state[ncci] == INC_ACT_PENDING))
3125     {
3126         /* queue data */
3127       ncci_ptr = &(a->ncci[ncci]);
3128       i = ncci_ptr->data_out + ncci_ptr->data_pending;
3129       if (i >= MAX_DATA_B3)
3130         i -= MAX_DATA_B3;
3131       data = &(ncci_ptr->DBuffer[i]);
3132       data->Number = Number;
3133       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3134        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3135       {
3136
3137         data->P = (byte *)(long)(*((dword *)(parms[0].info)));
3138
3139       }
3140       else
3141         data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3142       data->Length = GET_WORD(parms[1].info);
3143       data->Handle = GET_WORD(parms[2].info);
3144       data->Flags = GET_WORD(parms[3].info);
3145       (ncci_ptr->data_pending)++;
3146
3147         /* check for delivery confirmation */
3148       if (data->Flags & 0x0004)
3149       {
3150         i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3151         if (i >= MAX_DATA_ACK)
3152           i -= MAX_DATA_ACK;
3153         ncci_ptr->DataAck[i].Number = data->Number;
3154         ncci_ptr->DataAck[i].Handle = data->Handle;
3155         (ncci_ptr->data_ack_pending)++;
3156       }
3157
3158       send_data(plci);
3159       return false;
3160     }
3161   }
3162   if (appl)
3163   {
3164     if (plci)
3165     {
3166       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3167        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3168       {
3169
3170         TransmitBufferFree (appl, (byte *)(long)(*((dword *)(parms[0].info))));
3171
3172       }
3173     }
3174     sendf(appl,
3175           _DATA_B3_R|CONFIRM,
3176           Id,
3177           Number,
3178           "ww",GET_WORD(parms[2].info),Info);
3179   }
3180   return false;
3181 }
3182
3183 static byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3184                         PLCI *plci, APPL *appl, API_PARSE *parms)
3185 {
3186   word n;
3187   word ncci;
3188   word NCCIcode;
3189
3190   dbug(1,dprintf("data_b3_res"));
3191
3192   ncci = (word)(Id>>16);
3193   if(plci && ncci) {
3194     n = GET_WORD(parms[0].info);
3195     dbug(1,dprintf("free(%d)",n));
3196     NCCIcode = ncci | (((word) a->Id) << 8);
3197     if(n<appl->MaxBuffer &&
3198        appl->DataNCCI[n]==NCCIcode &&
3199        (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3200       dbug(1,dprintf("found"));
3201       appl->DataNCCI[n] = 0;
3202
3203       if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3204         channel_request_xon (plci, a->ncci_ch[ncci]);
3205       }
3206       channel_xmit_xon (plci);
3207
3208       if(appl->DataFlags[n] &4) {
3209         nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3210         return 1;
3211       }
3212     }
3213   }
3214   return false;
3215 }
3216
3217 static byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3218                          PLCI *plci, APPL *appl, API_PARSE *parms)
3219 {
3220   word Info;
3221   word ncci;
3222
3223   dbug(1,dprintf("reset_b3_req"));
3224
3225   Info = _WRONG_IDENTIFIER;
3226   ncci = (word)(Id>>16);
3227   if(plci && ncci)
3228   {
3229     Info = _WRONG_STATE;
3230     switch (plci->B3_prot)
3231     {
3232     case B3_ISO8208:
3233     case B3_X25_DCE:
3234       if(a->ncci_state[ncci]==CONNECTED)
3235       {
3236         nl_req_ncci(plci,N_RESET,(byte)ncci);
3237         send_req(plci);
3238         Info = GOOD;
3239       }
3240       break;
3241     case B3_TRANSPARENT:
3242       if(a->ncci_state[ncci]==CONNECTED)
3243       {
3244         start_internal_command (Id, plci, reset_b3_command);
3245         Info = GOOD;
3246       }
3247       break;
3248     }
3249   }
3250   /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3251   sendf(appl,
3252         _RESET_B3_R|CONFIRM,
3253         Id,
3254         Number,
3255         "w",Info);
3256   return false;
3257 }
3258
3259 static byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3260                          PLCI *plci, APPL *appl, API_PARSE *parms)
3261 {
3262   word ncci;
3263
3264   dbug(1,dprintf("reset_b3_res"));
3265
3266   ncci = (word)(Id>>16);
3267   if(plci && ncci) {
3268     switch (plci->B3_prot)
3269     {
3270     case B3_ISO8208:
3271     case B3_X25_DCE:
3272       if(a->ncci_state[ncci]==INC_RES_PENDING)
3273       {
3274         a->ncci_state[ncci] = CONNECTED;
3275         nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
3276         return true;
3277       }
3278     break;
3279     }
3280   }
3281   return false;
3282 }
3283
3284 static byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3285                                  PLCI *plci, APPL *appl, API_PARSE *parms)
3286 {
3287   word ncci;
3288   API_PARSE * ncpi;
3289   byte req;
3290
3291   dbug(1,dprintf("connect_b3_t90_a_res"));
3292
3293   ncci = (word)(Id>>16);
3294   if(plci && ncci) {
3295     if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3296       a->ncci_state[ncci] = CONNECTED;
3297     }
3298     else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3299       a->ncci_state[ncci] = CONNECTED;
3300
3301       req = N_CONNECT_ACK;
3302
3303         /* parms[0]==0 for CAPI original message definition! */
3304       if(parms[0].info) {
3305         ncpi = &parms[1];
3306         if(ncpi->length>2) {
3307           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3308           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3309         }
3310       }
3311       nl_req_ncci(plci,req,(byte)ncci);
3312       return 1;
3313     }
3314   }
3315   return false;
3316 }
3317
3318
3319 static byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3320                          PLCI *plci, APPL *appl, API_PARSE *msg)
3321 {
3322   word Info=0;
3323   word i;
3324   byte tel;
3325     API_PARSE bp_parms[7];
3326
3327   if(!plci || !msg)
3328   {
3329     Info = _WRONG_IDENTIFIER;
3330   }
3331   else
3332   {
3333     dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3334                    msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3335     dbug(1,dprintf("PlciState=0x%x",plci->State));
3336     for(i=0;i<7;i++) bp_parms[i].length = 0;
3337
3338     /* check if no channel is open, no B3 connected only */
3339     if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3340      || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3341     {
3342       Info = _WRONG_STATE;
3343     }
3344     /* check message format and fill bp_parms pointer */
3345     else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3346     {
3347       Info = _WRONG_MESSAGE_FORMAT;
3348     }
3349     else
3350     {
3351       if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3352       {                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3353         if(Id & EXT_CONTROLLER)
3354         {
3355           sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3356           return 0;
3357         }
3358         plci->State=INC_CON_CONNECTED_ALERT;
3359         plci->appl = appl;
3360         clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3361         dump_c_ind_mask (plci);
3362         for(i=0; i<max_appl; i++) /* disconnect the other appls */
3363         {                         /* its quasi a connect        */
3364           if(test_c_ind_mask_bit (plci, i))
3365             sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3366         }
3367       }
3368
3369       api_save_msg(msg, "s", &plci->saved_msg);
3370       tel = plci->tel;
3371       if(Id & EXT_CONTROLLER)
3372       {
3373         if(tel) /* external controller in use by this PLCI */
3374         {
3375           if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3376           {
3377             dbug(1,dprintf("Ext_Ctrl in use 1"));
3378             Info = _WRONG_STATE;
3379           }
3380         }
3381         else  /* external controller NOT in use by this PLCI ? */
3382         {
3383           if(a->AdvSignalPLCI)
3384           {
3385             dbug(1,dprintf("Ext_Ctrl in use 2"));
3386             Info = _WRONG_STATE;
3387           }
3388           else /* activate the codec */
3389           {
3390             dbug(1,dprintf("Ext_Ctrl start"));
3391             if(AdvCodecSupport(a, plci, appl, 0) )
3392             {
3393               dbug(1,dprintf("Error in codec procedures"));
3394               Info = _WRONG_STATE;
3395             }
3396             else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3397             {
3398               plci->spoofed_msg = AWAITING_SELECT_B;
3399               plci->internal_command = BLOCK_PLCI; /* lock other commands */
3400               plci->command = 0;
3401               dbug(1,dprintf("continue if codec loaded"));
3402               return false;
3403             }
3404           }
3405         }
3406       }
3407       else /* external controller bit is OFF */
3408       {
3409         if(tel) /* external controller in use, need to switch off */
3410         {
3411           if(a->AdvSignalAppl==appl)
3412           {
3413             CodecIdCheck(a, plci);
3414             plci->tel = 0;
3415             plci->adv_nl = 0;
3416             dbug(1,dprintf("Ext_Ctrl disable"));
3417           }
3418           else
3419           {
3420             dbug(1,dprintf("Ext_Ctrl not requested"));
3421           }
3422         }
3423       }
3424       if (!Info)
3425       {
3426         if (plci->call_dir & CALL_DIR_OUT)
3427           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3428         else if (plci->call_dir & CALL_DIR_IN)
3429           plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3430         start_internal_command (Id, plci, select_b_command);
3431         return false;
3432       }
3433     }
3434   }
3435   sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
3436   return false;
3437 }
3438
3439 static byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3440                              PLCI *plci, APPL *appl, API_PARSE *parms)
3441 {
3442   word command;
3443   word i;
3444   word ncci;
3445   API_PARSE * m;
3446     API_PARSE m_parms[5];
3447   word codec;
3448   byte req;
3449   byte ch;
3450   byte dir;
3451   static byte chi[2] = {0x01,0x00};
3452   static byte lli[2] = {0x01,0x00};
3453   static byte codec_cai[2] = {0x01,0x01};
3454   static byte null_msg = {0};
3455   static API_PARSE null_parms = { 0, &null_msg };
3456   PLCI   * v_plci;
3457   word Info=0;
3458
3459   dbug(1,dprintf("manufacturer_req"));
3460   for(i=0;i<5;i++) m_parms[i].length = 0;
3461
3462   if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3463     Info = _WRONG_MESSAGE_FORMAT;
3464   }
3465   command = GET_WORD(parms[1].info);
3466   m = &parms[2];
3467   if (!Info)
3468   {
3469     switch(command) {
3470     case _DI_ASSIGN_PLCI:
3471       if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3472         Info = _WRONG_MESSAGE_FORMAT;
3473         break;
3474       }
3475       codec = GET_WORD(m_parms[0].info);
3476       ch = m_parms[1].info[0];
3477       dir = m_parms[2].info[0];
3478       if((i=get_plci(a))) {
3479         plci = &a->plci[i-1];
3480         plci->appl = appl;
3481         plci->command = _MANUFACTURER_R;
3482         plci->m_command = command;
3483         plci->number = Number;
3484         plci->State = LOCAL_CONNECT;
3485         Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3486         dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3487
3488         if((ch==1 || ch==2) && (dir<=2)) {
3489           chi[1] = (byte)(0x80|ch);
3490           lli[1] = 0;
3491           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3492           switch(codec)
3493           {
3494           case 0:
3495             Info = add_b1(plci,&m_parms[3],0,0);
3496             break;
3497           case 1:
3498             add_p(plci,CAI,codec_cai);
3499             break;
3500           /* manual 'swich on' to the codec support without signalling */
3501           /* first 'assign plci' with this function, then use */
3502           case 2:
3503             if(AdvCodecSupport(a, plci, appl, 0) ) {
3504               Info = _RESOURCE_ERROR;
3505             }
3506             else {
3507               Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3508               lli[1] = 0x10; /* local call codec stream */
3509             }
3510             break;
3511           }
3512
3513           plci->State = LOCAL_CONNECT;
3514           plci->manufacturer = true;
3515           plci->command = _MANUFACTURER_R;
3516           plci->m_command = command;
3517           plci->number = Number;
3518
3519           if(!Info)
3520           {
3521             add_p(plci,LLI,lli);
3522             add_p(plci,CHI,chi);
3523             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3524             sig_req(plci,ASSIGN,DSIG_ID);
3525
3526             if(!codec)
3527             {
3528               Info = add_b23(plci,&m_parms[3]);
3529               if(!Info)
3530               {
3531                 nl_req_ncci(plci,ASSIGN,0);
3532                 send_req(plci);
3533               }
3534             }
3535             if(!Info)
3536             {
3537               dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3538               if (plci->spoofed_msg==SPOOFING_REQUIRED)
3539               {
3540                 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3541                 plci->spoofed_msg = AWAITING_MANUF_CON;
3542                 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3543                 plci->command = 0;
3544                 send_req(plci);
3545                 return false;
3546               }
3547               if(dir==1) {
3548                 sig_req(plci,CALL_REQ,0);
3549               }
3550               else if(!dir){
3551                 sig_req(plci,LISTEN_REQ,0);
3552               }
3553               send_req(plci);
3554             }
3555             else
3556             {
3557               sendf(appl,
3558                     _MANUFACTURER_R|CONFIRM,
3559                     Id,
3560                     Number,
3561                     "dww",_DI_MANU_ID,command,Info);
3562               return 2;
3563             }
3564           }
3565         }
3566       }
3567       else  Info = _OUT_OF_PLCI;
3568       break;
3569
3570     case _DI_IDI_CTRL:
3571       if(!plci)
3572       {
3573         Info = _WRONG_IDENTIFIER;
3574         break;
3575       }
3576       if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3577         Info = _WRONG_MESSAGE_FORMAT;
3578         break;
3579       }
3580       req = m_parms[0].info[0];
3581       plci->command = _MANUFACTURER_R;
3582       plci->m_command = command;
3583       plci->number = Number;
3584       if(req==CALL_REQ)
3585       {
3586         plci->b_channel = getChannel(&m_parms[1]);
3587         mixer_set_bchannel_id_esc (plci, plci->b_channel);
3588         if(plci->spoofed_msg==SPOOFING_REQUIRED)
3589         {
3590           plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3591           plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3592           plci->command = 0;
3593           break;
3594         }
3595       }
3596       else if(req==LAW_REQ)
3597       {
3598         plci->cr_enquiry = true;
3599       }
3600       add_ss(plci,FTY,&m_parms[1]);
3601       sig_req(plci,req,0);
3602       send_req(plci);
3603       if(req==HANGUP)
3604       {      
3605         if (plci->NL.Id && !plci->nl_remove_id)
3606         {
3607           if (plci->channels)
3608           {
3609             for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3610             {
3611               if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3612               {
3613                 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3614                 cleanup_ncci_data (plci, ncci);
3615                 nl_req_ncci(plci,N_DISC,(byte)ncci);
3616               }
3617             }
3618           }
3619           mixer_remove (plci);
3620           nl_req_ncci(plci,REMOVE,0);
3621           send_req(plci);
3622         }  
3623       }
3624       break;
3625
3626     case _DI_SIG_CTRL:
3627     /* signalling control for loop activation B-channel */
3628       if(!plci)
3629       {
3630         Info = _WRONG_IDENTIFIER;
3631         break;
3632       }
3633       if(m->length){
3634         plci->command = _MANUFACTURER_R;
3635         plci->number = Number;
3636         add_ss(plci,FTY,m);
3637         sig_req(plci,SIG_CTRL,0);
3638         send_req(plci);
3639       }
3640       else Info = _WRONG_MESSAGE_FORMAT;
3641       break;
3642
3643     case _DI_RXT_CTRL:
3644     /* activation control for receiver/transmitter B-channel */
3645       if(!plci)
3646       {
3647         Info = _WRONG_IDENTIFIER;
3648         break;
3649       }
3650       if(m->length){
3651         plci->command = _MANUFACTURER_R;
3652         plci->number = Number;
3653         add_ss(plci,FTY,m);
3654         sig_req(plci,DSP_CTRL,0);
3655         send_req(plci);
3656       }
3657       else Info = _WRONG_MESSAGE_FORMAT;
3658       break;
3659
3660     case _DI_ADV_CODEC:
3661     case _DI_DSP_CTRL:
3662       /* TEL_CTRL commands to support non standard adjustments: */
3663       /* Ring on/off, Handset micro volume, external micro vol. */
3664       /* handset+external speaker volume, receiver+transm. gain,*/
3665       /* handsfree on (hookinfo off), set mixer command         */
3666
3667       if(command == _DI_ADV_CODEC)
3668       {
3669         if(!a->AdvCodecPLCI) {
3670           Info = _WRONG_STATE;
3671           break;
3672         }
3673         v_plci = a->AdvCodecPLCI;
3674       }
3675       else
3676       {
3677         if (plci
3678          && (m->length >= 3)
3679          && (m->info[1] == 0x1c)
3680          && (m->info[2] >= 1))
3681         {
3682           if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3683           {
3684             if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3685             {
3686               Info = _WRONG_STATE;
3687               break;
3688             }
3689             a->adv_voice_coef_length = m->info[2] - 1;
3690             if (a->adv_voice_coef_length > m->length - 3)
3691               a->adv_voice_coef_length = (byte)(m->length - 3);
3692             if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3693               a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3694             for (i = 0; i < a->adv_voice_coef_length; i++)
3695               a->adv_voice_coef_buffer[i] = m->info[4 + i];
3696             if (plci->B1_facilities & B1_FACILITY_VOICE)
3697               adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3698             break;
3699           }
3700           else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3701           {
3702             if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3703             {
3704               Info = _FACILITY_NOT_SUPPORTED;
3705               break;
3706             }
3707
3708             plci->dtmf_parameter_length = m->info[2] - 1;
3709             if (plci->dtmf_parameter_length > m->length - 3)
3710               plci->dtmf_parameter_length = (byte)(m->length - 3);
3711             if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3712               plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3713             for (i = 0; i < plci->dtmf_parameter_length; i++)
3714               plci->dtmf_parameter_buffer[i] = m->info[4+i];
3715             if (plci->B1_facilities & B1_FACILITY_DTMFR)
3716               dtmf_parameter_write (plci);
3717             break;
3718
3719           }
3720         }
3721         v_plci = plci;
3722       }
3723
3724       if(!v_plci)
3725       {
3726         Info = _WRONG_IDENTIFIER;
3727         break;
3728       }
3729       if(m->length){
3730         add_ss(v_plci,FTY,m);
3731         sig_req(v_plci,TEL_CTRL,0);
3732         send_req(v_plci);
3733       }
3734       else Info = _WRONG_MESSAGE_FORMAT;
3735
3736       break;
3737
3738     case _DI_OPTIONS_REQUEST:
3739       if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3740         Info = _WRONG_MESSAGE_FORMAT;
3741         break;
3742       }
3743       if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3744       {
3745         Info = _FACILITY_NOT_SUPPORTED;
3746         break;
3747       }
3748       a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3749       break;
3750
3751
3752
3753     default:
3754       Info = _WRONG_MESSAGE_FORMAT;
3755       break;
3756     }
3757   }
3758
3759   sendf(appl,
3760         _MANUFACTURER_R|CONFIRM,
3761         Id,
3762         Number,
3763         "dww",_DI_MANU_ID,command,Info);
3764   return false;
3765 }
3766
3767
3768 static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
3769                              PLCI *plci, APPL *appl, API_PARSE *msg)
3770 {
3771   word indication;
3772
3773     API_PARSE m_parms[3];
3774   API_PARSE *ncpi;
3775     API_PARSE fax_parms[9];
3776   word i;
3777   byte len;
3778
3779
3780   dbug(1,dprintf("manufacturer_res"));
3781
3782   if ((msg[0].length == 0)
3783    || (msg[1].length == 0)
3784    || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3785   {
3786     return false;
3787   }
3788   indication = GET_WORD(msg[1].info);
3789   switch (indication)
3790   {
3791
3792   case _DI_NEGOTIATE_B3:
3793     if(!plci)
3794       break;
3795     if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3796      || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3797     {
3798       dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3799       break;
3800     }
3801     if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3802     {
3803       dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3804       break;
3805     }
3806     ncpi = &m_parms[1];
3807     len = ((byte)(((T30_INFO *) 0)->station_id + 20));
3808     if (plci->fax_connect_info_length < len)
3809     {
3810       ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3811       ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3812     }
3813     if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3814     {
3815       dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3816     }
3817     else
3818     {
3819       if (plci->fax_connect_info_length <= len)
3820         plci->fax_connect_info_buffer[len] = 0;
3821       len += 1 + plci->fax_connect_info_buffer[len];
3822       if (plci->fax_connect_info_length <= len)
3823         plci->fax_connect_info_buffer[len] = 0;
3824       len += 1 + plci->fax_connect_info_buffer[len];
3825       if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3826         plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3827       plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3828       for (i = 0; i < fax_parms[7].length; i++)
3829         plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3830     }
3831     plci->fax_connect_info_length = len;
3832     plci->fax_edata_ack_length = plci->fax_connect_info_length;
3833     start_internal_command (Id, plci, fax_edata_ack_command);
3834     break;
3835
3836   }
3837   return false;
3838 }
3839
3840 /*------------------------------------------------------------------*/
3841 /* IDI callback function                                            */
3842 /*------------------------------------------------------------------*/
3843
3844 void   callback(ENTITY   * e)
3845 {
3846   DIVA_CAPI_ADAPTER   * a;
3847   APPL   * appl;
3848   PLCI   * plci;
3849   CAPI_MSG   *m;
3850   word i, j;
3851   byte rc;
3852   byte ch;
3853   byte req;
3854   byte global_req;
3855   int no_cancel_rc;
3856
3857   dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3858                  (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3859
3860   a = &(adapter[(byte)e->user[0]]);
3861   plci = &(a->plci[e->user[1]]);
3862   no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3863
3864   /*
3865      If new protocol code and new XDI is used then CAPI should work
3866      fully in accordance with IDI cpec an look on callback field instead
3867      of Rc field for return codes.
3868    */
3869   if (((e->complete == 0xff) && no_cancel_rc) ||
3870       (e->Rc && !no_cancel_rc)) {
3871     rc = e->Rc;
3872     ch = e->RcCh;
3873     req = e->Req;
3874     e->Rc = 0;
3875
3876     if (e->user[0] & 0x8000)
3877     {
3878       /*
3879          If REMOVE request was sent then we have to wait until
3880          return code with Id set to zero arrives.
3881          All other return codes should be ignored.
3882          */
3883       if (req == REMOVE)
3884       {
3885         if (e->Id)
3886         {
3887           dbug(1,dprintf("cancel RC in REMOVE state"));
3888           return;
3889         }
3890         channel_flow_control_remove (plci);
3891         for (i = 0; i < 256; i++)
3892         {
3893           if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3894             a->FlowControlIdTable[i] = 0;
3895         }
3896         plci->nl_remove_id = 0;
3897         if (plci->rx_dma_descriptor > 0) {
3898           diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3899           plci->rx_dma_descriptor = 0;
3900         }
3901       }
3902       if (rc == OK_FC)
3903       {
3904         a->FlowControlIdTable[ch] = e->Id;
3905         a->FlowControlSkipTable[ch] = 0;
3906
3907         a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3908         a->ch_flow_plci[ch] = plci->Id;
3909         plci->nl_req = 0;
3910       }
3911       else
3912       {
3913         /*
3914           Cancel return codes self, if feature was requested
3915           */
3916         if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3917           a->FlowControlIdTable[ch] = 0;
3918           if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3919             dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x",                              e->Id, ch));
3920             return;
3921           }
3922         }
3923
3924         if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3925         {
3926           a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3927           if (ch == e->ReqCh)
3928             plci->nl_req = 0;
3929         }
3930         else
3931           plci->nl_req = 0;
3932       }
3933       if (plci->nl_req)
3934         control_rc (plci, 0, rc, ch, 0, true);
3935       else
3936       {
3937         if (req == N_XON)
3938         {
3939           channel_x_on (plci, ch);
3940           if (plci->internal_command)
3941             control_rc (plci, req, rc, ch, 0, true);
3942         }
3943         else
3944         {
3945           if (plci->nl_global_req)
3946           {
3947             global_req = plci->nl_global_req;
3948             plci->nl_global_req = 0;
3949             if (rc != ASSIGN_OK) {
3950               e->Id = 0;
3951               if (plci->rx_dma_descriptor > 0) {
3952                 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3953                 plci->rx_dma_descriptor = 0;
3954               }
3955             }
3956             channel_xmit_xon (plci);
3957             control_rc (plci, 0, rc, ch, global_req, true);
3958           }
3959           else if (plci->data_sent)
3960           {
3961             channel_xmit_xon (plci);
3962             plci->data_sent = false;
3963             plci->NL.XNum = 1;
3964             data_rc (plci, ch);
3965             if (plci->internal_command)
3966               control_rc (plci, req, rc, ch, 0, true);
3967           }
3968           else
3969           {
3970             channel_xmit_xon (plci);
3971             control_rc (plci, req, rc, ch, 0, true);
3972           }
3973         }
3974       }
3975     }
3976     else
3977     {
3978       /*
3979          If REMOVE request was sent then we have to wait until
3980          return code with Id set to zero arrives.
3981          All other return codes should be ignored.
3982          */
3983       if (req == REMOVE)
3984       {
3985         if (e->Id)
3986         {
3987           dbug(1,dprintf("cancel RC in REMOVE state"));
3988           return;
3989         }
3990         plci->sig_remove_id = 0;
3991       }
3992       plci->sig_req = 0;
3993       if (plci->sig_global_req)
3994       {
3995         global_req = plci->sig_global_req;
3996         plci->sig_global_req = 0;
3997         if (rc != ASSIGN_OK)
3998           e->Id = 0;
3999         channel_xmit_xon (plci);
4000         control_rc (plci, 0, rc, ch, global_req, false);
4001       }
4002       else
4003       {
4004         channel_xmit_xon (plci);
4005         control_rc (plci, req, rc, ch, 0, false);
4006       }
4007     }
4008     /*
4009       Again: in accordance with IDI spec Rc and Ind can't be delivered in the
4010       same callback. Also if new XDI and protocol code used then jump
4011       direct to finish.
4012       */
4013     if (no_cancel_rc) {
4014       channel_xmit_xon(plci);
4015       goto capi_callback_suffix;
4016     }
4017   }
4018
4019   channel_xmit_xon(plci);
4020
4021   if (e->Ind) {
4022     if (e->user[0] &0x8000) {
4023       byte Ind = e->Ind & 0x0f;
4024       byte Ch = e->IndCh;
4025       if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4026           (a->ch_flow_plci[Ch] == plci->Id)) {
4027         if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4028           dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4029         }
4030         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4031       }
4032       nl_ind(plci);
4033       if ((e->RNR != 1) &&
4034           (a->ch_flow_plci[Ch] == plci->Id) &&
4035           (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4036         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4037         dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4038       }
4039     } else {
4040       sig_ind(plci);
4041     }
4042     e->Ind = 0;
4043   }
4044
4045 capi_callback_suffix:
4046
4047   while (!plci->req_in
4048    && !plci->internal_command
4049    && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4050   {
4051     j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4052
4053     i = (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4054
4055     m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
4056     appl = *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j+i]));
4057     dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4058       m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4059     if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4060     {
4061       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4062       plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4063     }
4064     else
4065     {
4066       plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4067     }
4068     if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4069     {
4070       plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4071       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4072     }
4073     else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4074     {
4075       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4076       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4077     }
4078     i = api_put (appl, m);
4079     if (i != 0)
4080     {
4081       if (m->header.command == _DATA_B3_R)
4082
4083         TransmitBufferFree (appl, (byte *)(long)(m->info.data_b3_req.Data));
4084
4085       dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4086       break;
4087     }
4088
4089     if (plci->li_notify_update)
4090     {
4091       plci->li_notify_update = false;
4092       mixer_notify_update (plci, false);
4093     }
4094
4095   }
4096   send_data(plci);
4097   send_req(plci);
4098 }
4099
4100
4101 static void control_rc(PLCI *plci, byte req, byte rc, byte ch, byte global_req,
4102                        byte nl_rc)
4103 {
4104   dword Id;
4105   dword rId;
4106   word Number;
4107   word Info=0;
4108   word i;
4109   word ncci;
4110   DIVA_CAPI_ADAPTER   * a;
4111   APPL   * appl;
4112   PLCI   * rplci;
4113     byte SSparms[]  = "\x05\x00\x00\x02\x00\x00";
4114     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4115
4116   if (!plci) {
4117     dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4118     return;
4119   }
4120   dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4121   if(plci->req_in!=plci->req_out)
4122   {
4123     if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4124     {
4125       dbug(1,dprintf("req_1return"));
4126       return;
4127     }
4128     /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4129   }
4130   plci->req_in = plci->req_in_start = plci->req_out = 0;
4131   dbug(1,dprintf("control_rc"));
4132
4133   appl = plci->appl;
4134   a = plci->adapter;
4135   ncci = a->ch_ncci[ch];
4136   if(appl)
4137   {
4138     Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4139     if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4140     Number = plci->number;
4141     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));
4142     dbug(1,dprintf("channels=0x%x",plci->channels));
4143     if (plci_remove_check(plci))
4144       return;
4145     if(req==REMOVE && rc==ASSIGN_OK)
4146     {
4147       sig_req(plci,HANGUP,0);
4148       sig_req(plci,REMOVE,0);
4149       send_req(plci);
4150     }
4151     if(plci->command)
4152     {
4153       switch(plci->command)
4154       {
4155       case C_HOLD_REQ:
4156         dbug(1,dprintf("HoldRC=0x%x",rc));
4157         SSparms[1] = (byte)S_HOLD;
4158         if(rc!=OK)
4159         {
4160           plci->SuppState = IDLE;
4161           Info = 0x2001;
4162         }
4163         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4164         break;
4165
4166       case C_RETRIEVE_REQ:
4167         dbug(1,dprintf("RetrieveRC=0x%x",rc));
4168         SSparms[1] = (byte)S_RETRIEVE;
4169         if(rc!=OK)
4170         {
4171           plci->SuppState = CALL_HELD;
4172           Info = 0x2001;
4173         }
4174         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4175         break;
4176
4177       case _INFO_R:
4178         dbug(1,dprintf("InfoRC=0x%x",rc));
4179         if(rc!=OK) Info=_WRONG_STATE;
4180         sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4181         break;
4182
4183       case _CONNECT_R:
4184         dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4185         if (plci->State == INC_DIS_PENDING)
4186           break;
4187         if(plci->Sig.Id!=0xff)
4188         {
4189           if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4190            || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4191           {
4192             dbug(1,dprintf("No more IDs/Call_Req failed"));
4193             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4194             plci_remove(plci);
4195             plci->State = IDLE;
4196             break;
4197           }
4198           if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4199           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4200         }
4201         else /* D-ch activation */
4202         {
4203           if (rc != ASSIGN_OK)
4204           {
4205             dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4206             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4207             plci_remove(plci);
4208             plci->State = IDLE;
4209             break;
4210           }
4211           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4212           sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4213           plci->State = INC_ACT_PENDING;
4214         }
4215         break;
4216
4217       case _CONNECT_I|RESPONSE:
4218         if (plci->State != INC_DIS_PENDING)
4219           plci->State = INC_CON_ACCEPT;
4220         break;
4221
4222       case _DISCONNECT_R:
4223         if (plci->State == INC_DIS_PENDING)
4224           break;
4225         if(plci->Sig.Id!=0xff)
4226         {
4227           plci->State = OUTG_DIS_PENDING;
4228           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4229         }
4230         break;
4231
4232       case SUSPEND_REQ:
4233         break;
4234
4235       case RESUME_REQ:
4236         break;
4237
4238       case _CONNECT_B3_R:
4239         if(rc!=OK)
4240         {
4241           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4242           break;
4243         }
4244         ncci = get_ncci (plci, ch, 0);
4245         Id = (Id & 0xffff) | (((dword) ncci) << 16);
4246         plci->channels++;
4247         if(req==N_RESET)
4248         {
4249           a->ncci_state[ncci] = INC_ACT_PENDING;
4250           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4251           sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4252         }
4253         else
4254         {
4255           a->ncci_state[ncci] = OUTG_CON_PENDING;
4256           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4257         }
4258         break;
4259
4260       case _CONNECT_B3_I|RESPONSE:
4261         break;
4262
4263       case _RESET_B3_R:
4264 /*        sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4265         break;
4266
4267       case _DISCONNECT_B3_R:
4268         sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4269         break;
4270
4271       case _MANUFACTURER_R:
4272         break;
4273
4274       case PERM_LIST_REQ:
4275         if(rc!=OK)
4276         {
4277           Info = _WRONG_IDENTIFIER;
4278           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4279           plci_remove(plci);
4280         }
4281         else
4282           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4283         break;
4284
4285       default:
4286         break;
4287       }
4288       plci->command = 0;
4289     }
4290     else if (plci->internal_command)
4291     {
4292       switch(plci->internal_command)
4293       {
4294       case BLOCK_PLCI:
4295         return;
4296
4297       case GET_MWI_STATE:
4298         if(rc==OK) /* command supported, wait for indication */
4299         {
4300           return;
4301         }
4302         plci_remove(plci);
4303         break;
4304
4305         /* Get Supported Services */
4306       case GETSERV_REQ_PEND:
4307         if(rc==OK) /* command supported, wait for indication */
4308         {
4309           break;
4310         }
4311         PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4312         sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4313         plci_remove(plci);
4314         break;
4315
4316       case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
4317       case INTERR_NUMBERS_REQ_PEND:
4318       case CF_START_PEND:                  /* Call Forwarding Start pending */
4319       case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
4320       case CCBS_REQUEST_REQ_PEND:
4321       case CCBS_DEACTIVATE_REQ_PEND:
4322       case CCBS_INTERROGATE_REQ_PEND:
4323         switch(plci->internal_command)
4324         {
4325           case INTERR_DIVERSION_REQ_PEND:
4326             SSparms[1] = S_INTERROGATE_DIVERSION;
4327             break;
4328           case INTERR_NUMBERS_REQ_PEND:
4329             SSparms[1] = S_INTERROGATE_NUMBERS;
4330             break;
4331           case CF_START_PEND:
4332             SSparms[1] = S_CALL_FORWARDING_START;
4333             break;
4334           case CF_STOP_PEND:
4335             SSparms[1] = S_CALL_FORWARDING_STOP;
4336             break;
4337           case CCBS_REQUEST_REQ_PEND:
4338             SSparms[1] = S_CCBS_REQUEST;
4339             break;
4340           case CCBS_DEACTIVATE_REQ_PEND:
4341             SSparms[1] = S_CCBS_DEACTIVATE;
4342             break;
4343           case CCBS_INTERROGATE_REQ_PEND:
4344             SSparms[1] = S_CCBS_INTERROGATE;
4345             break;
4346         }
4347         if(global_req==ASSIGN)
4348         {
4349           dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4350           return;
4351         }
4352         if(!plci->appl) break;
4353         if(rc==ISDN_GUARD_REJ)
4354         {
4355           Info = _CAPI_GUARD_ERROR;
4356         }
4357         else if(rc!=OK)
4358         {
4359           Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4360         }
4361         sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4362               plci->number,"wws",Info,(word)3,SSparms);
4363         if(Info) plci_remove(plci);
4364         break;
4365
4366         /* 3pty conference pending */
4367       case PTY_REQ_PEND:
4368         if(!plci->relatedPTYPLCI) break;
4369         rplci = plci->relatedPTYPLCI;
4370         SSparms[1] = plci->ptyState;
4371         rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4372         if(rplci->tel) rId|=EXT_CONTROLLER;
4373         if(rc!=OK)
4374         {
4375           Info = 0x300E; /* not supported */
4376           plci->relatedPTYPLCI = NULL;
4377           plci->ptyState = 0;
4378         }
4379         sendf(rplci->appl,
4380               _FACILITY_R|CONFIRM,
4381               rId,
4382               plci->number,
4383               "wws",Info,(word)3,SSparms);
4384         break;
4385
4386         /* Explicit Call Transfer pending */
4387       case ECT_REQ_PEND:
4388         dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4389         if(!plci->relatedPTYPLCI) break;
4390         rplci = plci->relatedPTYPLCI;
4391         SSparms[1] = S_ECT;
4392         rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4393         if(rplci->tel) rId|=EXT_CONTROLLER;
4394         if(rc!=OK)
4395         {
4396           Info = 0x300E; /* not supported */
4397           plci->relatedPTYPLCI = NULL;
4398           plci->ptyState = 0;
4399         }
4400         sendf(rplci->appl,
4401               _FACILITY_R|CONFIRM,
4402               rId,
4403               plci->number,
4404               "wws",Info,(word)3,SSparms);
4405         break;
4406
4407       case _MANUFACTURER_R:
4408         dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4409         if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4410         {
4411           dbug(1,dprintf("No more IDs"));
4412           sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4413           plci_remove(plci);  /* after codec init, internal codec commands pending */
4414         }
4415         break;
4416
4417       case _CONNECT_R:
4418         dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4419         if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4420         {
4421           dbug(1,dprintf("No more IDs"));
4422           sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4423           plci_remove(plci);  /* after codec init, internal codec commands pending */
4424         }
4425         break;
4426
4427       case PERM_COD_HOOK:                     /* finished with Hook_Ind */
4428         return;
4429
4430       case PERM_COD_CALL:
4431         dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4432         plci->internal_command = PERM_COD_CONN_PEND;
4433         return;
4434
4435       case PERM_COD_ASSIGN:
4436         dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4437         if(rc!=ASSIGN_OK) break;
4438         sig_req(plci,CALL_REQ,0);
4439         send_req(plci);
4440         plci->internal_command = PERM_COD_CALL;
4441         return;
4442
4443         /* Null Call Reference Request pending */
4444       case C_NCR_FAC_REQ:
4445         dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4446         if(global_req==ASSIGN)
4447         {
4448           if(rc==ASSIGN_OK)
4449           {
4450             return;
4451           }
4452           else
4453           {
4454             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4455             appl->NullCREnable = false;
4456             plci_remove(plci);
4457           }
4458         }
4459         else if(req==NCR_FACILITY)
4460         {
4461           if(rc==OK)
4462           {
4463             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4464           }
4465           else
4466           {
4467             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4468             appl->NullCREnable = false;
4469           }
4470           plci_remove(plci);
4471         }
4472         break;
4473
4474       case HOOK_ON_REQ:
4475         if(plci->channels)
4476         {
4477           if(a->ncci_state[ncci]==CONNECTED)
4478           {
4479             a->ncci_state[ncci] = OUTG_DIS_PENDING;
4480             cleanup_ncci_data (plci, ncci);
4481             nl_req_ncci(plci,N_DISC,(byte)ncci);
4482           }
4483           break;
4484         }
4485         break;
4486
4487       case HOOK_OFF_REQ:
4488         if (plci->State == INC_DIS_PENDING)
4489           break;
4490         sig_req(plci,CALL_REQ,0);
4491         send_req(plci);
4492         plci->State=OUTG_CON_PENDING;
4493         break;
4494
4495
4496       case MWI_ACTIVATE_REQ_PEND:
4497       case MWI_DEACTIVATE_REQ_PEND:
4498         if(global_req == ASSIGN && rc==ASSIGN_OK)
4499         {
4500           dbug(1,dprintf("MWI_REQ assigned"));
4501           return;
4502         }
4503         else if(rc!=OK)
4504         {                 
4505           if(rc==WRONG_IE)
4506           {
4507             Info = 0x2007; /* Illegal message parameter coding */
4508             dbug(1,dprintf("MWI_REQ invalid parameter"));
4509           }
4510           else
4511           {
4512             Info = 0x300B; /* not supported */                      
4513             dbug(1,dprintf("MWI_REQ not supported"));
4514           }
4515           /* 0x3010: Request not allowed in this state */
4516           PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4517                     
4518         }
4519         if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4520         {
4521           PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4522         }
4523         else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4524
4525         if(plci->cr_enquiry)
4526         {
4527           sendf(plci->appl,
4528                 _FACILITY_R|CONFIRM,
4529                 Id&0xf,
4530                 plci->number,
4531                 "wws",Info,(word)3,SSparms);
4532           if(rc!=OK) plci_remove(plci);
4533         }
4534         else
4535         {
4536           sendf(plci->appl,
4537                 _FACILITY_R|CONFIRM,
4538                 Id,
4539                 plci->number,
4540                 "wws",Info,(word)3,SSparms);
4541         }
4542         break;
4543
4544       case CONF_BEGIN_REQ_PEND:
4545       case CONF_ADD_REQ_PEND:
4546       case CONF_SPLIT_REQ_PEND:
4547       case CONF_DROP_REQ_PEND:
4548       case CONF_ISOLATE_REQ_PEND:
4549       case CONF_REATTACH_REQ_PEND:
4550         dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4551         if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4552         rplci = plci;
4553         rId = Id;
4554         switch(plci->internal_command)
4555         {
4556           case CONF_BEGIN_REQ_PEND:
4557             SSparms[1] = S_CONF_BEGIN;
4558             break;
4559           case CONF_ADD_REQ_PEND:
4560             SSparms[1] = S_CONF_ADD;
4561             rplci = plci->relatedPTYPLCI;
4562             rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4563             break;
4564           case CONF_SPLIT_REQ_PEND:
4565             SSparms[1] = S_CONF_SPLIT;
4566             break;
4567           case CONF_DROP_REQ_PEND:
4568             SSparms[1] = S_CONF_DROP;
4569             break;
4570           case CONF_ISOLATE_REQ_PEND:
4571             SSparms[1] = S_CONF_ISOLATE;
4572             break;
4573           case CONF_REATTACH_REQ_PEND:
4574             SSparms[1] = S_CONF_REATTACH;
4575             break;
4576         }
4577         
4578         if(rc!=OK)
4579         {
4580           Info = 0x300E; /* not supported */
4581           plci->relatedPTYPLCI = NULL;
4582           plci->ptyState = 0;
4583         }
4584         sendf(rplci->appl,
4585               _FACILITY_R|CONFIRM,
4586               rId,
4587               plci->number,
4588               "wws",Info,(word)3,SSparms);
4589         break;
4590
4591       case VSWITCH_REQ_PEND:
4592         if(rc!=OK)
4593         {
4594           if(plci->relatedPTYPLCI)
4595           {
4596             plci->relatedPTYPLCI->vswitchstate=0;
4597             plci->relatedPTYPLCI->vsprot=0;
4598             plci->relatedPTYPLCI->vsprotdialect=0;    
4599           }
4600           plci->vswitchstate=0;
4601           plci->vsprot=0;
4602           plci->vsprotdialect=0;
4603         }
4604         else
4605         {
4606           if(plci->relatedPTYPLCI &&
4607              plci->vswitchstate==1 &&
4608              plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4609             plci->vswitchstate=3;
4610         }
4611         break;
4612
4613   /* Call Deflection Request pending (SSCT) */
4614       case CD_REQ_PEND:
4615         SSparms[1] = S_CALL_DEFLECTION;
4616         if(rc!=OK)
4617         {
4618           Info = 0x300E; /* not supported */
4619           plci->appl->CDEnable = 0;
4620         }  
4621         sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4622           plci->number,"wws",Info,(word)3,SSparms);
4623         break;
4624
4625       case RTP_CONNECT_B3_REQ_COMMAND_2:
4626         if (rc == OK)
4627         {
4628           ncci = get_ncci (plci, ch, 0);
4629           Id = (Id & 0xffff) | (((dword) ncci) << 16);
4630           plci->channels++;
4631           a->ncci_state[ncci] = OUTG_CON_PENDING;
4632         }
4633
4634       default:
4635         if (plci->internal_command_queue[0])
4636         {
4637           (*(plci->internal_command_queue[0]))(Id, plci, rc);
4638           if (plci->internal_command)
4639             return;
4640         }
4641         break;
4642       }
4643       next_internal_command (Id, plci);
4644     }
4645   }
4646   else /* appl==0 */
4647   {
4648     Id = ((word)plci->Id<<8)|plci->adapter->Id;
4649     if(plci->tel) Id|=EXT_CONTROLLER;
4650
4651     switch(plci->internal_command)
4652     {
4653     case BLOCK_PLCI:
4654       return;
4655
4656     case START_L1_SIG_ASSIGN_PEND:
4657     case REM_L1_SIG_ASSIGN_PEND:
4658       if(global_req == ASSIGN)
4659       {
4660         break;
4661       }
4662       else
4663       {
4664         dbug(1,dprintf("***L1 Req rem PLCI"));
4665         plci->internal_command = 0;
4666         sig_req(plci,REMOVE,0);
4667         send_req(plci);
4668       }
4669       break;
4670
4671       /* Call Deflection Request pending, just no appl ptr assigned */
4672     case CD_REQ_PEND:
4673       SSparms[1] = S_CALL_DEFLECTION;
4674       if(rc!=OK)
4675       {
4676         Info = 0x300E; /* not supported */
4677       }
4678       for(i=0; i<max_appl; i++)
4679       {
4680         if(application[i].CDEnable)
4681         {
4682           if(!application[i].Id) application[i].CDEnable = 0;
4683           else
4684           {
4685             sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4686                   plci->number,"wws",Info,(word)3,SSparms);
4687             if(Info) application[i].CDEnable = 0;
4688           }
4689         }
4690       }
4691       plci->internal_command = 0;
4692       break;
4693
4694     case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4695       return;
4696
4697     case PERM_COD_CALL:
4698       plci->internal_command = PERM_COD_CONN_PEND;
4699       dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4700       return;
4701
4702     case PERM_COD_ASSIGN:
4703       dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4704       plci->internal_command = 0;
4705       if(rc!=ASSIGN_OK) break;
4706       plci->internal_command = PERM_COD_CALL;
4707       sig_req(plci,CALL_REQ,0);
4708       send_req(plci);
4709       return;
4710
4711     case LISTEN_SIG_ASSIGN_PEND:
4712       if(rc == ASSIGN_OK)
4713       {
4714         plci->internal_command = 0;
4715         dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4716         add_p(plci,ESC,"\x02\x18\x00");             /* support call waiting */
4717         sig_req(plci,INDICATE_REQ,0);
4718         send_req(plci);
4719       }
4720       else
4721       {
4722         dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4723         a->listen_active--;
4724         plci_remove(plci);
4725         plci->State = IDLE;
4726       }
4727       break;
4728
4729     case USELAW_REQ:
4730       if(global_req == ASSIGN)
4731       {
4732         if (rc==ASSIGN_OK)
4733       {
4734         sig_req(plci,LAW_REQ,0);
4735         send_req(plci);
4736         dbug(1,dprintf("Auto-Law assigned"));
4737         }
4738         else
4739         {
4740           dbug(1,dprintf("Auto-Law assign failed"));
4741           a->automatic_law = 3;
4742           plci->internal_command = 0;
4743           a->automatic_lawPLCI = NULL;
4744         }
4745         break;
4746       }
4747       else if(req == LAW_REQ && rc==OK)
4748       {
4749         dbug(1,dprintf("Auto-Law initiated"));
4750         a->automatic_law = 2;
4751         plci->internal_command = 0;
4752       }
4753       else
4754       {
4755         dbug(1,dprintf("Auto-Law not supported"));
4756         a->automatic_law = 3;
4757         plci->internal_command = 0;
4758         sig_req(plci,REMOVE,0);
4759         send_req(plci);
4760         a->automatic_lawPLCI = NULL;
4761       }
4762       break;
4763     }
4764     plci_remove_check(plci);
4765   }
4766 }
4767
4768 static void data_rc(PLCI *plci, byte ch)
4769 {
4770   dword Id;
4771   DIVA_CAPI_ADAPTER   * a;
4772   NCCI   *ncci_ptr;
4773   DATA_B3_DESC   *data;
4774   word ncci;
4775
4776   if (plci->appl)
4777   {
4778     TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4779     a = plci->adapter;
4780     ncci = a->ch_ncci[ch];
4781     if (ncci && (a->ncci_plci[ncci] == plci->Id))
4782     {
4783       ncci_ptr = &(a->ncci[ncci]);
4784       dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4785       if (ncci_ptr->data_pending)
4786       {
4787         data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4788         if (!(data->Flags &4) && a->ncci_state[ncci])
4789         {
4790           Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4791           if(plci->tel) Id|=EXT_CONTROLLER;
4792           sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4793                 "ww",data->Handle,0);
4794         }
4795         (ncci_ptr->data_out)++;
4796         if (ncci_ptr->data_out == MAX_DATA_B3)
4797           ncci_ptr->data_out = 0;
4798         (ncci_ptr->data_pending)--;
4799       }
4800     }
4801   }
4802 }
4803
4804 static void data_ack(PLCI *plci, byte ch)
4805 {
4806   dword Id;
4807   DIVA_CAPI_ADAPTER   * a;
4808   NCCI   *ncci_ptr;
4809   word ncci;
4810
4811   a = plci->adapter;
4812   ncci = a->ch_ncci[ch];
4813   ncci_ptr = &(a->ncci[ncci]);
4814   if (ncci_ptr->data_ack_pending)
4815   {
4816     if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4817     {
4818       Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4819       if(plci->tel) Id|=EXT_CONTROLLER;
4820       sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4821             "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4822     }
4823     (ncci_ptr->data_ack_out)++;
4824     if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4825       ncci_ptr->data_ack_out = 0;
4826     (ncci_ptr->data_ack_pending)--;
4827   }
4828 }
4829
4830 static void sig_ind(PLCI *plci)
4831 {
4832   dword x_Id;
4833   dword Id;
4834   dword rId;
4835   word Number = 0;
4836   word i;
4837   word cip;
4838   dword cip_mask;
4839   byte   *ie;
4840   DIVA_CAPI_ADAPTER   * a;
4841     API_PARSE saved_parms[MAX_MSG_PARMS+1];
4842 #define MAXPARMSIDS 31
4843     byte   * parms[MAXPARMSIDS];
4844     byte   * add_i[4];
4845     byte   * multi_fac_parms[MAX_MULTI_IE];
4846     byte   * multi_pi_parms [MAX_MULTI_IE];
4847     byte   * multi_ssext_parms [MAX_MULTI_IE];
4848     byte   * multi_CiPN_parms [MAX_MULTI_IE];
4849
4850     byte   * multi_vswitch_parms [MAX_MULTI_IE];
4851
4852   byte ai_len;
4853     byte   *esc_chi = "";
4854     byte   *esc_law = "";
4855     byte   *pty_cai = "";
4856     byte   *esc_cr  = "";
4857     byte   *esc_profile = "";
4858
4859     byte facility[256];
4860   PLCI   * tplci = NULL;
4861   byte chi[] = "\x02\x18\x01";
4862   byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4863     byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4864   /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4865   /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4866   /* SMSG is situated at the end because its 0 (for compatibility reasons */
4867   /* (see Info_Mask Bit 4, first IE. then the message type)           */
4868     word parms_id[] =
4869          {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4870           UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4871           RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4872           CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4873           /* 14 FTY repl by ESC_CHI */
4874           /* 18 PI  repl by ESC_LAW */
4875          /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4876      word multi_fac_id[] = {1, FTY};
4877      word multi_pi_id[]  = {1, PI};
4878      word multi_CiPN_id[]  = {1, OAD};
4879      word multi_ssext_id[]  = {1, ESC_SSEXT};
4880
4881      word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4882
4883   byte   * cau;
4884   word ncci;
4885     byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4886     byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4887     byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4888     byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
4889   byte force_mt_info = false;
4890   byte dir;
4891   dword d;
4892   word w;
4893
4894   a = plci->adapter;
4895   Id = ((word)plci->Id<<8)|a->Id;
4896   PUT_WORD(&SS_Ind[4],0x0000);
4897
4898   if (plci->sig_remove_id)
4899   {
4900     plci->Sig.RNR = 2; /* discard */
4901     dbug(1,dprintf("SIG discard while remove pending"));
4902     return;
4903   }
4904   if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4905   dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4906     Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4907   if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4908   {
4909     plci->Sig.RNR = 1;
4910     return;
4911   }
4912   if(plci->Sig.Ind==HANGUP && plci->channels)
4913   {
4914     plci->Sig.RNR = 1;
4915     plci->hangup_flow_ctrl_timer++;
4916     /* recover the network layer after timeout */
4917     if(plci->hangup_flow_ctrl_timer==100)
4918     {
4919       dbug(1,dprintf("Exceptional disc"));
4920       plci->Sig.RNR = 0;
4921       plci->hangup_flow_ctrl_timer = 0;
4922       for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4923       {
4924         if (a->ncci_plci[ncci] == plci->Id)
4925         {
4926           cleanup_ncci_data (plci, ncci);
4927           if(plci->channels)plci->channels--;
4928           if (plci->appl)
4929             sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4930         }
4931       }
4932       if (plci->appl)
4933         sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4934       plci_remove(plci);
4935       plci->State=IDLE;
4936     }
4937     return;
4938   }
4939
4940   /* do first parse the info with no OAD in, because OAD will be converted */
4941   /* first the multiple facility IE, then mult. progress ind.              */
4942   /* then the parameters for the info_ind + conn_ind                       */
4943   IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4944   IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4945   IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4946
4947   IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4948
4949   IndParse(plci,parms_id,parms,0);
4950   IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4951   esc_chi  = parms[14];
4952   esc_law  = parms[18];
4953   pty_cai  = parms[24];
4954   esc_cr   = parms[25];
4955   esc_profile = parms[27];
4956   if(esc_cr[0] && plci)
4957   {
4958     if(plci->cr_enquiry && plci->appl)
4959     {
4960       plci->cr_enquiry = false;
4961       /* d = MANU_ID            */
4962       /* w = m_command          */
4963       /* b = total length       */
4964       /* b = indication type    */
4965       /* b = length of all IEs  */
4966       /* b = IE1                */
4967       /* S = IE1 length + cont. */
4968       /* b = IE2                */
4969       /* S = IE2 length + cont. */
4970       sendf(plci->appl,
4971         _MANUFACTURER_I,
4972         Id,
4973         0,
4974         "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4975         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);
4976     }
4977   }
4978   /* create the additional info structure                                  */
4979   add_i[1] = parms[15]; /* KEY of additional info */
4980   add_i[2] = parms[11]; /* UUI of additional info */
4981   ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4982
4983   /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4984   /* indication returns by the card if requested by the function           */
4985   /* AutomaticLaw() after driver init                                      */
4986   if (a->automatic_law<4)
4987   {
4988     if(esc_law[0]){
4989       if(esc_law[2]){
4990         dbug(0,dprintf("u-Law selected"));
4991         a->u_law = 1;
4992       }
4993       else {
4994         dbug(0,dprintf("a-Law selected"));
4995         a->u_law = 0;
4996       }
4997       a->automatic_law = 4;
4998       if(plci==a->automatic_lawPLCI) {
4999         plci->internal_command = 0;
5000         sig_req(plci,REMOVE,0);
5001         send_req(plci);
5002         a->automatic_lawPLCI = NULL;
5003       }
5004     }
5005     if (esc_profile[0])
5006     {
5007       dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
5008         UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
5009         GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
5010         GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
5011
5012       a->profile.Global_Options &= 0x000000ffL;
5013       a->profile.B1_Protocols &= 0x000003ffL;
5014       a->profile.B2_Protocols &= 0x00001fdfL;
5015       a->profile.B3_Protocols &= 0x000000b7L;
5016
5017       a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
5018         GL_BCHANNEL_OPERATION_SUPPORTED;
5019       a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
5020       a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
5021       a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
5022       a->manufacturer_features = GET_DWORD (&esc_profile[46]);
5023       a->man_profile.private_options = 0;
5024
5025       if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5026       {
5027         a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5028         a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5029       }
5030
5031
5032       if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5033         a->man_profile.private_options |= 1L << PRIVATE_RTP;
5034       a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
5035       a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
5036
5037
5038       if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5039         a->man_profile.private_options |= 1L << PRIVATE_T38;
5040
5041
5042       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5043         a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5044
5045
5046       if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5047         a->man_profile.private_options |= 1L << PRIVATE_V18;
5048
5049
5050       if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5051         a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5052
5053
5054       if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5055         a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5056
5057
5058       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5059         a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5060
5061
5062       if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5063         a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5064
5065
5066       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5067         a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5068
5069     }
5070     else
5071     {
5072       a->profile.Global_Options &= 0x0000007fL;
5073       a->profile.B1_Protocols &= 0x000003dfL;
5074       a->profile.B2_Protocols &= 0x00001adfL;
5075       a->profile.B3_Protocols &= 0x000000b7L;
5076       a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5077     }
5078     if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5079       MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5080     {
5081       a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5082     }
5083     a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5084     dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5085       UnMapController (a->Id), a->profile.Global_Options,
5086       a->profile.B1_Protocols, a->profile.B2_Protocols,
5087       a->profile.B3_Protocols, a->manufacturer_features));
5088   }
5089   /* codec plci for the handset/hook state support is just an internal id  */
5090   if(plci!=a->AdvCodecPLCI)
5091   {
5092     force_mt_info =  SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5093     force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5094     SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5095     SendInfo(plci,Id, parms, force_mt_info);
5096
5097     VSwitchReqInd(plci,Id,multi_vswitch_parms);
5098
5099   }
5100
5101   /* switch the codec to the b-channel                                     */
5102   if(esc_chi[0] && plci && !plci->SuppState){
5103     plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5104     mixer_set_bchannel_id_esc (plci, plci->b_channel);
5105     dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5106     if(plci->tel==ADV_VOICE && plci->appl) {
5107       SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5108     }
5109   }
5110
5111   if(plci->appl) Number = plci->appl->Number++;
5112
5113   switch(plci->Sig.Ind) {
5114   /* Response to Get_Supported_Services request */
5115   case S_SUPPORTED:
5116     dbug(1,dprintf("S_Supported"));
5117     if(!plci->appl) break;
5118     if(pty_cai[0]==4)
5119     {
5120       PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
5121     }
5122     else
5123     {
5124       PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5125     }
5126     PUT_WORD (&CF_Ind[1], 0);
5127     PUT_WORD (&CF_Ind[4], 0);
5128     sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5129     plci_remove(plci);
5130     break;
5131                     
5132   /* Supplementary Service rejected */
5133   case S_SERVICE_REJ:
5134     dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5135     if(!pty_cai[0]) break;
5136     switch (pty_cai[5])
5137     {
5138     case ECT_EXECUTE:
5139     case THREE_PTY_END:
5140     case THREE_PTY_BEGIN:
5141       if(!plci->relatedPTYPLCI) break;
5142       tplci = plci->relatedPTYPLCI;
5143       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5144       if(tplci->tel) rId|=EXT_CONTROLLER;
5145       if(pty_cai[5]==ECT_EXECUTE)
5146       {
5147         PUT_WORD(&SS_Ind[1],S_ECT);
5148
5149         plci->vswitchstate=0;
5150         plci->relatedPTYPLCI->vswitchstate=0;
5151
5152       }
5153       else
5154       {
5155         PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5156       }
5157       if(pty_cai[2]!=0xff)
5158       {
5159         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5160       }
5161       else
5162       {
5163         PUT_WORD(&SS_Ind[4],0x300E);
5164       }
5165       plci->relatedPTYPLCI = NULL;
5166       plci->ptyState = 0;
5167       sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5168       break;
5169
5170     case CALL_DEFLECTION:
5171       if(pty_cai[2]!=0xff)
5172       {
5173         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5174       }
5175       else
5176       {
5177         PUT_WORD(&SS_Ind[4],0x300E);
5178       }
5179       PUT_WORD(&SS_Ind[1],pty_cai[5]);
5180       for(i=0; i<max_appl; i++)
5181       {
5182         if(application[i].CDEnable)
5183         {
5184           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5185           application[i].CDEnable = false;
5186         }
5187       }
5188       break;
5189
5190     case DEACTIVATION_DIVERSION:
5191     case ACTIVATION_DIVERSION:
5192     case DIVERSION_INTERROGATE_CFU:
5193     case DIVERSION_INTERROGATE_CFB:
5194     case DIVERSION_INTERROGATE_CFNR:
5195     case DIVERSION_INTERROGATE_NUM:
5196     case CCBS_REQUEST:
5197     case CCBS_DEACTIVATE:
5198     case CCBS_INTERROGATE:
5199       if(!plci->appl) break;
5200       if(pty_cai[2]!=0xff)
5201       {
5202         PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5203       }
5204       else
5205       {
5206         PUT_WORD(&Interr_Err_Ind[4],0x300E);
5207       }
5208       switch (pty_cai[5])
5209       {
5210         case DEACTIVATION_DIVERSION:
5211           dbug(1,dprintf("Deact_Div"));
5212           Interr_Err_Ind[0]=0x9;
5213           Interr_Err_Ind[3]=0x6;
5214           PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5215           break;
5216         case ACTIVATION_DIVERSION:
5217           dbug(1,dprintf("Act_Div"));
5218           Interr_Err_Ind[0]=0x9;
5219           Interr_Err_Ind[3]=0x6;
5220           PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5221           break;
5222         case DIVERSION_INTERROGATE_CFU:
5223         case DIVERSION_INTERROGATE_CFB:
5224         case DIVERSION_INTERROGATE_CFNR:
5225           dbug(1,dprintf("Interr_Div"));
5226           Interr_Err_Ind[0]=0xa;
5227           Interr_Err_Ind[3]=0x7;
5228           PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5229           break;
5230         case DIVERSION_INTERROGATE_NUM:
5231           dbug(1,dprintf("Interr_Num"));
5232           Interr_Err_Ind[0]=0xa;
5233           Interr_Err_Ind[3]=0x7;
5234           PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5235           break;
5236         case CCBS_REQUEST:
5237           dbug(1,dprintf("CCBS Request"));
5238           Interr_Err_Ind[0]=0xd;
5239           Interr_Err_Ind[3]=0xa;
5240           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5241           break;
5242         case CCBS_DEACTIVATE:
5243           dbug(1,dprintf("CCBS Deactivate"));
5244           Interr_Err_Ind[0]=0x9;
5245           Interr_Err_Ind[3]=0x6;
5246           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5247           break;
5248         case CCBS_INTERROGATE:
5249           dbug(1,dprintf("CCBS Interrogate"));
5250           Interr_Err_Ind[0]=0xb;
5251           Interr_Err_Ind[3]=0x8;
5252           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5253           break;
5254       }
5255       PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5256       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5257       plci_remove(plci);
5258       break;
5259     case ACTIVATION_MWI:      
5260     case DEACTIVATION_MWI:
5261       if(pty_cai[5]==ACTIVATION_MWI)
5262       {
5263         PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5264       }
5265       else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5266       
5267       if(pty_cai[2]!=0xff)
5268       {
5269         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5270       }
5271       else
5272       {
5273         PUT_WORD(&SS_Ind[4],0x300E);
5274       }
5275
5276       if(plci->cr_enquiry)
5277       {
5278         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5279         plci_remove(plci);
5280       }
5281       else
5282       {
5283         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5284       }
5285       break;
5286     case CONF_ADD: /* ERROR */
5287     case CONF_BEGIN:
5288     case CONF_DROP:
5289     case CONF_ISOLATE:
5290     case CONF_REATTACH:
5291       CONF_Ind[0]=9;
5292       CONF_Ind[3]=6;   
5293       switch(pty_cai[5])
5294       {
5295       case CONF_BEGIN:
5296           PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5297           plci->ptyState = 0;
5298           break;
5299       case CONF_DROP:
5300           CONF_Ind[0]=5;
5301           CONF_Ind[3]=2;
5302           PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5303           plci->ptyState = CONNECTED;
5304           break;
5305       case CONF_ISOLATE:
5306           CONF_Ind[0]=5;
5307           CONF_Ind[3]=2;
5308           PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5309           plci->ptyState = CONNECTED;
5310           break;
5311       case CONF_REATTACH:
5312           CONF_Ind[0]=5;
5313           CONF_Ind[3]=2;
5314           PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5315           plci->ptyState = CONNECTED;
5316           break;
5317       case CONF_ADD:
5318           PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5319           plci->relatedPTYPLCI = NULL;
5320           tplci=plci->relatedPTYPLCI;
5321           if(tplci) tplci->ptyState = CONNECTED;
5322           plci->ptyState = CONNECTED;
5323           break;
5324       }
5325           
5326       if(pty_cai[2]!=0xff)
5327       {
5328         PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5329       }
5330       else
5331       {
5332         PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5333                                             within the required time */
5334       }
5335
5336       PUT_DWORD(&CONF_Ind[6],0x0);
5337       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5338       break;
5339     }
5340     break;
5341
5342   /* Supplementary Service indicates success */
5343   case S_SERVICE:
5344     dbug(1,dprintf("Service_Ind"));
5345     PUT_WORD (&CF_Ind[4], 0);
5346     switch (pty_cai[5])
5347     {
5348     case THREE_PTY_END:
5349     case THREE_PTY_BEGIN:
5350     case ECT_EXECUTE:
5351       if(!plci->relatedPTYPLCI) break;
5352       tplci = plci->relatedPTYPLCI;
5353       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5354       if(tplci->tel) rId|=EXT_CONTROLLER;
5355       if(pty_cai[5]==ECT_EXECUTE)
5356       {
5357         PUT_WORD(&SS_Ind[1],S_ECT);
5358
5359         if(plci->vswitchstate!=3)
5360         {
5361
5362         plci->ptyState = IDLE;
5363         plci->relatedPTYPLCI = NULL;
5364         plci->ptyState = 0;
5365
5366         }
5367
5368         dbug(1,dprintf("ECT OK"));
5369         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5370
5371
5372
5373       }
5374       else
5375       {
5376         switch (plci->ptyState)
5377         {
5378         case S_3PTY_BEGIN:
5379           plci->ptyState = CONNECTED;
5380           dbug(1,dprintf("3PTY ON"));
5381           break;
5382
5383         case S_3PTY_END:
5384           plci->ptyState = IDLE;
5385           plci->relatedPTYPLCI = NULL;
5386           plci->ptyState = 0;
5387           dbug(1,dprintf("3PTY OFF"));
5388           break;
5389         }
5390         PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5391         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5392       }
5393       break;
5394
5395     case CALL_DEFLECTION:
5396       PUT_WORD(&SS_Ind[1],pty_cai[5]);
5397       for(i=0; i<max_appl; i++)
5398       {
5399         if(application[i].CDEnable)
5400         {
5401           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5402           application[i].CDEnable = false;
5403         }
5404       }
5405       break;
5406
5407     case DEACTIVATION_DIVERSION:
5408     case ACTIVATION_DIVERSION:
5409       if(!plci->appl) break;
5410       PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
5411       PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5412       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5413       plci_remove(plci);
5414       break;
5415
5416     case DIVERSION_INTERROGATE_CFU:
5417     case DIVERSION_INTERROGATE_CFB:
5418     case DIVERSION_INTERROGATE_CFNR:
5419     case DIVERSION_INTERROGATE_NUM:
5420     case CCBS_REQUEST:
5421     case CCBS_DEACTIVATE:
5422     case CCBS_INTERROGATE:
5423       if(!plci->appl) break;
5424       switch (pty_cai[5])
5425       {
5426         case DIVERSION_INTERROGATE_CFU:
5427         case DIVERSION_INTERROGATE_CFB:
5428         case DIVERSION_INTERROGATE_CFNR:
5429           dbug(1,dprintf("Interr_Div"));
5430           PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5431           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5432           break;
5433         case DIVERSION_INTERROGATE_NUM:
5434           dbug(1,dprintf("Interr_Num"));
5435           PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5436           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5437           break;
5438         case CCBS_REQUEST:
5439           dbug(1,dprintf("CCBS Request"));
5440           PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
5441           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5442           break;
5443         case CCBS_DEACTIVATE:
5444           dbug(1,dprintf("CCBS Deactivate"));
5445           PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5446           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5447           break;
5448         case CCBS_INTERROGATE:
5449           dbug(1,dprintf("CCBS Interrogate"));
5450           PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5451           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5452           break;
5453       }
5454       PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5455       PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
5456       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5457       plci_remove(plci);
5458       break;
5459
5460     case ACTIVATION_MWI:
5461     case DEACTIVATION_MWI:
5462       if(pty_cai[5]==ACTIVATION_MWI)
5463       {
5464         PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5465       }
5466       else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5467       if(plci->cr_enquiry)
5468       {
5469         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5470         plci_remove(plci);
5471       }
5472       else
5473       {
5474         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5475       }
5476       break;
5477     case MWI_INDICATION:
5478       if(pty_cai[0]>=0x12)
5479       {
5480         PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
5481         pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5482         pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5483         if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5484         {
5485           if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5486           {
5487             sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5488             plci_remove(plci);
5489             return;
5490           }
5491           else  sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5492           pty_cai[0]=0;
5493         }
5494         else
5495         {
5496           for(i=0; i<max_appl; i++)
5497           {                     
5498             if(a->Notification_Mask[i]&SMASK_MWI)
5499             {
5500               sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5501               pty_cai[0]=0;
5502             }
5503           }
5504         }
5505
5506         if(!pty_cai[0])
5507         { /* acknowledge */
5508           facility[2]= 0; /* returncode */
5509         }
5510         else facility[2]= 0xff;
5511       }
5512       else
5513       {
5514         /* reject */
5515         facility[2]= 0xff; /* returncode */
5516       }
5517       facility[0]= 2;
5518       facility[1]= MWI_RESPONSE; /* Function */
5519       add_p(plci,CAI,facility);
5520       add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5521       sig_req(plci,S_SERVICE,0);
5522       send_req(plci);
5523       plci->command = 0;
5524       next_internal_command (Id, plci);
5525       break;
5526     case CONF_ADD: /* OK */
5527     case CONF_BEGIN:
5528     case CONF_DROP:
5529     case CONF_ISOLATE:
5530     case CONF_REATTACH:
5531     case CONF_PARTYDISC:
5532       CONF_Ind[0]=9;
5533       CONF_Ind[3]=6;
5534       switch(pty_cai[5])
5535       {
5536       case CONF_BEGIN:
5537           PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5538           if(pty_cai[0]==6)
5539           {
5540               d=pty_cai[6];
5541               PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5542           }
5543           else
5544           {
5545               PUT_DWORD(&CONF_Ind[6],0x0);
5546           }
5547           break;
5548       case CONF_ISOLATE:
5549           PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5550           CONF_Ind[0]=5;
5551           CONF_Ind[3]=2;
5552           break;
5553       case CONF_REATTACH:
5554           PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5555           CONF_Ind[0]=5;
5556           CONF_Ind[3]=2;
5557           break;
5558       case CONF_DROP:
5559           PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5560           CONF_Ind[0]=5;
5561           CONF_Ind[3]=2;
5562           break;
5563       case CONF_ADD:
5564           PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5565           d=pty_cai[6];
5566           PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5567           tplci=plci->relatedPTYPLCI;
5568           if(tplci) tplci->ptyState = CONNECTED;
5569           break;
5570       case CONF_PARTYDISC:
5571           CONF_Ind[0]=7;
5572           CONF_Ind[3]=4;          
5573           PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5574           d=pty_cai[6];
5575           PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5576           break;
5577       }
5578       plci->ptyState = CONNECTED;
5579       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5580       break;
5581     case CCBS_INFO_RETAIN:
5582     case CCBS_ERASECALLLINKAGEID:
5583     case CCBS_STOP_ALERTING:
5584       CONF_Ind[0]=5;
5585       CONF_Ind[3]=2;
5586       switch(pty_cai[5])
5587       {
5588       case CCBS_INFO_RETAIN:
5589         PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5590         break;
5591       case CCBS_STOP_ALERTING:
5592         PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5593     break;
5594       case CCBS_ERASECALLLINKAGEID:
5595         PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5596         CONF_Ind[0]=7;
5597         CONF_Ind[3]=4;
5598         CONF_Ind[6]=0;
5599         CONF_Ind[7]=0;
5600         break;
5601       }      
5602       w=pty_cai[6];
5603       PUT_WORD(&CONF_Ind[4],w); /* PartyID */
5604
5605       if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5606       {
5607         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5608       }
5609       else
5610       {
5611         for(i=0; i<max_appl; i++)
5612             if(a->Notification_Mask[i]&SMASK_CCBS)
5613                 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5614       }
5615       break;
5616     }
5617     break;
5618   case CALL_HOLD_REJ:
5619     cau = parms[7];
5620     if(cau)
5621     {
5622       i = _L3_CAUSE | cau[2];
5623       if(cau[2]==0) i = 0x3603;
5624     }
5625     else
5626     {
5627       i = 0x3603;
5628     }
5629     PUT_WORD(&SS_Ind[1],S_HOLD);
5630     PUT_WORD(&SS_Ind[4],i);
5631     if(plci->SuppState == HOLD_REQUEST)
5632     {
5633       plci->SuppState = IDLE;
5634       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5635     }
5636     break;
5637
5638   case CALL_HOLD_ACK:
5639     if(plci->SuppState == HOLD_REQUEST)
5640     {
5641       plci->SuppState = CALL_HELD;
5642       CodecIdCheck(a, plci);
5643       start_internal_command (Id, plci, hold_save_command);
5644     }
5645     break;
5646
5647   case CALL_RETRIEVE_REJ:
5648     cau = parms[7];
5649     if(cau)
5650     {
5651       i = _L3_CAUSE | cau[2];
5652       if(cau[2]==0) i = 0x3603;
5653     }
5654     else
5655     {
5656       i = 0x3603;
5657     }
5658     PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5659     PUT_WORD(&SS_Ind[4],i);
5660     if(plci->SuppState == RETRIEVE_REQUEST)
5661     {
5662       plci->SuppState = CALL_HELD;
5663       CodecIdCheck(a, plci);
5664       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5665     }
5666     break;
5667
5668   case CALL_RETRIEVE_ACK:
5669     PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5670     if(plci->SuppState == RETRIEVE_REQUEST)
5671     {
5672       plci->SuppState = IDLE;
5673       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5674       plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5675       if(plci->tel)
5676       {
5677         mixer_set_bchannel_id_esc (plci, plci->b_channel);
5678         dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5679         SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5680         if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5681         {
5682           dbug(1,dprintf("Get B-ch"));
5683           start_internal_command (Id, plci, retrieve_restore_command);
5684         }
5685         else
5686           sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5687       }
5688       else
5689         start_internal_command (Id, plci, retrieve_restore_command);
5690     }
5691     break;
5692
5693   case INDICATE_IND:
5694     if(plci->State != LISTENING) {
5695       sig_req(plci,HANGUP,0);
5696       send_req(plci);
5697       break;
5698     }
5699     cip = find_cip(a,parms[4],parms[6]);
5700     cip_mask = 1L<<cip;
5701     dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5702     clear_c_ind_mask (plci);
5703     if (!remove_started && !a->adapter_disabled)
5704     {
5705       set_c_ind_mask_bit (plci, MAX_APPL);
5706       group_optimization(a, plci);
5707       for(i=0; i<max_appl; i++) {
5708         if(application[i].Id
5709         && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5710         && CPN_filter_ok(parms[0],a,i)
5711         && test_group_ind_mask_bit (plci, i) ) {
5712           dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5713           set_c_ind_mask_bit (plci, i);
5714           dump_c_ind_mask (plci);
5715           plci->State = INC_CON_PENDING;
5716           plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5717             CALL_DIR_IN | CALL_DIR_ANSWER;
5718           if(esc_chi[0]) {
5719             plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5720             mixer_set_bchannel_id_esc (plci, plci->b_channel);
5721           }
5722           /* if a listen on the ext controller is done, check if hook states */
5723           /* are supported or if just a on board codec must be activated     */
5724           if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5725             if(a->profile.Global_Options & HANDSET)
5726               plci->tel = ADV_VOICE;
5727             else if(a->profile.Global_Options & ON_BOARD_CODEC)
5728               plci->tel = CODEC;
5729             if(plci->tel) Id|=EXT_CONTROLLER;
5730             a->codec_listen[i] = plci;
5731           }
5732
5733           sendf(&application[i],_CONNECT_I,Id,0,
5734                 "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5735                              parms[0],    /* CalledPartyNumber   */
5736                              multi_CiPN_parms[0],    /* CallingPartyNumber  */
5737                              parms[2],    /* CalledPartySubad    */
5738                              parms[3],    /* CallingPartySubad   */
5739                              parms[4],    /* BearerCapability    */
5740                              parms[5],    /* LowLC               */
5741                              parms[6],    /* HighLC              */
5742                              ai_len,      /* nested struct add_i */
5743                              add_i[0],    /* B channel info    */
5744                              add_i[1],    /* keypad facility   */
5745                              add_i[2],    /* user user data    */
5746                              add_i[3],    /* nested facility   */
5747                              multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5748                              );
5749           SendSSExtInd(&application[i],
5750                         plci,
5751                         Id,
5752                         multi_ssext_parms);
5753           SendSetupInfo(&application[i],
5754                         plci,
5755                         Id,
5756                         parms,
5757                         SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
5758         }
5759       }
5760       clear_c_ind_mask_bit (plci, MAX_APPL);
5761       dump_c_ind_mask (plci);
5762     }
5763     if(c_ind_mask_empty (plci)) {
5764       sig_req(plci,HANGUP,0);
5765       send_req(plci);
5766       plci->State = IDLE;
5767     }
5768     plci->notifiedcall = 0;
5769     a->listen_active--;
5770     listen_check(a);
5771     break;
5772
5773   case CALL_PEND_NOTIFY:
5774     plci->notifiedcall = 1;
5775     listen_check(a);
5776     break;
5777
5778   case CALL_IND:
5779   case CALL_CON:
5780     if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5781     {
5782       if(plci->internal_command==PERM_COD_CONN_PEND)
5783       {
5784         if(plci->State==ADVANCED_VOICE_NOSIG)
5785         {
5786           dbug(1,dprintf("***Codec OK"));
5787           if(a->AdvSignalPLCI)
5788           {
5789             tplci = a->AdvSignalPLCI;
5790             if(tplci->spoofed_msg)
5791             {
5792               dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5793               tplci->command = 0;
5794               tplci->internal_command = 0;
5795               x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5796               switch (tplci->spoofed_msg)
5797               {
5798               case CALL_RES:
5799                 tplci->command = _CONNECT_I|RESPONSE;
5800                 api_load_msg (&tplci->saved_msg, saved_parms);
5801                 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5802                 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5803                 {
5804                   /* early B3 connect (CIP mask bit 9) no release after a disc */
5805                   add_p(tplci,LLI,"\x01\x01");
5806                 }
5807                 add_s(tplci, CONN_NR, &saved_parms[2]);
5808                 add_s(tplci, LLC, &saved_parms[4]);
5809                 add_ai(tplci, &saved_parms[5]);
5810                 tplci->State = INC_CON_ACCEPT;
5811                 sig_req(tplci, CALL_RES,0);
5812                 send_req(tplci);
5813                 break;
5814
5815               case AWAITING_SELECT_B:
5816                 dbug(1,dprintf("Select_B continue"));
5817                 start_internal_command (x_Id, tplci, select_b_command);
5818                 break;
5819
5820               case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5821                 if(!tplci->Sig.Id)
5822                 {
5823                   dbug(1,dprintf("No SigID!"));
5824                   sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5825                   plci_remove(tplci);
5826                   break;
5827                 }
5828                 tplci->command = _MANUFACTURER_R;
5829                 api_load_msg (&tplci->saved_msg, saved_parms);
5830                 dir = saved_parms[2].info[0];
5831                 if(dir==1) {
5832                   sig_req(tplci,CALL_REQ,0);
5833                 }
5834                 else if(!dir){
5835                   sig_req(tplci,LISTEN_REQ,0);
5836                 }
5837                 send_req(tplci);
5838                 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5839                 break;
5840
5841               case (CALL_REQ|AWAITING_MANUF_CON):
5842                 sig_req(tplci,CALL_REQ,0);
5843                 send_req(tplci);
5844                 break;
5845
5846               case CALL_REQ:
5847                 if(!tplci->Sig.Id)
5848                 {
5849                   dbug(1,dprintf("No SigID!"));
5850                   sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5851                   plci_remove(tplci);
5852                   break;
5853                 }
5854                 tplci->command = _CONNECT_R;
5855                 api_load_msg (&tplci->saved_msg, saved_parms);
5856                 add_s(tplci,CPN,&saved_parms[1]);
5857                 add_s(tplci,DSA,&saved_parms[3]);
5858                 add_ai(tplci,&saved_parms[9]);
5859                 sig_req(tplci,CALL_REQ,0);
5860                 send_req(tplci);
5861                 break;
5862
5863               case CALL_RETRIEVE:
5864                 tplci->command = C_RETRIEVE_REQ;
5865                 sig_req(tplci,CALL_RETRIEVE,0);
5866                 send_req(tplci);
5867                 break;
5868               }
5869               tplci->spoofed_msg = 0;
5870               if (tplci->internal_command == 0)
5871                 next_internal_command (x_Id, tplci);
5872             }
5873           }
5874           next_internal_command (Id, plci);
5875           break;
5876         }
5877         dbug(1,dprintf("***Codec Hook Init Req"));
5878         plci->internal_command = PERM_COD_HOOK;
5879         add_p(plci,FTY,"\x01\x09");             /* Get Hook State*/
5880         sig_req(plci,TEL_CTRL,0);
5881         send_req(plci);
5882       }
5883     }
5884     else if(plci->command != _MANUFACTURER_R  /* old style permanent connect */
5885     && plci->State!=INC_ACT_PENDING)
5886     {
5887       mixer_set_bchannel_id_esc (plci, plci->b_channel);
5888       if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5889       {
5890         chi[2] = plci->b_channel;
5891         SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5892       }
5893       sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5894       plci->State = INC_ACT_PENDING;
5895     }
5896     break;
5897
5898   case TEL_CTRL:
5899     Number = 0;
5900     ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5901     if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5902       switch (ie[1]&0x91) {
5903         case 0x80:   /* hook off */
5904         case 0x81:
5905           if(plci->internal_command==PERM_COD_HOOK)
5906           {
5907             dbug(1,dprintf("init:hook_off"));
5908             plci->hook_state = ie[1];
5909             next_internal_command (Id, plci);
5910             break;
5911           }
5912           else /* ignore doubled hook indications */
5913           {
5914             if( ((plci->hook_state)&0xf0)==0x80)
5915             {
5916               dbug(1,dprintf("ignore hook"));
5917               break;
5918             }
5919             plci->hook_state = ie[1]&0x91;
5920           }
5921           /* check for incoming call pending */
5922           /* and signal '+'.Appl must decide */
5923           /* with connect_res if call must   */
5924           /* accepted or not                 */
5925           for(i=0, tplci=NULL;i<max_appl;i++){
5926             if(a->codec_listen[i]
5927             && (a->codec_listen[i]->State==INC_CON_PENDING
5928               ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5929               tplci = a->codec_listen[i];
5930               tplci->appl = &application[i];
5931             }
5932           }
5933           /* no incoming call, do outgoing call */
5934           /* and signal '+' if outg. setup   */
5935           if(!a->AdvSignalPLCI && !tplci){
5936             if((i=get_plci(a))) {
5937               a->AdvSignalPLCI = &a->plci[i-1];
5938               tplci = a->AdvSignalPLCI;
5939               tplci->tel  = ADV_VOICE;
5940               PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5941               if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5942                 /* early B3 connect (CIP mask bit 9) no release after a disc */
5943                 add_p(tplci,LLI,"\x01\x01");
5944               }
5945               add_p(tplci, CAI, voice_cai);
5946               add_p(tplci, OAD, a->TelOAD);
5947               add_p(tplci, OSA, a->TelOSA);
5948               add_p(tplci,SHIFT|6,NULL);
5949               add_p(tplci,SIN,"\x02\x01\x00");
5950               add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5951               sig_req(tplci,ASSIGN,DSIG_ID);
5952               a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5953               a->AdvSignalPLCI->command = 0;
5954               tplci->appl = a->AdvSignalAppl;
5955               tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5956               send_req(tplci);
5957             }
5958
5959           }
5960
5961           if(!tplci) break;
5962           Id = ((word)tplci->Id<<8)|a->Id;
5963           Id|=EXT_CONTROLLER;
5964           sendf(tplci->appl,
5965                 _FACILITY_I,
5966                 Id,
5967                 0,
5968                 "ws", (word)0, "\x01+");
5969           break;
5970
5971         case 0x90:   /* hook on  */
5972         case 0x91:
5973           if(plci->internal_command==PERM_COD_HOOK)
5974           {
5975             dbug(1,dprintf("init:hook_on"));
5976             plci->hook_state = ie[1]&0x91;
5977             next_internal_command (Id, plci);
5978             break;
5979           }
5980           else /* ignore doubled hook indications */
5981           {
5982             if( ((plci->hook_state)&0xf0)==0x90) break;
5983             plci->hook_state = ie[1]&0x91;
5984           }
5985           /* hangup the adv. voice call and signal '-' to the appl */
5986           if(a->AdvSignalPLCI) {
5987             Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5988             if(plci->tel) Id|=EXT_CONTROLLER;
5989             sendf(a->AdvSignalAppl,
5990                   _FACILITY_I,
5991                   Id,
5992                   0,
5993                   "ws", (word)0, "\x01-");
5994             a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5995             a->AdvSignalPLCI->command = 0;
5996             sig_req(a->AdvSignalPLCI,HANGUP,0);
5997             send_req(a->AdvSignalPLCI);
5998           }
5999           break;
6000       }
6001     }
6002     break;
6003
6004   case RESUME:
6005     clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
6006     PUT_WORD(&resume_cau[4],GOOD);
6007     sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6008     break;
6009
6010   case SUSPEND:
6011     clear_c_ind_mask (plci);
6012
6013     if (plci->NL.Id && !plci->nl_remove_id) {
6014       mixer_remove (plci);
6015       nl_req_ncci(plci,REMOVE,0);
6016     }
6017     if (!plci->sig_remove_id) {
6018       plci->internal_command = 0;
6019       sig_req(plci,REMOVE,0);
6020     }
6021     send_req(plci);
6022     if(!plci->channels) {
6023       sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6024       sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6025     }
6026     break;
6027
6028   case SUSPEND_REJ:
6029     break;
6030
6031   case HANGUP:
6032     plci->hangup_flow_ctrl_timer=0;
6033     if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6034     cau = parms[7];
6035     if(cau) {
6036       i = _L3_CAUSE | cau[2];
6037       if(cau[2]==0) i = 0;
6038       else if(cau[2]==8) i = _L1_ERROR;
6039       else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6040       else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6041     }
6042     else {
6043       i = _L3_ERROR;
6044     }
6045
6046     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6047     {
6048       for(i=0; i<max_appl; i++)
6049       {
6050         if(test_c_ind_mask_bit (plci, i))
6051           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6052       }
6053     }
6054     else
6055     {
6056       clear_c_ind_mask (plci);
6057     }
6058     if(!plci->appl)
6059     {
6060       if (plci->State == LISTENING)
6061       {
6062         plci->notifiedcall=0;
6063         a->listen_active--;
6064       }
6065       plci->State = INC_DIS_PENDING;
6066       if(c_ind_mask_empty (plci))
6067       {
6068         plci->State = IDLE;
6069         if (plci->NL.Id && !plci->nl_remove_id)
6070         {
6071           mixer_remove (plci);
6072           nl_req_ncci(plci,REMOVE,0);
6073         }
6074         if (!plci->sig_remove_id)
6075         {
6076           plci->internal_command = 0;
6077           sig_req(plci,REMOVE,0);
6078         }
6079         send_req(plci);
6080       }
6081     }
6082     else
6083     {
6084         /* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
6085         /* result in a second HANGUP! Don't generate another        */
6086         /* DISCONNECT                                               */
6087       if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6088       {
6089         if(plci->State==RESUMING)
6090         {
6091           PUT_WORD(&resume_cau[4],i);
6092           sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6093         }
6094         plci->State = INC_DIS_PENDING;
6095         sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6096       }
6097     }
6098     break;
6099
6100   case SSEXT_IND:
6101     SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6102     break;
6103
6104   case VSWITCH_REQ:
6105     VSwitchReqInd(plci,Id,multi_vswitch_parms);
6106     break;
6107   case VSWITCH_IND:
6108  if(plci->relatedPTYPLCI &&
6109   plci->vswitchstate==3 &&
6110   plci->relatedPTYPLCI->vswitchstate==3 &&
6111   parms[MAXPARMSIDS-1][0])
6112  {
6113   add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6114   sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6115   send_req(plci->relatedPTYPLCI);
6116  }
6117     else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6118     break;
6119
6120   }
6121 }
6122
6123
6124 static void SendSetupInfo(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms, byte Info_Sent_Flag)
6125 {
6126   word i;
6127   byte   * ie;
6128   word Info_Number;
6129   byte   * Info_Element;
6130   word Info_Mask = 0;
6131
6132   dbug(1,dprintf("SetupInfo"));
6133
6134   for(i=0; i<MAXPARMSIDS; i++) {
6135     ie = parms[i];
6136     Info_Number = 0;
6137     Info_Element = ie;
6138     if(ie[0]) {
6139       switch(i) {
6140       case 0:
6141         dbug(1,dprintf("CPN "));
6142         Info_Number = 0x0070;
6143         Info_Mask   = 0x80;
6144         Info_Sent_Flag = true;
6145         break;
6146       case 8:  /* display      */
6147         dbug(1,dprintf("display(%d)",i));
6148         Info_Number = 0x0028;
6149         Info_Mask = 0x04;
6150         Info_Sent_Flag = true;
6151         break;
6152       case 16: /* Channel Id */
6153         dbug(1,dprintf("CHI"));
6154         Info_Number = 0x0018;
6155         Info_Mask = 0x100;
6156         Info_Sent_Flag = true;
6157         mixer_set_bchannel_id (plci, Info_Element);
6158         break;
6159       case 19: /* Redirected Number */
6160         dbug(1,dprintf("RDN"));
6161         Info_Number = 0x0074;
6162         Info_Mask = 0x400;
6163         Info_Sent_Flag = true;
6164         break;
6165       case 20: /* Redirected Number extended */
6166         dbug(1,dprintf("RDX"));
6167         Info_Number = 0x0073;
6168         Info_Mask = 0x400;
6169         Info_Sent_Flag = true;
6170         break;
6171       case 22: /* Redirecing Number  */
6172         dbug(1,dprintf("RIN"));
6173         Info_Number = 0x0076;
6174         Info_Mask = 0x400;
6175         Info_Sent_Flag = true;
6176         break;
6177       default:
6178         Info_Number = 0;
6179         break;
6180       }
6181     }
6182
6183     if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6184       Info_Number = 0x8000 |5;
6185       Info_Mask = 0x10;
6186       Info_Element = "";
6187     }
6188
6189     if(Info_Sent_Flag && Info_Number){
6190       if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6191         sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6192       }
6193     }
6194   }
6195 }
6196
6197
6198 static void SendInfo(PLCI *plci, dword Id, byte **parms, byte iesent)
6199 {
6200   word i;
6201   word j;
6202   word k;
6203   byte   * ie;
6204   word Info_Number;
6205   byte   * Info_Element;
6206   word Info_Mask = 0;
6207   static byte charges[5] = {4,0,0,0,0};
6208   static byte cause[] = {0x02,0x80,0x00};
6209   APPL   *appl;
6210
6211   dbug(1,dprintf("InfoParse "));
6212
6213   if(
6214         !plci->appl
6215         && !plci->State
6216         && plci->Sig.Ind!=NCR_FACILITY
6217       )
6218   {
6219     dbug(1,dprintf("NoParse "));
6220     return;
6221   }
6222   cause[2] = 0;
6223   for(i=0; i<MAXPARMSIDS; i++) {
6224     ie = parms[i];
6225     Info_Number = 0;
6226     Info_Element = ie;
6227     if(ie[0]) {
6228       switch(i) {
6229       case 0:
6230         dbug(1,dprintf("CPN "));
6231         Info_Number = 0x0070;
6232         Info_Mask   = 0x80;
6233         break;
6234       case 7: /* ESC_CAU */
6235         dbug(1,dprintf("cau(0x%x)",ie[2]));
6236         Info_Number = 0x0008;
6237         Info_Mask = 0x00;
6238         cause[2] = ie[2];
6239         Info_Element = NULL;
6240         break;
6241       case 8:  /* display      */
6242         dbug(1,dprintf("display(%d)",i));
6243         Info_Number = 0x0028;
6244         Info_Mask = 0x04;
6245         break;
6246       case 9:  /* Date display */
6247         dbug(1,dprintf("date(%d)",i));
6248         Info_Number = 0x0029;
6249         Info_Mask = 0x02;
6250         break;
6251       case 10: /* charges */
6252         for(j=0;j<4;j++) charges[1+j] = 0;
6253         for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6254         for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6255         Info_Number = 0x4000;
6256         Info_Mask = 0x40;
6257         Info_Element = charges;
6258         break;
6259       case 11: /* user user info */
6260         dbug(1,dprintf("uui"));
6261         Info_Number = 0x007E;
6262         Info_Mask = 0x08;
6263         break;
6264       case 12: /* congestion receiver ready */
6265         dbug(1,dprintf("clRDY"));
6266         Info_Number = 0x00B0;
6267         Info_Mask = 0x08;
6268         Info_Element = "";
6269         break;
6270       case 13: /* congestion receiver not ready */
6271         dbug(1,dprintf("clNRDY"));
6272         Info_Number = 0x00BF;
6273         Info_Mask = 0x08;
6274         Info_Element = "";
6275         break;
6276       case 15: /* Keypad Facility */
6277         dbug(1,dprintf("KEY"));
6278         Info_Number = 0x002C;
6279         Info_Mask = 0x20;
6280         break;
6281       case 16: /* Channel Id */
6282         dbug(1,dprintf("CHI"));
6283         Info_Number = 0x0018;
6284         Info_Mask = 0x100;
6285         mixer_set_bchannel_id (plci, Info_Element);
6286         break;
6287       case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6288         dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6289         if(!cause[2] || cause[2]<0x80) break;  /* eg. layer 1 error */
6290         Info_Number = 0x0008;
6291         Info_Mask = 0x01;
6292         if(cause[2] != ie[2]) Info_Element = cause;
6293         break;
6294       case 19: /* Redirected Number */
6295         dbug(1,dprintf("RDN"));
6296         Info_Number = 0x0074;
6297         Info_Mask = 0x400;
6298         break;
6299       case 22: /* Redirecing Number  */
6300         dbug(1,dprintf("RIN"));
6301         Info_Number = 0x0076;
6302         Info_Mask = 0x400;
6303         break;
6304       case 23: /* Notification Indicator  */
6305         dbug(1,dprintf("NI"));
6306         Info_Number = (word)NI;
6307         Info_Mask = 0x210;
6308         break;
6309       case 26: /* Call State  */
6310         dbug(1,dprintf("CST"));
6311         Info_Number = (word)CST;
6312         Info_Mask = 0x01; /* do with cause i.e. for now */
6313         break;
6314       case MAXPARMSIDS-2:  /* Escape Message Type, must be the last indication */
6315         dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6316         Info_Number = 0x8000 |ie[3];
6317         if(iesent) Info_Mask = 0xffff;
6318         else  Info_Mask = 0x10;
6319         Info_Element = "";
6320         break;
6321       default:
6322         Info_Number  = 0;
6323         Info_Mask    = 0;
6324         Info_Element = "";
6325         break;
6326       }
6327     }
6328
6329     if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
6330     {
6331       for(j=0; j<max_appl; j++)
6332       {
6333         appl = &application[j];
6334         if(Info_Number
6335         && appl->Id
6336         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6337         {
6338           dbug(1,dprintf("NCR_Ind"));
6339           iesent=true;
6340           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6341         }
6342       }
6343     }
6344     else if(!plci->appl)
6345     { /* overlap receiving broadcast */
6346       if(Info_Number==CPN
6347       || Info_Number==KEY
6348       || Info_Number==NI
6349       || Info_Number==DSP
6350       || Info_Number==UUI )
6351       {
6352         for(j=0; j<max_appl; j++)
6353         {
6354           if(test_c_ind_mask_bit (plci, j))
6355           {
6356             dbug(1,dprintf("Ovl_Ind"));
6357             iesent=true;
6358             sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6359           }
6360         }
6361       }
6362     }               /* all other signalling states */
6363     else if(Info_Number
6364     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6365     {
6366       dbug(1,dprintf("Std_Ind"));
6367       iesent=true;
6368       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6369     }
6370   }
6371 }
6372
6373
6374 static byte SendMultiIE(PLCI *plci, dword Id, byte **parms, byte ie_type,
6375                         dword info_mask, byte setupParse)
6376 {
6377   word i;
6378   word j;
6379   byte   * ie;
6380   word Info_Number;
6381   byte   * Info_Element;
6382   APPL   *appl;
6383   word Info_Mask = 0;
6384   byte iesent=0;
6385
6386   if(
6387       !plci->appl
6388       && !plci->State
6389       && plci->Sig.Ind!=NCR_FACILITY
6390       && !setupParse
6391       )
6392   {
6393     dbug(1,dprintf("NoM-IEParse "));
6394     return 0;
6395   }
6396   dbug(1,dprintf("M-IEParse "));
6397
6398   for(i=0; i<MAX_MULTI_IE; i++)
6399   {
6400     ie = parms[i];
6401     Info_Number = 0;
6402     Info_Element = ie;
6403     if(ie[0])
6404     {
6405       dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6406       Info_Number = (word)ie_type;
6407       Info_Mask = (word)info_mask;
6408     }
6409
6410     if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
6411     {
6412       for(j=0; j<max_appl; j++)
6413       {
6414         appl = &application[j];
6415         if(Info_Number
6416         && appl->Id
6417         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6418         {
6419           iesent = true;
6420           dbug(1,dprintf("Mlt_NCR_Ind"));
6421           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6422         }
6423       }
6424     }
6425     else if(!plci->appl && Info_Number)
6426     {                                        /* overlap receiving broadcast */
6427       for(j=0; j<max_appl; j++)
6428       {
6429         if(test_c_ind_mask_bit (plci, j))
6430         {
6431           iesent = true;
6432           dbug(1,dprintf("Mlt_Ovl_Ind"));
6433           sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6434         }
6435       }
6436     }                                        /* all other signalling states */
6437     else if(Info_Number
6438     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6439     {
6440       iesent = true;
6441       dbug(1,dprintf("Mlt_Std_Ind"));
6442       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6443     }
6444   }
6445   return iesent;
6446 }
6447
6448 static void SendSSExtInd(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms)
6449 {
6450   word i;
6451    /* Format of multi_ssext_parms[i][]:
6452    0 byte length
6453    1 byte SSEXTIE
6454    2 byte SSEXT_REQ/SSEXT_IND
6455    3 byte length
6456    4 word SSExtCommand
6457    6... Params
6458    */
6459   if(
6460    plci
6461    && plci->State
6462    && plci->Sig.Ind!=NCR_FACILITY
6463     )
6464  for(i=0;i<MAX_MULTI_IE;i++)
6465     {
6466       if(parms[i][0]<6) continue;
6467    if(parms[i][2]==SSEXT_REQ) continue;
6468
6469    if(appl)
6470    {
6471     parms[i][0]=0; /* kill it */
6472     sendf(appl,_MANUFACTURER_I,
6473     Id,
6474     0,
6475     "dwS",
6476     _DI_MANU_ID,
6477     _DI_SSEXT_CTRL,
6478     &parms[i][3]);
6479    }
6480    else if(plci->appl)
6481    {
6482     parms[i][0]=0; /* kill it */
6483     sendf(plci->appl,_MANUFACTURER_I,
6484     Id,
6485     0,
6486     "dwS",
6487     _DI_MANU_ID,
6488     _DI_SSEXT_CTRL,
6489     &parms[i][3]);
6490    }
6491     }
6492 };
6493
6494 static void nl_ind(PLCI *plci)
6495 {
6496   byte ch;
6497   word ncci;
6498   dword Id;
6499   DIVA_CAPI_ADAPTER   * a;
6500   word NCCIcode;
6501   APPL   * APPLptr;
6502   word count;
6503   word Num;
6504   word i, ncpi_state;
6505   byte len, ncci_state;
6506   word msg;
6507   word info = 0;
6508   word fax_feature_bits;
6509   byte fax_send_edata_ack;
6510   static byte v120_header_buffer[2 + 3];
6511   static word fax_info[] = {
6512     0,                     /* T30_SUCCESS                        */
6513     _FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
6514     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
6515     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
6516     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
6517     _FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
6518     _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
6519     _FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
6520     _FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
6521     _FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
6522     _FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
6523     _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
6524     _FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
6525     _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
6526     _FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
6527     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
6528     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
6529     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
6530     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
6531     _FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
6532     _FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
6533     _FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
6534     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
6535     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
6536     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
6537     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
6538     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
6539     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
6540     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
6541     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
6542     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
6543     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
6544     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
6545     0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
6546     0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
6547     0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
6548     _FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
6549     _FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
6550     _FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
6551     _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
6552     _FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
6553     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6554     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
6555     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
6556     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
6557     _FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
6558     _FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
6559   };
6560
6561     byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6562
6563
6564   static word rtp_info[] = {
6565     GOOD,                  /* RTP_SUCCESS                       */
6566     0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
6567   };
6568
6569   static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6570   {
6571     0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6572     0x00000000, 0x00000000, 0x00000000, 0x00000000
6573   };
6574
6575   ch = plci->NL.IndCh;
6576   a = plci->adapter;
6577   ncci = a->ch_ncci[ch];
6578   Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6579   if(plci->tel) Id|=EXT_CONTROLLER;
6580   APPLptr = plci->appl;
6581   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",
6582     plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6583
6584   /* in the case if no connect_active_Ind was sent to the appl we wait for */
6585
6586   if (plci->nl_remove_id)
6587   {
6588     plci->NL.RNR = 2; /* discard */
6589     dbug(1,dprintf("NL discard while remove pending"));
6590     return;
6591   }
6592   if((plci->NL.Ind &0x0f)==N_CONNECT)
6593   {
6594     if(plci->State==INC_DIS_PENDING
6595     || plci->State==OUTG_DIS_PENDING
6596     || plci->State==IDLE)
6597     {
6598       plci->NL.RNR = 2; /* discard */
6599       dbug(1,dprintf("discard n_connect"));
6600       return;
6601     }
6602     if(plci->State < INC_ACT_PENDING)
6603     {
6604       plci->NL.RNR = 1; /* flow control */
6605       channel_x_off (plci, ch, N_XON_CONNECT_IND);
6606       return;
6607     }
6608   }
6609
6610   if(!APPLptr)                         /* no application or invalid data */
6611   {                                    /* while reloading the DSP        */
6612     dbug(1,dprintf("discard1"));
6613     plci->NL.RNR = 2;
6614     return;
6615   }
6616
6617   if (((plci->NL.Ind &0x0f) == N_UDATA)
6618      && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6619         || (plci->B2_prot == 7)
6620         || (plci->B3_prot == 7)) )
6621   {
6622     plci->ncpi_buffer[0] = 0;
6623
6624     ncpi_state = plci->ncpi_state;
6625     if (plci->NL.complete == 1)
6626     {
6627       byte  * data = &plci->NL.RBuffer->P[0];
6628
6629       if ((plci->NL.RBuffer->length >= 12)
6630         &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6631           ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6632       {
6633         word conn_opt, ncpi_opt = 0x00;
6634 /*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6635
6636         if (*data == DSP_UDATA_INDICATION_DCD_ON)
6637           plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6638         if (*data == DSP_UDATA_INDICATION_CTS_ON)
6639           plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6640
6641         data++;    /* indication code */
6642         data += 2; /* timestamp */
6643         if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6644           ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6645         data++;    /* connected norm */
6646         conn_opt = GET_WORD(data);
6647         data += 2; /* connected options */
6648
6649         PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6650
6651         if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6652         {
6653           ncpi_opt |= MDM_NCPI_ECM_V42;
6654         }
6655         else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6656         {
6657           ncpi_opt |= MDM_NCPI_ECM_MNP;
6658         }
6659         else
6660         {
6661           ncpi_opt |= MDM_NCPI_TRANSPARENT;
6662         }
6663         if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6664         {
6665           ncpi_opt |= MDM_NCPI_COMPRESSED;
6666         }
6667         PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6668         plci->ncpi_buffer[0] = 4;
6669
6670         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6671       }
6672     }
6673     if (plci->B3_prot == 7)
6674     {
6675       if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6676        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6677        && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6678       {
6679         a->ncci_state[ncci] = INC_ACT_PENDING;
6680         sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6681         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6682       }
6683     }
6684
6685     if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6686         & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6687      || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6688      || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6689
6690     {
6691       plci->NL.RNR = 2;
6692       return;
6693     }
6694   }
6695
6696   if(plci->NL.complete == 2)
6697     {
6698     if (((plci->NL.Ind &0x0f) == N_UDATA)
6699      && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6700     {
6701       switch(plci->RData[0].P[0])
6702       {
6703
6704       case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6705         if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6706           sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6707         break;
6708       case DTMF_UDATA_INDICATION_ANSWER_TONE:
6709         if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6710           sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6711         break;
6712       case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6713         dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6714         break;
6715       case DTMF_UDATA_INDICATION_DIGITS_SENT:
6716         dtmf_confirmation (Id, plci);
6717         break;
6718
6719
6720       case UDATA_INDICATION_MIXER_TAP_DATA:
6721         capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6722  i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6723  if (i != 0)
6724  {
6725    dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6726           dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6727  }
6728         break;
6729
6730
6731       case UDATA_INDICATION_MIXER_COEFS_SET:
6732         mixer_indication_coefs_set (Id, plci);
6733         break;
6734       case UDATA_INDICATION_XCONNECT_FROM:
6735         mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6736         break;
6737       case UDATA_INDICATION_XCONNECT_TO:
6738         mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6739         break;
6740
6741
6742       case LEC_UDATA_INDICATION_DISABLE_DETECT:
6743         ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6744         break;
6745
6746
6747
6748       default:
6749         break;
6750       }
6751     }
6752     else
6753   {
6754       if ((plci->RData[0].PLength != 0)
6755      && ((plci->B2_prot == B2_V120_ASYNC)
6756       || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6757       || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6758     {
6759
6760       sendf(plci->appl,_DATA_B3_I,Id,0,
6761             "dwww",
6762             plci->RData[1].P,
6763               (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6764             plci->RNum,
6765             plci->RFlags);
6766
6767     }
6768     else
6769     {
6770
6771       sendf(plci->appl,_DATA_B3_I,Id,0,
6772             "dwww",
6773             plci->RData[0].P,
6774             plci->RData[0].PLength,
6775             plci->RNum,
6776             plci->RFlags);
6777
6778     }
6779     }
6780     return;
6781   }
6782
6783   fax_feature_bits = 0;
6784   if((plci->NL.Ind &0x0f)==N_CONNECT ||
6785      (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6786      (plci->NL.Ind &0x0f)==N_DISC ||
6787      (plci->NL.Ind &0x0f)==N_EDATA ||
6788      (plci->NL.Ind &0x0f)==N_DISC_ACK)
6789   {
6790     info = 0;
6791     plci->ncpi_buffer[0] = 0;
6792     switch (plci->B3_prot) {
6793     case  0: /*XPARENT*/
6794     case  1: /*T.90 NL*/
6795       break;    /* no network control protocol info - jfr */
6796     case  2: /*ISO8202*/
6797     case  3: /*X25 DCE*/
6798       for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6799       plci->ncpi_buffer[0] = (byte)(i+3);
6800       plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6801       plci->ncpi_buffer[2] = 0;
6802       plci->ncpi_buffer[3] = 0;
6803       break;
6804     case  4: /*T.30 - FAX*/
6805     case  5: /*T.30 - FAX*/
6806       if(plci->NL.RLength>=sizeof(T30_INFO))
6807       {
6808         dbug(1,dprintf("FaxStatus %04x", ((T30_INFO   *)plci->NL.RBuffer->P)->code));
6809         len = 9;
6810         PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO   *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6811         fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
6812         i = (((T30_INFO   *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6813         if (plci->B3_prot == 5)
6814         {
6815           if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6816             i |= 0x8000; /* This is not an ECM connection */
6817           if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6818             i |= 0x4000; /* This is a connection with MMR compression */
6819           if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6820             i |= 0x2000; /* This is a connection with MR compression */
6821           if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6822             i |= 0x0004; /* More documents */
6823           if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6824             i |= 0x0002; /* Fax-polling indication */
6825         }
6826         dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6827         PUT_WORD(&(plci->ncpi_buffer[3]),i);
6828         PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO   *)plci->NL.RBuffer->P)->data_format);
6829         plci->ncpi_buffer[7] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_low;
6830         plci->ncpi_buffer[8] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_high;
6831         plci->ncpi_buffer[len] = 0;
6832         if(((T30_INFO   *)plci->NL.RBuffer->P)->station_id_len)
6833         {
6834           plci->ncpi_buffer[len] = 20;
6835           for (i = 0; i < 20; i++)
6836             plci->ncpi_buffer[++len] = ((T30_INFO   *)plci->NL.RBuffer->P)->station_id[i];
6837         }
6838         if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6839         {
6840           if (((T30_INFO   *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6841             info = fax_info[((T30_INFO   *)plci->NL.RBuffer->P)->code];
6842           else
6843             info = _FAX_PROTOCOL_ERROR;
6844         }
6845
6846         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6847           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6848         {
6849           i = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((T30_INFO   *)plci->NL.RBuffer->P)->head_line_len;
6850           while (i < plci->NL.RBuffer->length)
6851             plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6852         }
6853
6854         plci->ncpi_buffer[0] = len;
6855         fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
6856         PUT_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6857
6858         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6859  if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6860          || (((plci->NL.Ind &0x0f) == N_CONNECT)
6861           && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6862          || (((plci->NL.Ind &0x0f) == N_EDATA)
6863           && ((((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6864            || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6865            || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6866  {
6867           plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6868  }
6869  if (((plci->NL.Ind &0x0f) == N_DISC)
6870   || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
6871   || (((plci->NL.Ind &0x0f) == N_EDATA)
6872    && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6873  {
6874           plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6875  }
6876       }
6877       break;
6878
6879     case B3_RTP:
6880       if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6881       {
6882         if (plci->NL.RLength != 0)
6883         {
6884           info = rtp_info[plci->NL.RBuffer->P[0]];
6885           plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6886           for (i = 1; i < plci->NL.RLength; i++)
6887             plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6888         }
6889       }
6890       break;
6891
6892     }
6893     plci->NL.RNR = 2;
6894   }
6895   switch(plci->NL.Ind &0x0f) {
6896   case N_EDATA:
6897     if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6898     {
6899       dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6900         ((T30_INFO   *)plci->NL.RBuffer->P)->code));
6901       fax_send_edata_ack = (((T30_INFO   *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6902
6903       if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6904        && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6905        && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6906        && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6907        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6908        && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6909       {
6910         ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code;
6911         sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
6912           (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6913         plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6914  if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6915    fax_send_edata_ack = false;
6916       }
6917
6918       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6919       {
6920         switch (((T30_INFO   *)plci->NL.RBuffer->P)->code)
6921         {
6922         case EDATA_T30_DIS:
6923           if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6924            && !(GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6925            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6926            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6927           {
6928             a->ncci_state[ncci] = INC_ACT_PENDING;
6929             if (plci->B3_prot == 4)
6930               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6931             else
6932               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6933             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6934           }
6935           break;
6936
6937         case EDATA_T30_TRAIN_OK:
6938           if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6939            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6940            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6941           {
6942             if (plci->B3_prot == 4)
6943               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6944             else
6945               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6946             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6947           }
6948           break;
6949
6950         case EDATA_T30_EOP_CAPI:
6951           if (a->ncci_state[ncci] == CONNECTED)
6952           {
6953             sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
6954             a->ncci_state[ncci] = INC_DIS_PENDING;
6955             plci->ncpi_state = 0;
6956      fax_send_edata_ack = false;
6957           }
6958           break;
6959         }
6960       }
6961       else
6962       {
6963         switch (((T30_INFO   *)plci->NL.RBuffer->P)->code)
6964         {
6965         case EDATA_T30_TRAIN_OK:
6966           if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6967            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6968            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6969           {
6970             if (plci->B3_prot == 4)
6971               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6972             else
6973               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6974             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6975           }
6976           break;
6977         }
6978       }
6979       if (fax_send_edata_ack)
6980       {
6981         ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code;
6982  plci->fax_edata_ack_length = 1;
6983         start_internal_command (Id, plci, fax_edata_ack_command);
6984       }
6985     }
6986     else
6987     {
6988       dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6989     }
6990     break;
6991   case N_CONNECT:
6992     if (!a->ch_ncci[ch])
6993     {
6994       ncci = get_ncci (plci, ch, 0);
6995       Id = (Id & 0xffff) | (((dword) ncci) << 16);
6996     }
6997     dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6998       ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6999
7000     msg = _CONNECT_B3_I;
7001     if (a->ncci_state[ncci] == IDLE)
7002       plci->channels++;
7003     else if (plci->B3_prot == 1)
7004       msg = _CONNECT_B3_T90_ACTIVE_I;
7005
7006     a->ncci_state[ncci] = INC_CON_PENDING;
7007     if(plci->B3_prot == 4)
7008       sendf(plci->appl,msg,Id,0,"s","");
7009     else
7010       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7011     break;
7012   case N_CONNECT_ACK:
7013     dbug(1,dprintf("N_connect_Ack"));
7014     if (plci->internal_command_queue[0]
7015      && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
7016       || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
7017       || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
7018     {
7019       (*(plci->internal_command_queue[0]))(Id, plci, 0);
7020       if (!plci->internal_command)
7021         next_internal_command (Id, plci);
7022       break;
7023     }
7024     msg = _CONNECT_B3_ACTIVE_I;
7025     if (plci->B3_prot == 1)
7026     {
7027       if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7028         msg = _CONNECT_B3_T90_ACTIVE_I;
7029       a->ncci_state[ncci] = INC_ACT_PENDING;
7030       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7031     }
7032     else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7033     {
7034       if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7035        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7036        && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7037       {
7038         a->ncci_state[ncci] = INC_ACT_PENDING;
7039         if (plci->B3_prot == 4)
7040           sendf(plci->appl,msg,Id,0,"s","");
7041         else
7042           sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7043         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7044       }
7045     }
7046     else
7047     {
7048       a->ncci_state[ncci] = INC_ACT_PENDING;
7049       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7050     }
7051     if (plci->adjust_b_restore)
7052     {
7053       plci->adjust_b_restore = false;
7054       start_internal_command (Id, plci, adjust_b_restore);
7055     }
7056     break;
7057   case N_DISC:
7058   case N_DISC_ACK:
7059     if (plci->internal_command_queue[0]
7060      && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7061       || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7062       || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7063     {
7064       (*(plci->internal_command_queue[0]))(Id, plci, 0);
7065       if (!plci->internal_command)
7066         next_internal_command (Id, plci);
7067     }
7068     ncci_state = a->ncci_state[ncci];
7069     ncci_remove (plci, ncci, false);
7070
7071         /* with N_DISC or N_DISC_ACK the IDI frees the respective   */
7072         /* channel, so we cannot store the state in ncci_state! The */
7073         /* information which channel we received a N_DISC is thus   */
7074         /* stored in the inc_dis_ncci_table buffer.                 */
7075     for(i=0; plci->inc_dis_ncci_table[i]; i++);
7076     plci->inc_dis_ncci_table[i] = (byte) ncci;
7077
7078       /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7079     if (!plci->channels
7080      && (plci->B1_resource == 16)
7081      && (plci->State <= CONNECTED))
7082     {
7083       len = 9;
7084       i = ((T30_INFO   *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7085       PUT_WORD (&plci->ncpi_buffer[1], i);
7086       PUT_WORD (&plci->ncpi_buffer[3], 0);
7087       i = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format;
7088       PUT_WORD (&plci->ncpi_buffer[5], i);
7089       PUT_WORD (&plci->ncpi_buffer[7], 0);
7090       plci->ncpi_buffer[len] = 0;
7091       plci->ncpi_buffer[0] = len;
7092       if(plci->B3_prot == 4)
7093         sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
7094       else
7095       {
7096
7097         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
7098           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7099         {
7100           plci->ncpi_buffer[++len] = 0;
7101           plci->ncpi_buffer[++len] = 0;
7102           plci->ncpi_buffer[++len] = 0;
7103           plci->ncpi_buffer[0] = len;
7104         }
7105
7106         sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
7107       }
7108       sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7109       plci->ncpi_state = 0;
7110       sig_req(plci,HANGUP,0);
7111       send_req(plci);
7112       plci->State = OUTG_DIS_PENDING;
7113       /* disc here */
7114     }
7115     else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7116      && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7117      && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7118     {
7119       if (ncci_state == IDLE)
7120       {
7121         if (plci->channels)
7122           plci->channels--;
7123         if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7124           if(plci->State == SUSPENDING){
7125             sendf(plci->appl,
7126                   _FACILITY_I,
7127                   Id & 0xffffL,
7128                   0,
7129                   "ws", (word)3, "\x03\x04\x00\x00");
7130             sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7131           }
7132           plci_remove(plci);
7133           plci->State=IDLE;
7134         }
7135       }
7136     }
7137     else if (plci->channels)
7138     {
7139       sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7140       plci->ncpi_state = 0;
7141       if ((ncci_state == OUTG_REJ_PENDING)
7142        && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7143       {
7144         sig_req(plci,HANGUP,0);
7145         send_req(plci);
7146         plci->State = OUTG_DIS_PENDING;
7147       }
7148     }
7149     break;
7150   case N_RESET:
7151     a->ncci_state[ncci] = INC_RES_PENDING;
7152     sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7153     break;
7154   case N_RESET_ACK:
7155     a->ncci_state[ncci] = CONNECTED;
7156     sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7157     break;
7158
7159   case N_UDATA:
7160     if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7161     {
7162       plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
7163       plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7164       plci->NL.R = plci->RData;
7165       plci->NL.RNum = 1;
7166       return;
7167     }
7168   case N_BDATA:
7169   case N_DATA:
7170     if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7171      || (a->ncci_state[ncci] == IDLE)
7172      || (a->ncci_state[ncci] == INC_DIS_PENDING))
7173     {
7174       plci->NL.RNR = 2;
7175       break;
7176     }
7177     if ((a->ncci_state[ncci] != CONNECTED)
7178      && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7179      && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7180     {
7181       dbug(1,dprintf("flow control"));
7182       plci->NL.RNR = 1; /* flow control  */
7183       channel_x_off (plci, ch, 0);
7184       break;
7185     }
7186
7187     NCCIcode = ncci | (((word)a->Id) << 8);
7188
7189                 /* count all buffers within the Application pool    */
7190                 /* belonging to the same NCCI. If this is below the */
7191                 /* number of buffers available per NCCI we accept   */
7192                 /* this packet, otherwise we reject it              */
7193     count = 0;
7194     Num = 0xffff;
7195     for(i=0; i<APPLptr->MaxBuffer; i++) {
7196       if(NCCIcode==APPLptr->DataNCCI[i]) count++;
7197       if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
7198     }
7199
7200     if(count>=APPLptr->MaxNCCIData || Num==0xffff)
7201     {
7202       dbug(3,dprintf("Flow-Control"));
7203       plci->NL.RNR = 1;
7204       if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7205        (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7206       {
7207         plci->NL.RNR = 2;
7208         dbug(3,dprintf("DiscardData"));
7209       } else {
7210         channel_x_off (plci, ch, 0);
7211       }
7212       break;
7213     }
7214     else
7215     {
7216       APPLptr->NCCIDataFlowCtrlTimer = 0;
7217     }
7218
7219     plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7220     if(!plci->RData[0].P) {
7221       plci->NL.RNR = 1;
7222       channel_x_off (plci, ch, 0);
7223       break;
7224     }
7225
7226     APPLptr->DataNCCI[Num] = NCCIcode;
7227     APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
7228     dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
7229
7230     plci->RNum = Num;
7231     plci->RFlags = plci->NL.Ind>>4;
7232     plci->RData[0].PLength = APPLptr->MaxDataLength;
7233     plci->NL.R = plci->RData;
7234     if ((plci->NL.RLength != 0)
7235      && ((plci->B2_prot == B2_V120_ASYNC)
7236       || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7237       || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7238     {
7239       plci->RData[1].P = plci->RData[0].P;
7240       plci->RData[1].PLength = plci->RData[0].PLength;
7241       plci->RData[0].P = v120_header_buffer + (-((int) v120_header_buffer) & 3);
7242       if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7243         plci->RData[0].PLength = 1;
7244       else
7245         plci->RData[0].PLength = 2;
7246       if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7247         plci->RFlags |= 0x0010;
7248       if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7249         plci->RFlags |= 0x8000;
7250       plci->NL.RNum = 2;
7251     }
7252     else
7253     {
7254       if((plci->NL.Ind &0x0f)==N_UDATA)
7255         plci->RFlags |= 0x0010;
7256
7257       else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7258         plci->RFlags |= 0x0001;
7259
7260       plci->NL.RNum = 1;
7261     }
7262     break;
7263   case N_DATA_ACK:
7264     data_ack (plci, ch);
7265     break;
7266   default:
7267     plci->NL.RNR = 2;
7268     break;
7269   }
7270 }
7271
7272 /*------------------------------------------------------------------*/
7273 /* find a free PLCI                                                 */
7274 /*------------------------------------------------------------------*/
7275
7276 static word get_plci(DIVA_CAPI_ADAPTER *a)
7277 {
7278   word i,j;
7279   PLCI   * plci;
7280
7281   dump_plcis (a);
7282   for(i=0;i<a->max_plci && a->plci[i].Id;i++);
7283   if(i==a->max_plci) {
7284     dbug(1,dprintf("get_plci: out of PLCIs"));
7285     return 0;
7286   }
7287   plci = &a->plci[i];
7288   plci->Id = (byte)(i+1);
7289
7290   plci->Sig.Id = 0;
7291   plci->NL.Id = 0;
7292   plci->sig_req = 0;
7293   plci->nl_req = 0;
7294
7295   plci->appl = NULL;
7296   plci->relatedPTYPLCI = NULL;
7297   plci->State = IDLE;
7298   plci->SuppState = IDLE;
7299   plci->channels = 0;
7300   plci->tel = 0;
7301   plci->B1_resource = 0;
7302   plci->B2_prot = 0;
7303   plci->B3_prot = 0;
7304
7305   plci->command = 0;
7306   plci->m_command = 0;
7307   init_internal_command_queue (plci);
7308   plci->number = 0;
7309   plci->req_in_start = 0;
7310   plci->req_in = 0;
7311   plci->req_out = 0;
7312   plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7313   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7314   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7315
7316   plci->data_sent = false;
7317   plci->send_disc = 0;
7318   plci->sig_global_req = 0;
7319   plci->sig_remove_id = 0;
7320   plci->nl_global_req = 0;
7321   plci->nl_remove_id = 0;
7322   plci->adv_nl = 0;
7323   plci->manufacturer = false;
7324   plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7325   plci->spoofed_msg = 0;
7326   plci->ptyState = 0;
7327   plci->cr_enquiry = false;
7328   plci->hangup_flow_ctrl_timer = 0;
7329
7330   plci->ncci_ring_list = 0;
7331   for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
7332   clear_c_ind_mask (plci);
7333   set_group_ind_mask (plci);
7334   plci->fax_connect_info_length = 0;
7335   plci->nsf_control_bits = 0;
7336   plci->ncpi_state = 0x00;
7337   plci->ncpi_buffer[0] = 0;
7338
7339   plci->requested_options_conn = 0;
7340   plci->requested_options = 0;
7341   plci->notifiedcall = 0;
7342   plci->vswitchstate = 0;
7343   plci->vsprot = 0;
7344   plci->vsprotdialect = 0;
7345   init_b1_config (plci);
7346   dbug(1,dprintf("get_plci(%x)",plci->Id));
7347   return i+1;
7348 }
7349
7350 /*------------------------------------------------------------------*/
7351 /* put a parameter in the parameter buffer                          */
7352 /*------------------------------------------------------------------*/
7353
7354 static void add_p(PLCI   * plci, byte code, byte   * p)
7355 {
7356   word p_length;
7357
7358   p_length = 0;
7359   if(p) p_length = p[0];
7360   add_ie(plci, code, p, p_length);
7361 }
7362
7363 /*------------------------------------------------------------------*/
7364 /* put a structure in the parameter buffer                          */
7365 /*------------------------------------------------------------------*/
7366 static void add_s(PLCI   * plci, byte code, API_PARSE * p)
7367 {
7368   if(p) add_ie(plci, code, p->info, (word)p->length);
7369 }
7370
7371 /*------------------------------------------------------------------*/
7372 /* put multiple structures in the parameter buffer                  */
7373 /*------------------------------------------------------------------*/
7374 static void add_ss(PLCI   * plci, byte code, API_PARSE * p)
7375 {
7376   byte i;
7377
7378   if(p){
7379     dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
7380     for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7381       dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
7382       add_ie(plci, p->info[i-1], (byte   *)&(p->info[i]), (word)p->info[i]);
7383     }
7384   }
7385 }
7386
7387 /*------------------------------------------------------------------*/
7388 /* return the channel number sent by the application in a esc_chi   */
7389 /*------------------------------------------------------------------*/
7390 static byte getChannel(API_PARSE * p)
7391 {
7392   byte i;
7393
7394   if(p){
7395     for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7396       if(p->info[i]==2){
7397         if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
7398       }
7399     }
7400   }
7401   return 0;
7402 }
7403
7404
7405 /*------------------------------------------------------------------*/
7406 /* put an information element in the parameter buffer               */
7407 /*------------------------------------------------------------------*/
7408
7409 static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length)
7410 {
7411   word i;
7412
7413   if(!(code &0x80) && !p_length) return;
7414
7415   if(plci->req_in==plci->req_in_start) {
7416     plci->req_in +=2;
7417   }
7418   else {
7419     plci->req_in--;
7420   }
7421   plci->RBuffer[plci->req_in++] = code;
7422
7423   if(p) {
7424     plci->RBuffer[plci->req_in++] = (byte)p_length;
7425     for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
7426   }
7427
7428   plci->RBuffer[plci->req_in++] = 0;
7429 }
7430
7431 /*------------------------------------------------------------------*/
7432 /* put a unstructured data into the buffer                          */
7433 /*------------------------------------------------------------------*/
7434
7435 static void add_d(PLCI *plci, word length, byte *p)
7436 {
7437   word i;
7438
7439   if(plci->req_in==plci->req_in_start) {
7440     plci->req_in +=2;
7441   }
7442   else {
7443     plci->req_in--;
7444   }
7445   for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
7446 }
7447
7448 /*------------------------------------------------------------------*/
7449 /* put parameters from the Additional Info parameter in the         */
7450 /* parameter buffer                                                 */
7451 /*------------------------------------------------------------------*/
7452
7453 static void add_ai(PLCI *plci, API_PARSE *ai)
7454 {
7455   word i;
7456     API_PARSE ai_parms[5];
7457
7458   for(i=0;i<5;i++) ai_parms[i].length = 0;
7459
7460   if(!ai->length)
7461     return;
7462   if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7463     return;
7464
7465   add_s (plci,KEY,&ai_parms[1]);
7466   add_s (plci,UUI,&ai_parms[2]);
7467   add_ss(plci,FTY,&ai_parms[3]);
7468 }
7469
7470 /*------------------------------------------------------------------*/
7471 /* put parameter for b1 protocol in the parameter buffer            */
7472 /*------------------------------------------------------------------*/
7473
7474 static word add_b1(PLCI *plci, API_PARSE *bp, word b_channel_info,
7475                    word b1_facilities)
7476 {
7477     API_PARSE bp_parms[8];
7478     API_PARSE mdm_cfg[9];
7479     API_PARSE global_config[2];
7480     byte cai[256];
7481   byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7482   byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7483   word i;
7484
7485     API_PARSE mdm_cfg_v18[4];
7486   word j, n, w;
7487   dword d;
7488
7489
7490   for(i=0;i<8;i++) bp_parms[i].length = 0;
7491   for(i=0;i<2;i++) global_config[i].length = 0;
7492
7493   dbug(1,dprintf("add_b1"));
7494   api_save_msg(bp, "s", &plci->B_protocol);
7495
7496   if(b_channel_info==2){
7497     plci->B1_resource = 0;
7498     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7499     add_p(plci, CAI, "\x01\x00");
7500     dbug(1,dprintf("Cai=1,0 (no resource)"));
7501     return 0;
7502   }
7503
7504   if(plci->tel == CODEC_PERMANENT) return 0;
7505   else if(plci->tel == CODEC){
7506     plci->B1_resource = 1;
7507     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7508     add_p(plci, CAI, "\x01\x01");
7509     dbug(1,dprintf("Cai=1,1 (Codec)"));
7510     return 0;
7511   }
7512   else if(plci->tel == ADV_VOICE){
7513     plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7514     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7515     voice_cai[1] = plci->B1_resource;
7516     PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength);
7517     add_p(plci, CAI, voice_cai);
7518     dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
7519     return 0;
7520   }
7521   plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7522   if (plci->call_dir & CALL_DIR_OUT)
7523     plci->call_dir |= CALL_DIR_ORIGINATE;
7524   else if (plci->call_dir & CALL_DIR_IN)
7525     plci->call_dir |= CALL_DIR_ANSWER;
7526
7527   if(!bp->length){
7528     plci->B1_resource = 0x5;
7529     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7530     add_p(plci, CAI, "\x01\x05");
7531     return 0;
7532   }
7533
7534   dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
7535   if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
7536   if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7537   {
7538     bp_parms[6].length = 0;
7539     if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7540     {
7541       dbug(1,dprintf("b-form.!"));
7542       return _WRONG_MESSAGE_FORMAT;
7543     }
7544   }
7545   else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7546   {
7547     dbug(1,dprintf("b-form.!"));
7548     return _WRONG_MESSAGE_FORMAT;
7549   }
7550
7551   if(bp_parms[6].length)
7552   {
7553     if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7554     {
7555       return _WRONG_MESSAGE_FORMAT;
7556     }
7557     switch(GET_WORD(global_config[0].info))
7558     {
7559     case 1:
7560       plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7561       break;
7562     case 2:
7563       plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7564       break;
7565     }
7566   }
7567   dbug(1,dprintf("call_dir=%04x", plci->call_dir));
7568
7569
7570   if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7571    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7572   {
7573     plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7574     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7575     cai[1] = plci->B1_resource;
7576     cai[2] = 0;
7577     cai[3] = 0;
7578     cai[4] = 0;
7579     PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7580     for (i = 0; i < bp_parms[3].length; i++)
7581       cai[7+i] = bp_parms[3].info[1+i];
7582     cai[0] = 6 + bp_parms[3].length;
7583     add_p(plci, CAI, cai);
7584     return 0;
7585   }
7586
7587
7588   if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7589    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7590   {
7591     plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7592     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7593     cai[1] = plci->B1_resource;
7594     cai[2] = 0;
7595     cai[3] = 0;
7596     cai[4] = 0;
7597     PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7598     cai[0] = 6;
7599     add_p(plci, CAI, cai);
7600     return 0;
7601   }
7602
7603
7604   if ((GET_WORD(bp_parms[0].info) >= 32)
7605    || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7606     && ((GET_WORD(bp_parms[0].info) != 3)
7607      || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7608      || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7609   {
7610     return _B1_NOT_SUPPORTED;
7611   }
7612   plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)],
7613     (word)(b1_facilities & ~B1_FACILITY_VOICE));
7614   adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7615   cai[0] = 6;
7616   cai[1] = plci->B1_resource;
7617   for (i=2;i<sizeof(cai);i++) cai[i] = 0;
7618
7619   if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7620    || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7621    || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7622   { /* B1 - modem */
7623     for (i=0;i<7;i++) mdm_cfg[i].length = 0;
7624
7625     if (bp_parms[3].length)
7626     {
7627       if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
7628       {
7629         return (_WRONG_MESSAGE_FORMAT);
7630       }
7631         
7632       cai[2] = 0; /* Bit rate for adaptation */
7633
7634       dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7635
7636       PUT_WORD (&cai[13], 0);                          /* Min Tx speed */
7637       PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7638       PUT_WORD (&cai[17], 0);                          /* Min Rx speed */
7639       PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7640
7641       cai[3] = 0; /* Async framing parameters */
7642       switch (GET_WORD (mdm_cfg[2].info))
7643       {       /* Parity     */
7644       case 1: /* odd parity */
7645         cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7646         dbug(1,dprintf("MDM: odd parity"));
7647         break;
7648
7649       case 2: /* even parity */
7650         cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7651         dbug(1,dprintf("MDM: even parity"));
7652         break;
7653
7654       default:
7655         dbug(1,dprintf("MDM: no parity"));
7656         break;
7657       }
7658
7659       switch (GET_WORD (mdm_cfg[3].info))
7660       {       /* stop bits   */
7661       case 1: /* 2 stop bits */
7662         cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7663         dbug(1,dprintf("MDM: 2 stop bits"));
7664         break;
7665
7666       default:
7667         dbug(1,dprintf("MDM: 1 stop bit"));
7668         break;
7669       }
7670
7671       switch (GET_WORD (mdm_cfg[1].info))
7672       {     /* char length */
7673       case 5:
7674         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7675         dbug(1,dprintf("MDM: 5 bits"));
7676         break;
7677
7678       case 6:
7679         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7680         dbug(1,dprintf("MDM: 6 bits"));
7681         break;
7682
7683       case 7:
7684         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7685         dbug(1,dprintf("MDM: 7 bits"));
7686         break;
7687
7688       default:
7689         dbug(1,dprintf("MDM: 8 bits"));
7690         break;
7691       }
7692
7693       cai[7] = 0; /* Line taking options */
7694       cai[8] = 0; /* Modulation negotiation options */
7695       cai[9] = 0; /* Modulation options */
7696
7697       if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7698       {
7699         cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7700         dbug(1, dprintf("MDM: Reverse direction"));
7701       }
7702
7703       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7704       {
7705         cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7706         dbug(1, dprintf("MDM: Disable retrain"));
7707       }
7708
7709       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7710       {
7711         cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7712         dbug(1, dprintf("MDM: Disable ring tone"));
7713       }
7714
7715       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7716       {
7717         cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7718         dbug(1, dprintf("MDM: 1800 guard tone"));
7719       }
7720       else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
7721       {
7722         cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7723         dbug(1, dprintf("MDM: 550 guard tone"));
7724       }
7725
7726       if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7727       {
7728         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7729         dbug(1, dprintf("MDM: V100"));
7730       }
7731       else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7732       {
7733         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7734         dbug(1, dprintf("MDM: IN CLASS"));
7735       }
7736       else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7737       {
7738         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7739         dbug(1, dprintf("MDM: DISABLED"));
7740       }
7741       cai[0] = 20;
7742
7743       if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7744        && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7745       {
7746         plci->requested_options |= 1L << PRIVATE_V18;
7747       }
7748       if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7749         plci->requested_options |= 1L << PRIVATE_VOWN;
7750
7751       if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
7752         & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7753       {
7754         if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
7755         {
7756           i = 27;
7757           if (mdm_cfg[6].length >= 4)
7758           {
7759             d = GET_DWORD(&mdm_cfg[6].info[1]);
7760             cai[7] |= (byte) d;          /* line taking options */
7761             cai[9] |= (byte)(d >> 8);    /* modulation options */
7762             cai[++i] = (byte)(d >> 16);  /* vown modulation options */
7763             cai[++i] = (byte)(d >> 24);
7764             if (mdm_cfg[6].length >= 8)
7765             {
7766               d = GET_DWORD(&mdm_cfg[6].info[5]);
7767               cai[10] |= (byte) d;        /* disabled modulations mask */
7768               cai[11] |= (byte)(d >> 8);
7769               if (mdm_cfg[6].length >= 12)
7770               {
7771                 d = GET_DWORD(&mdm_cfg[6].info[9]);
7772                 cai[12] = (byte) d;          /* enabled modulations mask */
7773                 cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */
7774                 cai[++i] = (byte)(d >> 16);
7775                 cai[++i] = (byte)(d >> 24);
7776                 cai[++i] = 0;
7777                 if (mdm_cfg[6].length >= 14)
7778                 {
7779                   w = GET_WORD(&mdm_cfg[6].info[13]);
7780                   if (w != 0)
7781                     PUT_WORD(&cai[13], w);  /* min tx speed */
7782                   if (mdm_cfg[6].length >= 16)
7783                   {
7784                     w = GET_WORD(&mdm_cfg[6].info[15]);
7785                     if (w != 0)
7786                       PUT_WORD(&cai[15], w);  /* max tx speed */
7787                     if (mdm_cfg[6].length >= 18)
7788                     {
7789                       w = GET_WORD(&mdm_cfg[6].info[17]);
7790                       if (w != 0)
7791                         PUT_WORD(&cai[17], w);  /* min rx speed */
7792                       if (mdm_cfg[6].length >= 20)
7793                       {
7794                         w = GET_WORD(&mdm_cfg[6].info[19]);
7795                         if (w != 0)
7796                           PUT_WORD(&cai[19], w);  /* max rx speed */
7797                         if (mdm_cfg[6].length >= 22)
7798                         {
7799                           w = GET_WORD(&mdm_cfg[6].info[21]);
7800                           cai[23] = (byte)(-((short) w));  /* transmit level */
7801                           if (mdm_cfg[6].length >= 24)
7802                           {
7803                             w = GET_WORD(&mdm_cfg[6].info[23]);
7804                             cai[22] |= (byte) w;        /* info options mask */
7805                             cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */
7806                           }
7807                         }
7808                       }
7809                     }
7810                   }
7811                 }
7812               }
7813             }
7814           }
7815           cai[27] = i - 27;
7816           i++;
7817           if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
7818           {
7819             if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
7820             {
7821               for (n = 0; n < 3; n++)
7822               {
7823                 cai[i] = (byte)(mdm_cfg_v18[n].length);
7824                 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7825                   cai[i+j] = mdm_cfg_v18[n].info[j];
7826                 i += cai[i] + 1;
7827               }
7828             }
7829           }
7830           cai[0] = (byte)(i - 1);
7831         }
7832       }
7833
7834     }
7835   }
7836   if(GET_WORD(bp_parms[0].info)==2 ||                         /* V.110 async */
7837      GET_WORD(bp_parms[0].info)==3 )                          /* V.110 sync */
7838   {
7839     if(bp_parms[3].length){
7840       dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1])));
7841       switch(GET_WORD(&bp_parms[3].info[1])){                 /* Rate */
7842         case 0:
7843         case 56000:
7844           if(GET_WORD(bp_parms[0].info)==3){                  /* V.110 sync 56k */
7845             dbug(1,dprintf("56k sync HSCX"));
7846             cai[1] = 8;
7847             cai[2] = 0;
7848             cai[3] = 0;
7849           }
7850           else if(GET_WORD(bp_parms[0].info)==2){
7851             dbug(1,dprintf("56k async DSP"));
7852             cai[2] = 9;
7853           }
7854           break;
7855         case 50:     cai[2] = 1;  break;
7856         case 75:     cai[2] = 1;  break;
7857         case 110:    cai[2] = 1;  break;
7858         case 150:    cai[2] = 1;  break;
7859         case 200:    cai[2] = 1;  break;
7860         case 300:    cai[2] = 1;  break;
7861         case 600:    cai[2] = 1;  break;
7862         case 1200:   cai[2] = 2;  break;
7863         case 2400:   cai[2] = 3;  break;
7864         case 4800:   cai[2] = 4;  break;
7865         case 7200:   cai[2] = 10; break;
7866         case 9600:   cai[2] = 5;  break;
7867         case 12000:  cai[2] = 13; break;
7868         case 24000:  cai[2] = 0;  break;
7869         case 14400:  cai[2] = 11; break;
7870         case 19200:  cai[2] = 6;  break;
7871         case 28800:  cai[2] = 12; break;
7872         case 38400:  cai[2] = 7;  break;
7873         case 48000:  cai[2] = 8;  break;
7874         case 76:     cai[2] = 15; break;  /* 75/1200     */
7875         case 1201:   cai[2] = 14; break;  /* 1200/75     */
7876         case 56001:  cai[2] = 9;  break;  /* V.110 56000 */
7877
7878         default:
7879           return _B1_PARM_NOT_SUPPORTED;
7880       }
7881       cai[3] = 0;
7882       if (cai[1] == 13)                                        /* v.110 async */
7883       {
7884         if (bp_parms[3].length >= 8)
7885         {
7886           switch (GET_WORD (&bp_parms[3].info[3]))
7887           {       /* char length */
7888           case 5:
7889             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7890             break;
7891           case 6:
7892             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7893             break;
7894           case 7:
7895             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7896             break;
7897           }
7898           switch (GET_WORD (&bp_parms[3].info[5]))
7899           {       /* Parity     */
7900           case 1: /* odd parity */
7901             cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7902             break;
7903           case 2: /* even parity */
7904             cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7905             break;
7906           }
7907           switch (GET_WORD (&bp_parms[3].info[7]))
7908           {       /* stop bits   */
7909           case 1: /* 2 stop bits */
7910             cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7911             break;
7912           }
7913         }
7914       }
7915     }
7916     else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){
7917       dbug(1,dprintf("V.110 default 56k sync"));
7918       cai[1] = 8;
7919       cai[2] = 0;
7920       cai[3] = 0;
7921     }
7922     else {
7923       dbug(1,dprintf("V.110 default 9600 async"));
7924       cai[2] = 5;
7925     }
7926   }
7927   PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7928   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]));
7929 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7930
7931   add_p(plci, CAI, cai);
7932   return 0;
7933 }
7934
7935 /*------------------------------------------------------------------*/
7936 /* put parameter for b2 and B3  protocol in the parameter buffer    */
7937 /*------------------------------------------------------------------*/
7938
7939 static word add_b23(PLCI *plci, API_PARSE *bp)
7940 {
7941   word i, fax_control_bits;
7942   byte pos, len;
7943   byte SAPI = 0x40;  /* default SAPI 16 for x.31 */
7944     API_PARSE bp_parms[8];
7945   API_PARSE * b1_config;
7946   API_PARSE * b2_config;
7947     API_PARSE b2_config_parms[8];
7948   API_PARSE * b3_config;
7949     API_PARSE b3_config_parms[6];
7950     API_PARSE global_config[2];
7951
7952   static byte llc[3] = {2,0,0};
7953   static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7954   static byte nlc[256];
7955   static byte lli[12] = {1,1};
7956
7957   const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7958   const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7959
7960   const byte llc3[] = {4,3,2,2,6,6,0};
7961   const byte header[] = {0,2,3,3,0,0,0};
7962
7963   for(i=0;i<8;i++) bp_parms[i].length = 0;
7964   for(i=0;i<6;i++) b2_config_parms[i].length = 0;
7965   for(i=0;i<5;i++) b3_config_parms[i].length = 0;
7966
7967   lli[0] = 1;
7968   lli[1] = 1;
7969   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7970     lli[1] |= 2;
7971   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7972     lli[1] |= 4;
7973
7974   if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7975     lli[1] |= 0x10;
7976     if (plci->rx_dma_descriptor <= 0) {
7977       plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
7978       if (plci->rx_dma_descriptor >= 0)
7979         plci->rx_dma_descriptor++;
7980     }
7981     if (plci->rx_dma_descriptor > 0) {
7982       lli[0] = 6;
7983       lli[1] |= 0x40;
7984       lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7985       lli[3] = (byte)plci->rx_dma_magic;
7986       lli[4] = (byte)(plci->rx_dma_magic >>  8);
7987       lli[5] = (byte)(plci->rx_dma_magic >> 16);
7988       lli[6] = (byte)(plci->rx_dma_magic >> 24);
7989     }
7990   }
7991
7992   if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7993     lli[1] |= 0x20;
7994   }
7995
7996   dbug(1,dprintf("add_b23"));
7997   api_save_msg(bp, "s", &plci->B_protocol);
7998
7999   if(!bp->length && plci->tel)
8000   {
8001     plci->adv_nl = true;
8002     dbug(1,dprintf("Default adv.Nl"));
8003     add_p(plci,LLI,lli);
8004     plci->B2_prot = 1 /*XPARENT*/;
8005     plci->B3_prot = 0 /*XPARENT*/;
8006     llc[1] = 2;
8007     llc[2] = 4;
8008     add_p(plci, LLC, llc);
8009     dlc[0] = 2;
8010     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8011     add_p(plci, DLC, dlc);
8012     return 0;
8013   }
8014
8015   if(!bp->length) /*default*/
8016   {   
8017     dbug(1,dprintf("ret default"));
8018     add_p(plci,LLI,lli);
8019     plci->B2_prot = 0 /*X.75   */;
8020     plci->B3_prot = 0 /*XPARENT*/;
8021     llc[1] = 1;
8022     llc[2] = 4;
8023     add_p(plci, LLC, llc);
8024     dlc[0] = 2;
8025     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8026     add_p(plci, DLC, dlc);
8027     return 0;
8028   }
8029   dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
8030   if((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT;
8031
8032   if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8033   {
8034     bp_parms[6].length = 0;
8035     if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8036     {
8037       dbug(1,dprintf("b-form.!"));
8038       return _WRONG_MESSAGE_FORMAT;
8039     }
8040   }
8041   else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8042   {
8043     dbug(1,dprintf("b-form.!"));
8044     return _WRONG_MESSAGE_FORMAT;
8045   }
8046
8047   if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
8048   {  
8049     if(GET_WORD(bp_parms[1].info)!=1
8050     || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
8051     plci->adv_nl = true;
8052   }
8053   else if(plci->tel) return _B2_NOT_SUPPORTED;
8054
8055
8056   if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8057    && (GET_WORD(bp_parms[2].info) == B3_RTP)
8058    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8059   {
8060     add_p(plci,LLI,lli);
8061     plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8062     plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8063     llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8064     llc[2] = 4;
8065     add_p(plci, LLC, llc);
8066     dlc[0] = 2;
8067     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8068     dlc[3] = 3; /* Addr A */
8069     dlc[4] = 1; /* Addr B */
8070     dlc[5] = 7; /* modulo mode */
8071     dlc[6] = 7; /* window size */
8072     dlc[7] = 0; /* XID len Lo  */
8073     dlc[8] = 0; /* XID len Hi  */
8074     for (i = 0; i < bp_parms[4].length; i++)
8075       dlc[9+i] = bp_parms[4].info[1+i];
8076     dlc[0] = (byte)(8 + bp_parms[4].length);
8077     add_p(plci, DLC, dlc);
8078     for (i = 0; i < bp_parms[5].length; i++)
8079       nlc[1+i] = bp_parms[5].info[1+i];
8080     nlc[0] = (byte)(bp_parms[5].length);
8081     add_p(plci, NLC, nlc);
8082     return 0;
8083   }
8084
8085
8086
8087   if ((GET_WORD(bp_parms[1].info) >= 32)
8088    || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8089     && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8090      || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8091
8092   {
8093     return _B2_NOT_SUPPORTED;
8094   }
8095   if ((GET_WORD(bp_parms[2].info) >= 32)
8096    || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8097   {
8098     return _B3_NOT_SUPPORTED;
8099   }
8100   if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8101    && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8102     || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8103     || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8104   {
8105     return (add_modem_b23 (plci, bp_parms));
8106   }
8107
8108   add_p(plci,LLI,lli);
8109
8110   plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8111   plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8112   if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
8113
8114   if(bp_parms[6].length)
8115   {
8116     if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8117     {
8118       return _WRONG_MESSAGE_FORMAT;
8119     }
8120     switch(GET_WORD(global_config[0].info))
8121     {
8122     case 1:
8123       plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8124       break;
8125     case 2:
8126       plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8127       break;
8128     }
8129   }
8130   dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8131
8132
8133   if (plci->B2_prot == B2_PIAFS)
8134     llc[1] = PIAFS_CRC;
8135   else
8136 /* IMPLEMENT_PIAFS */
8137   {
8138     llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8139              llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8140   }
8141   llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8142
8143   add_p(plci, LLC, llc);
8144
8145   dlc[0] = 2;
8146   PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8147                       header[GET_WORD(bp_parms[2].info)]);
8148
8149   b1_config = &bp_parms[3];
8150   nlc[0] = 0;
8151   if(plci->B3_prot == 4
8152   || plci->B3_prot == 5)
8153   {
8154     for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
8155     nlc[0] = sizeof(T30_INFO);
8156     if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8157       ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8158     ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8159     if(b1_config->length>=2)
8160     {
8161       ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400);
8162     }
8163   }
8164   b2_config = &bp_parms[4];
8165
8166
8167   if (llc[1] == PIAFS_CRC)
8168   {
8169     if (plci->B3_prot != B3_TRANSPARENT)
8170     {
8171       return _B_STACK_NOT_SUPPORTED;
8172     }
8173     if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8174       return _WRONG_MESSAGE_FORMAT;
8175     }
8176     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8177     dlc[3] = 0; /* Addr A */
8178     dlc[4] = 0; /* Addr B */
8179     dlc[5] = 0; /* modulo mode */
8180     dlc[6] = 0; /* window size */
8181     if (b2_config->length >= 7){
8182       dlc[ 7] = 7; 
8183       dlc[ 8] = 0; 
8184       dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8185       dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8186       dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8187       dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8188       dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8189       dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8190       dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8191       dlc[ 0] = 15;
8192       if(b2_config->length >= 8) { /* PIAFS control abilities */
8193         dlc[ 7] = 10; 
8194         dlc[16] = 2; /* Length of PIAFS extention */
8195         dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8196         dlc[18] = b2_config_parms[4].info[0]; /* value */
8197         dlc[ 0] = 18;
8198       }
8199     }
8200     else /* default values, 64K, variable, no compression */
8201     {
8202       dlc[ 7] = 7; 
8203       dlc[ 8] = 0; 
8204       dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
8205       dlc[10] = 0x03; /* V.42bis P0 */
8206       dlc[11] = 0;    /* V.42bis P0 */
8207       dlc[12] = 0;    /* V.42bis P1 */
8208       dlc[13] = 0;    /* V.42bis P1 */
8209       dlc[14] = 0;    /* V.42bis P2 */
8210       dlc[15] = 0;    /* V.42bis P2 */
8211     dlc[ 0] = 15;
8212     }
8213     add_p(plci, DLC, dlc);
8214   }
8215   else
8216
8217   if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8218   {
8219     if (plci->B3_prot != B3_TRANSPARENT)
8220       return _B_STACK_NOT_SUPPORTED;
8221
8222     dlc[0] = 6;
8223     PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2);
8224     dlc[3] = 0x08;
8225     dlc[4] = 0x01;
8226     dlc[5] = 127;
8227     dlc[6] = 7;
8228     if (b2_config->length != 0)
8229     {
8230       if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8231         return _WRONG_MESSAGE_FORMAT;
8232       }
8233       dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8234       dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8235       if (b2_config->info[3] != 128)
8236       {
8237         dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8238         return _B2_PARM_NOT_SUPPORTED;
8239       }
8240       dlc[5] = (byte)(b2_config->info[3] - 1);
8241       dlc[6] = b2_config->info[4];
8242       if(llc[1]==V120_V42BIS){
8243         if (b2_config->length >= 10){
8244           dlc[ 7] = 6; 
8245           dlc[ 8] = 0; 
8246           dlc[ 9] = b2_config_parms[4].info[0];
8247           dlc[10] = b2_config_parms[4].info[1];
8248           dlc[11] = b2_config_parms[5].info[0];
8249           dlc[12] = b2_config_parms[5].info[1];
8250           dlc[13] = b2_config_parms[6].info[0];
8251           dlc[14] = b2_config_parms[6].info[1];
8252           dlc[ 0] = 14;
8253           dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8254           dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8255           dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8256         }
8257         else {
8258           dlc[ 6] = 14;
8259         }
8260       }
8261     }
8262   }
8263   else
8264   {
8265     if(b2_config->length)
8266     {
8267       dbug(1,dprintf("B2-Config"));
8268       if(llc[1]==X75_V42BIS){
8269         if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8270         {
8271           return _WRONG_MESSAGE_FORMAT;
8272         }
8273       }
8274       else {
8275         if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8276         {
8277           return _WRONG_MESSAGE_FORMAT;
8278         }
8279       }
8280           /* if B2 Protocol is LAPD, b2_config structure is different */
8281       if(llc[1]==6)
8282       {
8283         dlc[0] = 4;
8284         if(b2_config->length>=1) dlc[2] = b2_config->info[1];      /* TEI */
8285         else dlc[2] = 0x01;
8286         if( (b2_config->length>=2) && (plci->B2_prot==12) )
8287         {
8288           SAPI = b2_config->info[2];    /* SAPI */
8289         }
8290         dlc[1] = SAPI;
8291         if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8292         {
8293           dlc[3] = 127;      /* Mode */
8294         }
8295         else
8296         {
8297           dlc[3] = 7;        /* Mode */
8298         }
8299    
8300         if(b2_config->length>=4) dlc[4] = b2_config->info[4];      /* Window */
8301         else dlc[4] = 1;
8302         dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8303         if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
8304       }
8305       else
8306       {
8307         dlc[0] = (byte)(b2_config_parms[4].length+6);
8308         dlc[3] = b2_config->info[1];
8309         dlc[4] = b2_config->info[2];
8310         if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
8311           dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8312           return _B2_PARM_NOT_SUPPORTED;
8313         }
8314
8315         dlc[5] = (byte)(b2_config->info[3]-1);
8316         dlc[6] = b2_config->info[4];
8317         if(dlc[6]>dlc[5]){
8318           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]));
8319           return _B2_PARM_NOT_SUPPORTED;
8320         }
8321  
8322         if(llc[1]==X75_V42BIS) {
8323           if (b2_config->length >= 10){
8324             dlc[ 7] = 6; 
8325             dlc[ 8] = 0; 
8326             dlc[ 9] = b2_config_parms[4].info[0];
8327             dlc[10] = b2_config_parms[4].info[1];
8328             dlc[11] = b2_config_parms[5].info[0];
8329             dlc[12] = b2_config_parms[5].info[1];
8330             dlc[13] = b2_config_parms[6].info[0];
8331             dlc[14] = b2_config_parms[6].info[1];
8332             dlc[ 0] = 14;
8333             dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8334             dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8335             dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8336           }
8337           else {
8338             dlc[ 6] = 14;
8339           }
8340
8341         }
8342         else {
8343           PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8344           for(i=0; i<b2_config_parms[4].length; i++)
8345             dlc[11+i] = b2_config_parms[4].info[1+i];
8346         }
8347       }
8348     }
8349   }
8350   add_p(plci, DLC, dlc);
8351
8352   b3_config = &bp_parms[5];
8353   if(b3_config->length)
8354   {
8355     if(plci->B3_prot == 4 
8356     || plci->B3_prot == 5)
8357     {
8358       if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8359       {
8360         return _WRONG_MESSAGE_FORMAT;
8361       }
8362       i = GET_WORD((byte   *)(b3_config_parms[0].info));
8363       ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8364         ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte   *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8365       ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte   *)b3_config_parms[1].info));
8366       fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8367       if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8368         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8369       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8370       {
8371
8372         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8373           & (1L << PRIVATE_FAX_PAPER_FORMATS))
8374         {
8375           ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8376             T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8377             T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8378         }
8379
8380  ((T30_INFO *)&nlc[1])->recording_properties =
8381    T30_RECORDING_WIDTH_ISO_A3 |
8382    (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8383    (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8384       }
8385       if(plci->B3_prot == 5)
8386       {
8387         if (i & 0x0002) /* Accept incoming fax-polling requests */
8388           fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8389         if (i & 0x2000) /* Do not use MR compression */
8390           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8391         if (i & 0x4000) /* Do not use MMR compression */
8392           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8393         if (i & 0x8000) /* Do not use ECM */
8394           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8395         if (plci->fax_connect_info_length != 0)
8396         {
8397           ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO   *)plci->fax_connect_info_buffer)->resolution;
8398           ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format;
8399           ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO   *)plci->fax_connect_info_buffer)->recording_properties;
8400           fax_control_bits |= GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) &
8401             (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8402         }
8403       }
8404       /* copy station id to NLC */
8405       for(i=0; i<20; i++)
8406       {
8407         if(i<b3_config_parms[2].length)
8408         {
8409           ((T30_INFO *)&nlc[1])->station_id[i] = ((byte   *)b3_config_parms[2].info)[1+i];
8410         }
8411         else
8412         {
8413           ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8414         }
8415       }
8416       ((T30_INFO *)&nlc[1])->station_id_len = 20;
8417       /* copy head line to NLC */
8418       if(b3_config_parms[3].length)
8419       {
8420
8421         pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20])));
8422         if (pos != 0)
8423         {
8424           if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8425             pos = 0;
8426           else
8427           {
8428             ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8429             ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8430             len = (byte)b3_config_parms[2].length;
8431             if (len > 20)
8432               len = 20;
8433             if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8434             {
8435               for (i = 0; i < len; i++)
8436                 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte   *)b3_config_parms[2].info)[1+i];
8437               ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8438               ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8439             }
8440           }
8441         }
8442
8443         len = (byte)b3_config_parms[3].length;
8444         if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8445           len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8446         ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8447         nlc[0] += (byte)(pos + len);
8448         for (i = 0; i < len; i++)
8449           ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte   *)b3_config_parms[3].info)[1+i];
8450         }
8451       else
8452         ((T30_INFO *)&nlc[1])->head_line_len = 0;
8453
8454       plci->nsf_control_bits = 0;
8455       if(plci->B3_prot == 5)
8456       {
8457         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8458          && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8459         {
8460           plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8461         }
8462         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8463          && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8464         {
8465           plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8466         }
8467         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8468           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8469         {
8470         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8471           & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8472         {
8473           fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8474           if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8475             fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8476           }
8477             len = nlc[0];
8478           pos = ((byte)(((T30_INFO *) 0)->station_id + 20));
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 (pos < plci->fax_connect_info_length)
8487    {
8488      for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8489               nlc[++len] = plci->fax_connect_info_buffer[pos++];
8490           }
8491    else
8492      nlc[++len] = 0;
8493           if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8494             & (1L << PRIVATE_FAX_NONSTANDARD))
8495           {
8496      if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8497      {
8498               if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8499                 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]);
8500        for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8501                 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8502             }
8503      else
8504      {
8505               if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8506               {
8507                 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8508                 nlc[++len] = 0;
8509               }
8510        else
8511        {
8512                 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8513                   plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8514          nlc[++len] = (byte)(b3_config_parms[4].length);
8515          for (i = 0; i < b3_config_parms[4].length; i++)
8516     nlc[++len] = b3_config_parms[4].info[1+i];
8517        }
8518             }
8519           }
8520             nlc[0] = len;
8521    if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8522     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8523    {
8524             ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8525           }
8526         }
8527       }
8528
8529       PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8530       len = ((byte)(((T30_INFO *) 0)->station_id + 20));
8531       for (i = 0; i < len; i++)
8532         plci->fax_connect_info_buffer[i] = nlc[1+i];
8533       ((T30_INFO   *) plci->fax_connect_info_buffer)->head_line_len = 0;
8534       i += ((T30_INFO *)&nlc[1])->head_line_len;
8535       while (i < nlc[0])
8536         plci->fax_connect_info_buffer[len++] = nlc[++i];
8537       plci->fax_connect_info_length = len;
8538     }
8539     else
8540     {
8541       nlc[0] = 14;
8542       if(b3_config->length!=16)
8543         return _B3_PARM_NOT_SUPPORTED;
8544       for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8545       if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128)
8546         return _B3_PARM_NOT_SUPPORTED;
8547       nlc[13] = b3_config->info[13];
8548       if(GET_WORD(&b3_config->info[15])>=nlc[13])
8549         return _B3_PARM_NOT_SUPPORTED;
8550       nlc[14] = b3_config->info[15];
8551     }
8552   }
8553   else
8554   {
8555     if (plci->B3_prot == 4 
8556      || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8557   }
8558   add_p(plci, NLC, nlc);
8559   return 0;
8560 }
8561
8562 /*----------------------------------------------------------------*/
8563 /*      make the same as add_b23, but only for the modem related  */
8564 /*      L2 and L3 B-Chan protocol.                                */
8565 /*                                                                */
8566 /*      Enabled L2 and L3 Configurations:                         */
8567 /*        If L1 == Modem all negotiation                          */
8568 /*          only L2 == Modem with full negotiation is allowed     */
8569 /*        If L1 == Modem async or sync                            */
8570 /*          only L2 == Transparent is allowed                     */
8571 /*        L3 == Modem or L3 == Transparent are allowed            */
8572 /*      B2 Configuration for modem:                               */
8573 /*          word : enable/disable compression, bitoptions         */
8574 /*      B3 Configuration for modem:                               */
8575 /*          empty                                                 */
8576 /*----------------------------------------------------------------*/
8577 static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms)
8578 {
8579   static byte lli[12] = {1,1};
8580   static byte llc[3] = {2,0,0};
8581   static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8582     API_PARSE mdm_config[2];
8583   word i;
8584   word b2_config = 0;
8585
8586   for(i=0;i<2;i++) mdm_config[i].length = 0;
8587   for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8588
8589   if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8590     && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8591    || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8592     && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8593   {
8594     return (_B_STACK_NOT_SUPPORTED);
8595   }
8596   if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8597    && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8598   {
8599     return (_B_STACK_NOT_SUPPORTED);
8600   }
8601
8602   plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8603   plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8604
8605   if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8606   {
8607     if (api_parse (&bp_parms[4].info[1],
8608                   (word)bp_parms[4].length, "w",
8609                   mdm_config))
8610     {
8611       return (_WRONG_MESSAGE_FORMAT);
8612     }
8613     b2_config = GET_WORD(mdm_config[0].info);
8614   }
8615
8616   /* OK, L2 is modem */
8617
8618   lli[0] = 1;
8619   lli[1] = 1;
8620   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8621     lli[1] |= 2;
8622   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8623     lli[1] |= 4;
8624
8625   if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8626     lli[1] |= 0x10;
8627     if (plci->rx_dma_descriptor <= 0) {
8628       plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8629       if (plci->rx_dma_descriptor >= 0)
8630         plci->rx_dma_descriptor++;
8631     }
8632     if (plci->rx_dma_descriptor > 0) {
8633       lli[1] |= 0x40;
8634       lli[0] = 6;
8635       lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8636       lli[3] = (byte)plci->rx_dma_magic;
8637       lli[4] = (byte)(plci->rx_dma_magic >>  8);
8638       lli[5] = (byte)(plci->rx_dma_magic >> 16);
8639       lli[6] = (byte)(plci->rx_dma_magic >> 24);
8640     }
8641   }
8642
8643   if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8644     lli[1] |= 0x20;
8645   }
8646
8647   llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8648     /*V42*/ 10 : /*V42_IN*/ 9;
8649   llc[2] = 4;                      /* pass L3 always transparent */
8650   add_p(plci, LLI, lli);
8651   add_p(plci, LLC, llc);
8652   i =  1;
8653   PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
8654   i += 2;
8655   if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8656   {
8657     if (bp_parms[4].length)
8658   {
8659     dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8660     dlc[i++] = 3; /* Addr A */
8661     dlc[i++] = 1; /* Addr B */
8662     dlc[i++] = 7; /* modulo mode */
8663     dlc[i++] = 7; /* window size */
8664     dlc[i++] = 0; /* XID len Lo  */
8665     dlc[i++] = 0; /* XID len Hi  */
8666
8667     if (b2_config & MDM_B2_DISABLE_V42bis)
8668     {
8669       dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8670     }
8671     if (b2_config & MDM_B2_DISABLE_MNP)
8672     {
8673       dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8674     }
8675     if (b2_config & MDM_B2_DISABLE_TRANS)
8676     {
8677       dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8678     }
8679     if (b2_config & MDM_B2_DISABLE_V42)
8680     {
8681       dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8682     }
8683     if (b2_config & MDM_B2_DISABLE_COMP)
8684     {
8685       dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8686     }
8687     i++;
8688   }
8689   }
8690   else
8691   {
8692     dlc[i++] = 3; /* Addr A */
8693     dlc[i++] = 1; /* Addr B */
8694     dlc[i++] = 7; /* modulo mode */
8695     dlc[i++] = 7; /* window size */
8696     dlc[i++] = 0; /* XID len Lo  */
8697     dlc[i++] = 0; /* XID len Hi  */
8698     dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8699                DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8700                DLC_MODEMPROT_DISABLE_V42_DETECT |
8701                DLC_MODEMPROT_DISABLE_COMPRESSION;
8702   }
8703   dlc[0] = (byte)(i - 1);
8704 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8705   add_p(plci, DLC, dlc);
8706   return (0);
8707 }
8708
8709
8710 /*------------------------------------------------------------------*/
8711 /* send a request for the signaling entity                          */
8712 /*------------------------------------------------------------------*/
8713
8714 static void sig_req(PLCI *plci, byte req, byte Id)
8715 {
8716   if(!plci) return;
8717   if(plci->adapter->adapter_disabled) return;
8718   dbug(1,dprintf("sig_req(%x)",req));
8719   if (req == REMOVE)
8720     plci->sig_remove_id = plci->Sig.Id;
8721   if(plci->req_in==plci->req_in_start) {
8722     plci->req_in +=2;
8723     plci->RBuffer[plci->req_in++] = 0;
8724   }
8725   PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8726   plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
8727   plci->RBuffer[plci->req_in++] = req;  /* request */
8728   plci->RBuffer[plci->req_in++] = 0;    /* channel */
8729   plci->req_in_start = plci->req_in;
8730 }
8731
8732 /*------------------------------------------------------------------*/
8733 /* send a request for the network layer entity                      */
8734 /*------------------------------------------------------------------*/
8735
8736 static void nl_req_ncci(PLCI *plci, byte req, byte ncci)
8737 {
8738   if(!plci) return;
8739   if(plci->adapter->adapter_disabled) return;
8740   dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8741   if (req == REMOVE)
8742   {
8743     plci->nl_remove_id = plci->NL.Id;
8744     ncci_remove (plci, 0, (byte)(ncci != 0));
8745     ncci = 0;
8746   }
8747   if(plci->req_in==plci->req_in_start) {
8748     plci->req_in +=2;
8749     plci->RBuffer[plci->req_in++] = 0;
8750   }
8751   PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8752   plci->RBuffer[plci->req_in++] = 1;    /* sig/nl flag */
8753   plci->RBuffer[plci->req_in++] = req;  /* request */
8754   plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
8755   plci->req_in_start = plci->req_in;
8756 }
8757
8758 static void send_req(PLCI *plci)
8759 {
8760   ENTITY   * e;
8761   word l;
8762 /*  word i; */
8763
8764   if(!plci) return;
8765   if(plci->adapter->adapter_disabled) return;
8766   channel_xmit_xon (plci);
8767
8768         /* if nothing to do, return */
8769   if(plci->req_in==plci->req_out) return;
8770   dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8771
8772   if(plci->nl_req || plci->sig_req) return;
8773
8774   l = GET_WORD(&plci->RBuffer[plci->req_out]);
8775   plci->req_out += 2;
8776   plci->XData[0].P = &plci->RBuffer[plci->req_out];
8777   plci->req_out += l;
8778   if(plci->RBuffer[plci->req_out]==1)
8779   {
8780     e = &plci->NL;
8781     plci->req_out++;
8782     e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8783     e->ReqCh = plci->RBuffer[plci->req_out++];
8784     if(!(e->Id & 0x1f))
8785     {
8786       e->Id = NL_ID;
8787       plci->RBuffer[plci->req_out-4] = CAI;
8788       plci->RBuffer[plci->req_out-3] = 1;
8789       plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8790       plci->RBuffer[plci->req_out-1] = 0;
8791       l+=3;
8792       plci->nl_global_req = plci->nl_req;
8793     }
8794     dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8795   }
8796   else
8797   {
8798     e = &plci->Sig;
8799     if(plci->RBuffer[plci->req_out])
8800       e->Id = plci->RBuffer[plci->req_out];
8801     plci->req_out++;
8802     e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8803     e->ReqCh = plci->RBuffer[plci->req_out++];
8804     if(!(e->Id & 0x1f))
8805       plci->sig_global_req = plci->sig_req;
8806     dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8807   }
8808   plci->XData[0].PLength = l;
8809   e->X = plci->XData;
8810   plci->adapter->request(e);
8811   dbug(1,dprintf("send_ok"));
8812 }
8813
8814 static void send_data(PLCI *plci)
8815 {
8816   DIVA_CAPI_ADAPTER   * a;
8817   DATA_B3_DESC   * data;
8818   NCCI   *ncci_ptr;
8819   word ncci;
8820
8821   if (!plci->nl_req && plci->ncci_ring_list)
8822   {
8823     a = plci->adapter;
8824     ncci = plci->ncci_ring_list;
8825     do
8826     {
8827       ncci = a->ncci_next[ncci];
8828       ncci_ptr = &(a->ncci[ncci]);
8829       if (!(a->ncci_ch[ncci]
8830          && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8831       {
8832         if (ncci_ptr->data_pending)
8833         {
8834           if ((a->ncci_state[ncci] == CONNECTED)
8835            || (a->ncci_state[ncci] == INC_ACT_PENDING)
8836            || (plci->send_disc == ncci))
8837           {
8838             data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8839             if ((plci->B2_prot == B2_V120_ASYNC)
8840              || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8841              || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8842             {
8843               plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8844               plci->NData[1].PLength = data->Length;
8845               if (data->Flags & 0x10)
8846                 plci->NData[0].P = v120_break_header;
8847               else
8848                 plci->NData[0].P = v120_default_header;
8849               plci->NData[0].PLength = 1 ;
8850               plci->NL.XNum = 2;
8851               plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8852             }
8853             else
8854             {
8855               plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8856               plci->NData[0].PLength = data->Length;
8857               if (data->Flags & 0x10)
8858                 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8859
8860               else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8861                 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8862
8863               else
8864                 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8865             }
8866             plci->NL.X = plci->NData;
8867             plci->NL.ReqCh = a->ncci_ch[ncci];
8868             dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
8869             plci->data_sent = true;
8870             plci->data_sent_ptr = data->P;
8871             a->request(&plci->NL);
8872           }
8873           else {
8874             cleanup_ncci_data (plci, ncci);
8875           }
8876         }
8877         else if (plci->send_disc == ncci)
8878         {
8879           /* dprintf("N_DISC"); */
8880           plci->NData[0].PLength = 0;
8881           plci->NL.ReqCh = a->ncci_ch[ncci];
8882           plci->NL.Req = plci->nl_req = N_DISC;
8883           a->request(&plci->NL);
8884           plci->command = _DISCONNECT_B3_R;
8885           plci->send_disc = 0;
8886         }
8887       }
8888     } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8889     plci->ncci_ring_list = ncci;
8890   }
8891 }
8892
8893 static void listen_check(DIVA_CAPI_ADAPTER *a)
8894 {
8895   word i,j;
8896   PLCI   * plci;
8897   byte activnotifiedcalls = 0;
8898
8899   dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8900   if (!remove_started && !a->adapter_disabled)
8901   {
8902     for(i=0;i<a->max_plci;i++)
8903     {
8904       plci = &(a->plci[i]);
8905       if(plci->notifiedcall) activnotifiedcalls++;
8906     }
8907     dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8908
8909     for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8910       if((j=get_plci(a))) {
8911         a->listen_active++;
8912         plci = &a->plci[j-1];
8913         plci->State = LISTENING;
8914
8915         add_p(plci,OAD,"\x01\xfd");
8916
8917         add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8918
8919         add_p(plci,CAI,"\x01\xc0");
8920         add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8921         add_p(plci,LLI,"\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */       
8922         add_p(plci,SHIFT|6,NULL);
8923         add_p(plci,SIN,"\x02\x00\x00");
8924         plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
8925         sig_req(plci,ASSIGN,DSIG_ID);
8926         send_req(plci);
8927       }
8928     }
8929   }
8930 }
8931
8932 /*------------------------------------------------------------------*/
8933 /* functions for all parameters sent in INDs                        */
8934 /*------------------------------------------------------------------*/
8935
8936 static void IndParse(PLCI *plci, word *parms_id, byte **parms, byte multiIEsize)
8937 {
8938   word ploc;            /* points to current location within packet */
8939   byte w;
8940   byte wlen;
8941   byte codeset,lock;
8942   byte   * in;
8943   word i;
8944   word code;
8945   word mIEindex = 0;
8946   ploc = 0;
8947   codeset = 0;
8948   lock = 0;
8949
8950   in = plci->Sig.RBuffer->P;
8951   for(i=0; i<parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
8952   {                            /* element but parms array is larger      */
8953     parms[i] = (byte   *)"";
8954   }
8955   for(i=0; i<multiIEsize; i++)
8956   {
8957     parms[i] = (byte   *)"";
8958   }
8959
8960   while(ploc<plci->Sig.RBuffer->length-1) {
8961
8962         /* read information element id and length                   */
8963     w = in[ploc];
8964
8965     if(w & 0x80) {
8966 /*    w &=0xf0; removed, cannot detect congestion levels */
8967 /*    upper 4 bit masked with w==SHIFT now               */
8968       wlen = 0;
8969     }
8970     else {
8971       wlen = (byte)(in[ploc+1]+1);
8972     }
8973         /* check if length valid (not exceeding end of packet)      */
8974     if((ploc+wlen) > 270) return ;
8975     if(lock & 0x80) lock &=0x7f;
8976     else codeset = lock;
8977
8978     if((w&0xf0)==SHIFT) {
8979       codeset = in[ploc];
8980       if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8981       codeset &=7;
8982       lock |=0x80;
8983     }
8984     else {
8985       if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8986       else code = w;
8987       code |= (codeset<<8);
8988
8989       for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8990
8991       if(i<parms_id[0]+1) {
8992         if(!multiIEsize) { /* with multiIEs use next field index,          */
8993           mIEindex = i-1;    /* with normal IEs use same index like parms_id */
8994         }
8995
8996         parms[mIEindex] = &in[ploc+1];
8997         dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8998         if(parms_id[i]==OAD
8999         || parms_id[i]==CONN_NR
9000         || parms_id[i]==CAD) {
9001           if(in[ploc+2] &0x80) {
9002             in[ploc+0] = (byte)(in[ploc+1]+1);
9003             in[ploc+1] = (byte)(in[ploc+2] &0x7f);
9004             in[ploc+2] = 0x80;
9005             parms[mIEindex] = &in[ploc];
9006           }
9007         }
9008         mIEindex++;       /* effects multiIEs only */
9009       }
9010     }
9011
9012     ploc +=(wlen+1);
9013   }
9014   return ;
9015 }
9016
9017 /*------------------------------------------------------------------*/
9018 /* try to match a cip from received BC and HLC                      */
9019 /*------------------------------------------------------------------*/
9020
9021 static byte ie_compare(byte *ie1, byte *ie2)
9022 {
9023   word i;
9024   if(!ie1 || ! ie2) return false;
9025   if(!ie1[0]) return false;
9026   for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false;
9027   return true;
9028 }
9029
9030 static word find_cip(DIVA_CAPI_ADAPTER *a, byte *bc, byte *hlc)
9031 {
9032   word i;
9033   word j;
9034
9035   for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9036
9037   for(j=16;j<29 &&
9038            (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9039   if(j==29) return i;
9040   return j;
9041 }
9042
9043
9044 static byte AddInfo(byte   **add_i,
9045                     byte   **fty_i,
9046                     byte   *esc_chi,
9047                     byte *facility)
9048 {
9049   byte i;
9050   byte j;
9051   byte k;
9052   byte flen;
9053   byte len=0;
9054    /* facility is a nested structure */
9055    /* FTY can be more than once      */
9056
9057         if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
9058   {
9059     add_i[0] = (byte   *)"\x02\x02\x00"; /* use neither b nor d channel */
9060   }
9061
9062   else
9063   {
9064     add_i[0] = (byte   *)"";
9065   }
9066   if(!fty_i[0][0])
9067   {
9068     add_i[3] = (byte   *)"";
9069   }
9070   else
9071   {    /* facility array found  */
9072     for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9073     {
9074       dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9075       len += fty_i[i][0];
9076       len += 2;
9077       flen=fty_i[i][0];
9078       facility[j++]=0x1c; /* copy fac IE */
9079       for(k=0;k<=flen;k++,j++)
9080       {
9081         facility[j]=fty_i[i][k];
9082 /*      dbug(1,dprintf("%x ",facility[j])); */
9083       }
9084     }
9085     facility[0] = len;
9086     add_i[3] = facility;
9087   }
9088 /*  dbug(1,dprintf("FacArrLen=%d ",len)); */
9089   len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9090   len += 4;                          /* calculate length of all */
9091   return(len);
9092 }
9093
9094 /*------------------------------------------------------------------*/
9095 /* voice and codec features                                         */
9096 /*------------------------------------------------------------------*/
9097
9098 static void SetVoiceChannel(PLCI *plci, byte *chi, DIVA_CAPI_ADAPTER *a)
9099 {
9100   byte voice_chi[] = "\x02\x18\x01";
9101   byte channel;
9102
9103   channel = chi[chi[0]]&0x3;
9104   dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9105   voice_chi[2] = (channel) ? channel : 1;
9106   add_p(plci,FTY,"\x02\x01\x07");             /* B On, default on 1 */
9107   add_p(plci,ESC,voice_chi);                  /* Channel */
9108   sig_req(plci,TEL_CTRL,0);
9109   send_req(plci);
9110   if(a->AdvSignalPLCI)
9111   {
9112     adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9113   }
9114 }
9115
9116 static void VoiceChannelOff(PLCI *plci)
9117 {
9118   dbug(1,dprintf("ExtDevOFF"));
9119   add_p(plci,FTY,"\x02\x01\x08");             /* B Off */
9120   sig_req(plci,TEL_CTRL,0);
9121   send_req(plci);
9122   if(plci->adapter->AdvSignalPLCI)
9123   {
9124     adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9125   }
9126 }
9127
9128
9129 static word AdvCodecSupport(DIVA_CAPI_ADAPTER *a, PLCI *plci, APPL *appl,
9130                             byte hook_listen)
9131 {
9132   word j;
9133   PLCI   *splci;
9134
9135   /* check if hardware supports handset with hook states (adv.codec) */
9136   /* or if just a on board codec is supported                        */
9137   /* the advanced codec plci is just for internal use                */
9138
9139   /* diva Pro with on-board codec:                                   */
9140   if(a->profile.Global_Options & HANDSET)
9141   {
9142     /* new call, but hook states are already signalled */
9143     if(a->AdvCodecFLAG)
9144     {
9145       if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9146       {
9147         dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9148         return 0x2001; /* codec in use by another application */
9149       }
9150       if(plci!=NULL)
9151       {
9152         a->AdvSignalPLCI = plci;
9153         plci->tel=ADV_VOICE;
9154       }
9155       return 0;                      /* adv codec still used */
9156     }
9157     if((j=get_plci(a)))
9158     {
9159       splci = &a->plci[j-1];
9160       splci->tel = CODEC_PERMANENT;
9161       /* hook_listen indicates if a facility_req with handset/hook support */
9162       /* was sent. Otherwise if just a call on an external device was made */
9163       /* the codec will be used but the hook info will be discarded (just  */
9164       /* the external controller is in use                                 */
9165       if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9166       else
9167       {
9168         splci->State = ADVANCED_VOICE_NOSIG;
9169         if(plci)
9170         {
9171           plci->spoofed_msg = SPOOFING_REQUIRED;
9172         }
9173                                                /* indicate D-ch connect if  */
9174       }                                        /* codec is connected OK     */
9175       if(plci!=NULL)
9176       {
9177         a->AdvSignalPLCI = plci;
9178         plci->tel=ADV_VOICE;
9179       }
9180       a->AdvSignalAppl = appl;
9181       a->AdvCodecFLAG = true;
9182       a->AdvCodecPLCI = splci;
9183       add_p(splci,CAI,"\x01\x15");
9184       add_p(splci,LLI,"\x01\x00");
9185       add_p(splci,ESC,"\x02\x18\x00");
9186       add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9187       splci->internal_command = PERM_COD_ASSIGN;
9188       dbug(1,dprintf("Codec Assign"));
9189       sig_req(splci,ASSIGN,DSIG_ID);
9190       send_req(splci);
9191     }
9192     else
9193     {
9194       return 0x2001; /* wrong state, no more plcis */
9195     }
9196   }
9197   else if(a->profile.Global_Options & ON_BOARD_CODEC)
9198   {
9199     if(hook_listen) return 0x300B;               /* Facility not supported */
9200                                                  /* no hook with SCOM      */
9201     if(plci!=NULL) plci->tel = CODEC;
9202     dbug(1,dprintf("S/SCOM codec"));
9203     /* first time we use the scom-s codec we must shut down the internal   */
9204     /* handset application of the card. This can be done by an assign with */
9205     /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9206     if(!a->scom_appl_disable){
9207       if((j=get_plci(a))) {
9208         splci = &a->plci[j-1];
9209         add_p(splci,CAI,"\x01\x80");
9210         add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9211         sig_req(splci,ASSIGN,0xC0);  /* 0xc0 is the TEL_ID */
9212         send_req(splci);
9213         a->scom_appl_disable = true;
9214       }
9215       else{
9216         return 0x2001; /* wrong state, no more plcis */
9217       }
9218     }
9219   }
9220   else return 0x300B;               /* Facility not supported */
9221
9222   return 0;
9223 }
9224
9225
9226 static void CodecIdCheck(DIVA_CAPI_ADAPTER *a, PLCI *plci)
9227 {
9228
9229   dbug(1,dprintf("CodecIdCheck"));
9230
9231   if(a->AdvSignalPLCI == plci)
9232   {
9233     dbug(1,dprintf("PLCI owns codec"));
9234     VoiceChannelOff(a->AdvCodecPLCI);
9235     if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9236     {
9237       dbug(1,dprintf("remove temp codec PLCI"));
9238       plci_remove(a->AdvCodecPLCI);
9239       a->AdvCodecFLAG  = 0;
9240       a->AdvCodecPLCI  = NULL;
9241       a->AdvSignalAppl = NULL;
9242     }
9243     a->AdvSignalPLCI = NULL;
9244   }
9245 }
9246
9247 /* -------------------------------------------------------------------
9248     Ask for physical address of card on PCI bus
9249    ------------------------------------------------------------------- */
9250 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  * a,
9251                                         IDI_SYNC_REQ  * preq) {
9252   a->sdram_bar = 0;
9253   if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9254     ENTITY   * e = (ENTITY   *)preq;
9255
9256     e->user[0] = a->Id - 1;
9257     preq->xdi_sdram_bar.info.bar    = 0;
9258     preq->xdi_sdram_bar.Req         = 0;
9259     preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9260
9261     (*(a->request))(e);
9262
9263     a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9264     dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9265   }
9266 }
9267
9268 /* -------------------------------------------------------------------
9269      Ask XDI about extended features
9270    ------------------------------------------------------------------- */
9271 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a) {
9272   IDI_SYNC_REQ   * preq;
9273     char buffer[              ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ?                     (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9274
9275     char features[4];
9276   preq = (IDI_SYNC_REQ   *)&buffer[0];
9277
9278   if (!diva_xdi_extended_features) {
9279     ENTITY   * e = (ENTITY   *)preq;
9280     diva_xdi_extended_features |= 0x80000000;
9281
9282     e->user[0] = a->Id - 1;
9283     preq->xdi_extended_features.Req = 0;
9284     preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9285     preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9286     preq->xdi_extended_features.info.features = &features[0];
9287
9288     (*(a->request))(e);
9289
9290     if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9291       /*
9292          Check features located in the byte '0'
9293          */
9294       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9295         diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9296       }
9297       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9298         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9299         dbug(1,dprintf("XDI provides RxDMA"));
9300       }
9301       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9302         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9303       }
9304       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9305         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9306         dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9307       }
9308
9309     }
9310   }
9311
9312   diva_ask_for_xdi_sdram_bar (a, preq);
9313 }
9314
9315 /*------------------------------------------------------------------*/
9316 /* automatic law                                                    */
9317 /*------------------------------------------------------------------*/
9318 /* called from OS specific part after init time to get the Law              */
9319 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9320 void AutomaticLaw(DIVA_CAPI_ADAPTER   *a)
9321 {
9322   word j;
9323   PLCI   *splci;
9324
9325   if(a->automatic_law) {
9326     return;
9327   }
9328   if((j=get_plci(a))) {
9329     diva_get_extended_adapter_features (a);
9330     splci = &a->plci[j-1];
9331     a->automatic_lawPLCI = splci;
9332     a->automatic_law = 1;
9333     add_p(splci,CAI,"\x01\x80");
9334     add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9335     splci->internal_command = USELAW_REQ;
9336     splci->command = 0;
9337     splci->number = 0;
9338     sig_req(splci,ASSIGN,DSIG_ID);
9339     send_req(splci);
9340   }
9341 }
9342
9343 /* called from OS specific part if an application sends an Capi20Release */
9344 word CapiRelease(word Id)
9345 {
9346   word i, j, appls_found;
9347   PLCI   *plci;
9348   APPL   *this;
9349   DIVA_CAPI_ADAPTER   *a;
9350
9351   if (!Id)
9352   {
9353     dbug(0,dprintf("A: CapiRelease(Id==0)"));
9354     return (_WRONG_APPL_ID);
9355   }
9356
9357   this = &application[Id-1];               /* get application pointer */
9358
9359   for(i=0,appls_found=0; i<max_appl; i++)
9360   {
9361     if(application[i].Id)       /* an application has been found        */
9362     {
9363       appls_found++;
9364     }
9365   }
9366
9367   for(i=0; i<max_adapter; i++)             /* scan all adapters...    */
9368   {
9369     a = &adapter[i];
9370     if (a->request)
9371     {
9372       a->Info_Mask[Id-1] = 0;
9373       a->CIP_Mask[Id-1] = 0;
9374       a->Notification_Mask[Id-1] = 0;
9375       a->codec_listen[Id-1] = NULL;
9376       a->requested_options_table[Id-1] = 0;
9377       for(j=0; j<a->max_plci; j++)           /* and all PLCIs connected */
9378       {                                      /* with this application   */
9379         plci = &a->plci[j];
9380         if(plci->Id)                         /* if plci owns no application */
9381         {                                    /* it may be not jet connected */
9382           if(plci->State==INC_CON_PENDING
9383           || plci->State==INC_CON_ALERT)
9384           {
9385             if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9386             {
9387               clear_c_ind_mask_bit (plci, (word)(Id-1));
9388               if(c_ind_mask_empty (plci))
9389               {
9390                 sig_req(plci,HANGUP,0);
9391                 send_req(plci);
9392                 plci->State = OUTG_DIS_PENDING;
9393               }
9394             }
9395           }
9396           if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9397           {
9398             clear_c_ind_mask_bit (plci, (word)(Id-1));
9399             if(c_ind_mask_empty (plci))
9400             {
9401               if(!plci->appl)
9402               {
9403                 plci_remove(plci);
9404                 plci->State = IDLE;
9405               }
9406             }
9407           }
9408           if(plci->appl==this)
9409           {
9410             plci->appl = NULL;
9411             plci_remove(plci);
9412             plci->State = IDLE;
9413           }
9414         }
9415       }
9416       listen_check(a);
9417
9418       if(a->flag_dynamic_l1_down)
9419       {
9420         if(appls_found==1)            /* last application does a capi release */
9421         {
9422           if((j=get_plci(a)))
9423           {
9424             plci = &a->plci[j-1];
9425             plci->command = 0;
9426             add_p(plci,OAD,"\x01\xfd");
9427             add_p(plci,CAI,"\x01\x80");
9428             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9429             add_p(plci,SHIFT|6,NULL);
9430             add_p(plci,SIN,"\x02\x00\x00");
9431             plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9432             sig_req(plci,ASSIGN,DSIG_ID);
9433             add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9434             sig_req(plci,SIG_CTRL,0);
9435             send_req(plci);
9436           }
9437         }
9438       }
9439       if(a->AdvSignalAppl==this)
9440       {
9441         this->NullCREnable = false;
9442         if (a->AdvCodecPLCI)
9443         {
9444           plci_remove(a->AdvCodecPLCI);
9445           a->AdvCodecPLCI->tel = 0;
9446           a->AdvCodecPLCI->adv_nl = 0;
9447         }
9448         a->AdvSignalAppl = NULL;
9449         a->AdvSignalPLCI = NULL;
9450         a->AdvCodecFLAG = 0;
9451         a->AdvCodecPLCI = NULL;
9452       }
9453     }
9454   }
9455
9456   this->Id = 0;
9457
9458   return GOOD;
9459 }
9460
9461 static word plci_remove_check(PLCI   *plci)
9462 {
9463   if(!plci) return true;
9464   if(!plci->NL.Id && c_ind_mask_empty (plci))
9465   {
9466     if(plci->Sig.Id == 0xff)
9467       plci->Sig.Id = 0;
9468     if(!plci->Sig.Id)
9469     {
9470       dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9471       dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9472       if (plci->Id)
9473       {
9474         CodecIdCheck(plci->adapter, plci);
9475         clear_b1_config (plci);
9476         ncci_remove (plci, 0, false);
9477         plci_free_msg_in_queue (plci);
9478         channel_flow_control_remove (plci);
9479         plci->Id = 0;
9480         plci->State = IDLE;
9481         plci->channels = 0;
9482         plci->appl = NULL;
9483         plci->notifiedcall = 0;
9484       }
9485       listen_check(plci->adapter);
9486       return true;
9487     }
9488   }
9489   return false;
9490 }
9491
9492
9493 /*------------------------------------------------------------------*/
9494
9495 static byte plci_nl_busy (PLCI   *plci)
9496 {
9497   /* only applicable for non-multiplexed protocols */
9498   return (plci->nl_req
9499     || (plci->ncci_ring_list
9500      && plci->adapter->ncci_ch[plci->ncci_ring_list]
9501      && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9502 }
9503
9504
9505 /*------------------------------------------------------------------*/
9506 /* DTMF facilities                                                  */
9507 /*------------------------------------------------------------------*/
9508
9509
9510 static struct
9511 {
9512   byte send_mask;
9513   byte listen_mask;
9514   byte character;
9515   byte code;
9516 } dtmf_digit_map[] =
9517 {
9518   { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9519   { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9520   { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9521   { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9522   { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9523   { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9524   { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9525   { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9526   { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9527   { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9528   { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9529   { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9530   { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9531   { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9532   { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9533   { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9534   { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9535   { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9536   { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9537   { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9538
9539   { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9540   { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9541   { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9542   { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9543   { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9544   { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9545   { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9546   { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9547   { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9548   { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9549   { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9550   { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9551   { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9552   { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9553   { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9554   { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9555   { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9556   { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9557   { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9558   { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9559   { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9560   { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9561   { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9562   { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9563   { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9564   { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9565   { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9566   { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9567   { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9568   { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9569   { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9570   { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9571   { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9572   { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9573   { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9574   { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9575   { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9576   { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9577   { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9578   { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9579   { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9580   { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9581   { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9582   { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9583   { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9584   { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9585   { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9586   { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9587   { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9588   { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9589   { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9590   { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9591
9592 };
9593
9594 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9595
9596
9597 static void dtmf_enable_receiver (PLCI   *plci, byte enable_mask)
9598 {
9599   word min_digit_duration, min_gap_duration;
9600
9601   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9602     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9603     (char   *)(FILE_), __LINE__, enable_mask));
9604
9605   if (enable_mask != 0)
9606   {
9607     min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9608     min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9609     plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9610     PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9611     PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9612     plci->NData[0].PLength = 5;
9613
9614     PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9615     plci->NData[0].PLength += 2;
9616     capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9617
9618   }
9619   else
9620   {
9621     plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9622     plci->NData[0].PLength = 1;
9623
9624     capidtmf_recv_disable (&(plci->capidtmf_state));
9625
9626   }
9627   plci->NData[0].P = plci->internal_req_buffer;
9628   plci->NL.X = plci->NData;
9629   plci->NL.ReqCh = 0;
9630   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9631   plci->adapter->request (&plci->NL);
9632 }
9633
9634
9635 static void dtmf_send_digits (PLCI   *plci, byte   *digit_buffer, word digit_count)
9636 {
9637   word w, i;
9638
9639   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9640     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9641     (char   *)(FILE_), __LINE__, digit_count));
9642
9643   plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9644   w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9645   PUT_WORD (&plci->internal_req_buffer[1], w);
9646   w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9647   PUT_WORD (&plci->internal_req_buffer[3], w);
9648   for (i = 0; i < digit_count; i++)
9649   {
9650     w = 0;
9651     while ((w < DTMF_DIGIT_MAP_ENTRIES)
9652       && (digit_buffer[i] != dtmf_digit_map[w].character))
9653     {
9654       w++;
9655     }
9656     plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9657       dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9658   }
9659   plci->NData[0].PLength = 5 + digit_count;
9660   plci->NData[0].P = plci->internal_req_buffer;
9661   plci->NL.X = plci->NData;
9662   plci->NL.ReqCh = 0;
9663   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9664   plci->adapter->request (&plci->NL);
9665 }
9666
9667
9668 static void dtmf_rec_clear_config (PLCI   *plci)
9669 {
9670
9671   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9672     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9673     (char   *)(FILE_), __LINE__));
9674
9675   plci->dtmf_rec_active = 0;
9676   plci->dtmf_rec_pulse_ms = 0;
9677   plci->dtmf_rec_pause_ms = 0;
9678
9679   capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9680
9681 }
9682
9683
9684 static void dtmf_send_clear_config (PLCI   *plci)
9685 {
9686
9687   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9688     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9689     (char   *)(FILE_), __LINE__));
9690
9691   plci->dtmf_send_requests = 0;
9692   plci->dtmf_send_pulse_ms = 0;
9693   plci->dtmf_send_pause_ms = 0;
9694 }
9695
9696
9697 static void dtmf_prepare_switch (dword Id, PLCI   *plci)
9698 {
9699
9700   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9701     UnMapId (Id), (char   *)(FILE_), __LINE__));
9702
9703   while (plci->dtmf_send_requests != 0)
9704     dtmf_confirmation (Id, plci);
9705 }
9706
9707
9708 static word dtmf_save_config (dword Id, PLCI   *plci, byte Rc)
9709 {
9710
9711   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9712     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9713
9714   return (GOOD);
9715 }
9716
9717
9718 static word dtmf_restore_config (dword Id, PLCI   *plci, byte Rc)
9719 {
9720   word Info;
9721
9722   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9723     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9724
9725   Info = GOOD;
9726   if (plci->B1_facilities & B1_FACILITY_DTMFR)
9727   {
9728     switch (plci->adjust_b_state)
9729     {
9730     case ADJUST_B_RESTORE_DTMF_1:
9731       plci->internal_command = plci->adjust_b_command;
9732       if (plci_nl_busy (plci))
9733       {
9734         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9735         break;
9736       }
9737       dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9738       plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9739       break;
9740     case ADJUST_B_RESTORE_DTMF_2:
9741       if ((Rc != OK) && (Rc != OK_FC))
9742       {
9743         dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9744           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9745         Info = _WRONG_STATE;
9746         break;
9747       }
9748       break;
9749     }
9750   }
9751   return (Info);
9752 }
9753
9754
9755 static void dtmf_command (dword Id, PLCI   *plci, byte Rc)
9756 {
9757   word internal_command, Info;
9758   byte mask;
9759     byte result[4];
9760
9761   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9762     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
9763     plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9764     plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9765
9766   Info = GOOD;
9767   result[0] = 2;
9768   PUT_WORD (&result[1], DTMF_SUCCESS);
9769   internal_command = plci->internal_command;
9770   plci->internal_command = 0;
9771   mask = 0x01;
9772   switch (plci->dtmf_cmd)
9773   {
9774
9775   case DTMF_LISTEN_TONE_START:
9776     mask <<= 1;
9777   case DTMF_LISTEN_MF_START:
9778     mask <<= 1;
9779
9780   case DTMF_LISTEN_START:
9781     switch (internal_command)
9782     {
9783     default:
9784       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9785         B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9786     case DTMF_COMMAND_1:
9787       if (adjust_b_process (Id, plci, Rc) != GOOD)
9788       {
9789         dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9790           UnMapId (Id), (char   *)(FILE_), __LINE__));
9791         Info = _FACILITY_NOT_SUPPORTED;
9792         break;
9793       }
9794       if (plci->internal_command)
9795         return;
9796     case DTMF_COMMAND_2:
9797       if (plci_nl_busy (plci))
9798       {
9799         plci->internal_command = DTMF_COMMAND_2;
9800         return;
9801       }
9802       plci->internal_command = DTMF_COMMAND_3;
9803       dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9804       return;
9805     case DTMF_COMMAND_3:
9806       if ((Rc != OK) && (Rc != OK_FC))
9807       {
9808         dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9809           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9810         Info = _FACILITY_NOT_SUPPORTED;
9811         break;
9812       }
9813
9814       plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9815
9816       plci->dtmf_rec_active |= mask;
9817       break;
9818     }
9819     break;
9820
9821
9822   case DTMF_LISTEN_TONE_STOP:
9823     mask <<= 1;
9824   case DTMF_LISTEN_MF_STOP:
9825     mask <<= 1;
9826
9827   case DTMF_LISTEN_STOP:
9828     switch (internal_command)
9829     {
9830     default:
9831       plci->dtmf_rec_active &= ~mask;
9832       if (plci->dtmf_rec_active)
9833         break;
9834 /*
9835     case DTMF_COMMAND_1:
9836       if (plci->dtmf_rec_active)
9837       {
9838         if (plci_nl_busy (plci))
9839         {
9840           plci->internal_command = DTMF_COMMAND_1;
9841           return;
9842         }
9843         plci->dtmf_rec_active &= ~mask;
9844         plci->internal_command = DTMF_COMMAND_2;
9845         dtmf_enable_receiver (plci, false);
9846         return;
9847       }
9848       Rc = OK;
9849     case DTMF_COMMAND_2:
9850       if ((Rc != OK) && (Rc != OK_FC))
9851       {
9852         dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9853           UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9854         Info = _FACILITY_NOT_SUPPORTED;
9855         break;
9856       }
9857 */
9858       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9859         ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9860     case DTMF_COMMAND_3:
9861       if (adjust_b_process (Id, plci, Rc) != GOOD)
9862       {
9863         dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9864           UnMapId (Id), (char   *)(FILE_), __LINE__));
9865         Info = _FACILITY_NOT_SUPPORTED;
9866         break;
9867       }
9868       if (plci->internal_command)
9869         return;
9870       break;
9871     }
9872     break;
9873
9874
9875   case DTMF_SEND_TONE:
9876     mask <<= 1;
9877   case DTMF_SEND_MF:
9878     mask <<= 1;
9879
9880   case DTMF_DIGITS_SEND:
9881     switch (internal_command)
9882     {
9883     default:
9884       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9885         ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9886         DTMF_COMMAND_1);
9887     case DTMF_COMMAND_1:
9888       if (adjust_b_process (Id, plci, Rc) != GOOD)
9889       {
9890         dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9891           UnMapId (Id), (char   *)(FILE_), __LINE__));
9892         Info = _FACILITY_NOT_SUPPORTED;
9893         break;
9894       }
9895       if (plci->internal_command)
9896         return;
9897     case DTMF_COMMAND_2:
9898       if (plci_nl_busy (plci))
9899       {
9900         plci->internal_command = DTMF_COMMAND_2;
9901         return;
9902       }
9903       plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9904       plci->internal_command = DTMF_COMMAND_3;
9905       dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9906       return;
9907     case DTMF_COMMAND_3:
9908       if ((Rc != OK) && (Rc != OK_FC))
9909       {
9910         dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9911           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9912         if (plci->dtmf_send_requests != 0)
9913           (plci->dtmf_send_requests)--;
9914         Info = _FACILITY_NOT_SUPPORTED;
9915         break;
9916       }
9917       return;
9918     }
9919     break;
9920   }
9921   sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9922     "wws", Info, SELECTOR_DTMF, result);
9923 }
9924
9925
9926 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
9927 {
9928   word Info;
9929   word i, j;
9930   byte mask;
9931     API_PARSE dtmf_parms[5];
9932     byte result[40];
9933
9934   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9935     UnMapId (Id), (char   *)(FILE_), __LINE__));
9936
9937   Info = GOOD;
9938   result[0] = 2;
9939   PUT_WORD (&result[1], DTMF_SUCCESS);
9940   if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9941   {
9942     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9943       UnMapId (Id), (char   *)(FILE_), __LINE__));
9944     Info = _FACILITY_NOT_SUPPORTED;
9945   }
9946   else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9947   {
9948     dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9949       UnMapId (Id), (char   *)(FILE_), __LINE__));
9950     Info = _WRONG_MESSAGE_FORMAT;
9951   }
9952
9953   else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9954     || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9955   {
9956     if (!((a->requested_options_table[appl->Id-1])
9957         & (1L << PRIVATE_DTMF_TONE)))
9958     {
9959       dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9960         UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9961       PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9962     }
9963     else
9964     {
9965       for (i = 0; i < 32; i++)
9966         result[4 + i] = 0;
9967       if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9968       {
9969         for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9970         {
9971           if (dtmf_digit_map[i].listen_mask != 0)
9972             result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9973         }
9974       }
9975       else
9976       {
9977         for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9978         {
9979           if (dtmf_digit_map[i].send_mask != 0)
9980             result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9981         }
9982       }
9983       result[0] = 3 + 32;
9984       result[3] = 32;
9985     }
9986   }
9987
9988   else if (plci == NULL)
9989   {
9990     dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9991       UnMapId (Id), (char   *)(FILE_), __LINE__));
9992     Info = _WRONG_IDENTIFIER;
9993   }
9994   else
9995   {
9996     if (!plci->State
9997      || !plci->NL.Id || plci->nl_remove_id)
9998     {
9999       dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
10000         UnMapId (Id), (char   *)(FILE_), __LINE__));
10001       Info = _WRONG_STATE;
10002     }
10003     else
10004     {
10005       plci->command = 0;
10006       plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
10007       mask = 0x01;
10008       switch (plci->dtmf_cmd)
10009       {
10010
10011       case DTMF_LISTEN_TONE_START:
10012       case DTMF_LISTEN_TONE_STOP:
10013         mask <<= 1;
10014       case DTMF_LISTEN_MF_START:
10015       case DTMF_LISTEN_MF_STOP:
10016         mask <<= 1;
10017         if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10018           & (1L << PRIVATE_DTMF_TONE)))
10019         {
10020           dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10021             UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10022           PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10023           break;
10024         }
10025
10026       case DTMF_LISTEN_START:
10027       case DTMF_LISTEN_STOP:
10028         if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10029          && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10030         {
10031           dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10032             UnMapId (Id), (char   *)(FILE_), __LINE__));
10033           Info = _FACILITY_NOT_SUPPORTED;
10034           break;
10035         }
10036         if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10037         {
10038           if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10039           {
10040             plci->dtmf_rec_pulse_ms = 0;
10041             plci->dtmf_rec_pause_ms = 0;
10042           }
10043           else
10044           {
10045             plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info);
10046             plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info);
10047           }
10048         }
10049         start_internal_command (Id, plci, dtmf_command);
10050         return (false);
10051
10052
10053       case DTMF_SEND_TONE:
10054         mask <<= 1;
10055       case DTMF_SEND_MF:
10056         mask <<= 1;
10057         if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10058           & (1L << PRIVATE_DTMF_TONE)))
10059         {
10060           dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10061             UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10062           PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10063           break;
10064         }
10065
10066       case DTMF_DIGITS_SEND:
10067         if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10068         {
10069           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10070             UnMapId (Id), (char   *)(FILE_), __LINE__));
10071           Info = _WRONG_MESSAGE_FORMAT;
10072           break;
10073         }
10074         if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10075         {
10076           plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info);
10077           plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info);
10078         }
10079         i = 0;
10080         j = 0;
10081         while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10082         {
10083           j = 0;
10084           while ((j < DTMF_DIGIT_MAP_ENTRIES)
10085             && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10086              || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10087           {
10088             j++;
10089           }
10090           i++;
10091         }
10092         if (j == DTMF_DIGIT_MAP_ENTRIES)
10093         {
10094           dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10095             UnMapId (Id), (char   *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10096           PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10097           break;
10098         }
10099         if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10100         {
10101           dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10102             UnMapId (Id), (char   *)(FILE_), __LINE__));
10103           Info = _WRONG_STATE;
10104           break;
10105         }
10106         api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10107         start_internal_command (Id, plci, dtmf_command);
10108         return (false);
10109
10110       default:
10111         dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10112           UnMapId (Id), (char   *)(FILE_), __LINE__, plci->dtmf_cmd));
10113         PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10114       }
10115     }
10116   }
10117   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10118     "wws", Info, SELECTOR_DTMF, result);
10119   return (false);
10120 }
10121
10122
10123 static void dtmf_confirmation (dword Id, PLCI   *plci)
10124 {
10125   word Info;
10126   word i;
10127     byte result[4];
10128
10129   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10130     UnMapId (Id), (char   *)(FILE_), __LINE__));
10131
10132   Info = GOOD;
10133   result[0] = 2;
10134   PUT_WORD (&result[1], DTMF_SUCCESS);
10135   if (plci->dtmf_send_requests != 0)
10136   {
10137     sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10138       "wws", GOOD, SELECTOR_DTMF, result);
10139     (plci->dtmf_send_requests)--;
10140     for (i = 0; i < plci->dtmf_send_requests; i++)
10141       plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];      
10142   }
10143 }
10144
10145
10146 static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length)
10147 {
10148   word i, j, n;
10149
10150   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10151     UnMapId (Id), (char   *)(FILE_), __LINE__));
10152
10153   n = 0;
10154   for (i = 1; i < length; i++)
10155   {
10156     j = 0;
10157     while ((j < DTMF_DIGIT_MAP_ENTRIES)
10158       && ((msg[i] != dtmf_digit_map[j].code)
10159        || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10160     {
10161       j++;
10162     }
10163     if (j < DTMF_DIGIT_MAP_ENTRIES)
10164     {
10165
10166       if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10167        && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10168        && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10169       {
10170         if (n + 1 == i)
10171         {
10172           for (i = length; i > n + 1; i--)
10173             msg[i] = msg[i - 1];
10174           length++;
10175           i++;
10176         }
10177         msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10178       }
10179       plci->tone_last_indication_code = dtmf_digit_map[j].character;
10180
10181       msg[++n] = dtmf_digit_map[j].character;
10182     }
10183   }
10184   if (n != 0)
10185   {
10186     msg[0] = (byte) n;
10187     sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10188   }
10189 }
10190
10191
10192 /*------------------------------------------------------------------*/
10193 /* DTMF parameters                                                  */
10194 /*------------------------------------------------------------------*/
10195
10196 static void dtmf_parameter_write (PLCI   *plci)
10197 {
10198   word i;
10199     byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10200
10201   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10202     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10203     (char   *)(FILE_), __LINE__));
10204
10205   parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10206   parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10207   for (i = 0; i < plci->dtmf_parameter_length; i++)
10208     parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10209   add_p (plci, FTY, parameter_buffer);
10210   sig_req (plci, TEL_CTRL, 0);
10211   send_req (plci);
10212 }
10213
10214
10215 static void dtmf_parameter_clear_config (PLCI   *plci)
10216 {
10217
10218   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10219     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10220     (char   *)(FILE_), __LINE__));
10221
10222   plci->dtmf_parameter_length = 0;
10223 }
10224
10225
10226 static void dtmf_parameter_prepare_switch (dword Id, PLCI   *plci)
10227 {
10228
10229   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10230     UnMapId (Id), (char   *)(FILE_), __LINE__));
10231
10232 }
10233
10234
10235 static word dtmf_parameter_save_config (dword Id, PLCI   *plci, byte Rc)
10236 {
10237
10238   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10239     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10240
10241   return (GOOD);
10242 }
10243
10244
10245 static word dtmf_parameter_restore_config (dword Id, PLCI   *plci, byte Rc)
10246 {
10247   word Info;
10248
10249   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10250     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10251
10252   Info = GOOD;
10253   if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10254    && (plci->dtmf_parameter_length != 0))
10255   {
10256     switch (plci->adjust_b_state)
10257     {
10258     case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10259       plci->internal_command = plci->adjust_b_command;
10260       if (plci->sig_req)
10261       {
10262         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10263         break;
10264       }
10265       dtmf_parameter_write (plci);
10266       plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10267       break;
10268     case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10269       if ((Rc != OK) && (Rc != OK_FC))
10270       {
10271         dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10272           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10273         Info = _WRONG_STATE;
10274         break;
10275       }
10276       break;
10277     }
10278   }
10279   return (Info);
10280 }
10281
10282
10283 /*------------------------------------------------------------------*/
10284 /* Line interconnect facilities                                     */
10285 /*------------------------------------------------------------------*/
10286
10287
10288 LI_CONFIG   *li_config_table;
10289 word li_total_channels;
10290
10291
10292 /*------------------------------------------------------------------*/
10293 /* translate a CHI information element to a channel number          */
10294 /* returns 0xff - any channel                                       */
10295 /*         0xfe - chi wrong coding                                  */
10296 /*         0xfd - D-channel                                         */
10297 /*         0x00 - no channel                                        */
10298 /*         else channel number / PRI: timeslot                      */
10299 /* if channels is provided we accept more than one channel.         */
10300 /*------------------------------------------------------------------*/
10301
10302 static byte chi_to_channel (byte   *chi, dword *pchannelmap)
10303 {
10304   int p;
10305   int i;
10306   dword map;
10307   byte excl;
10308   byte ofs;
10309   byte ch;
10310
10311   if (pchannelmap) *pchannelmap = 0;
10312   if(!chi[0]) return 0xff;
10313   excl = 0;
10314
10315   if(chi[1] & 0x20) {
10316     if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10317     for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10318     if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10319     if((chi[1] |0xc8)!=0xe9) return 0xfe;
10320     if(chi[1] &0x08) excl = 0x40;
10321
10322         /* int. id present */
10323     if(chi[1] &0x40) {
10324       p=i+1;
10325       for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10326       if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10327     }
10328
10329         /* coding standard, Number/Map, Channel Type */
10330     p=i+1;
10331     for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10332     if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10333     if((chi[p]|0xd0)!=0xd3) return 0xfe;
10334
10335         /* Number/Map */
10336     if(chi[p] &0x10) {
10337
10338         /* map */
10339       if((chi[0]-p)==4) ofs = 0;
10340       else if((chi[0]-p)==3) ofs = 1;
10341       else return 0xfe;
10342       ch = 0;
10343       map = 0;
10344       for(i=0; i<4 && p<chi[0]; i++) {
10345         p++;
10346         ch += 8;
10347         map <<= 8;
10348         if(chi[p]) {
10349           for (ch=0; !(chi[p] & (1 << ch)); ch++);
10350           map |= chi[p];
10351         }
10352       }
10353       ch += ofs;
10354       map <<= ofs;
10355     }
10356     else {
10357
10358         /* number */
10359       p=i+1;
10360       ch = chi[p] &0x3f;
10361       if(pchannelmap) {
10362         if((byte)(chi[0]-p)>30) return 0xfe;
10363         map = 0;
10364         for(i=p; i<=chi[0]; i++) {
10365           if ((chi[i] &0x7f) > 31) return 0xfe;
10366           map |= (1L << (chi[i] &0x7f));
10367         }
10368       }
10369       else {
10370         if(p!=chi[0]) return 0xfe;
10371         if (ch > 31) return 0xfe;
10372         map = (1L << ch);
10373       }
10374       if(chi[p] &0x40) return 0xfe;
10375     }
10376     if (pchannelmap) *pchannelmap = map;
10377     else if (map != ((dword)(1L << ch))) return 0xfe;
10378     return (byte)(excl | ch);
10379   }
10380   else {  /* not PRI */
10381     for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10382     if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10383     if(chi[1] &0x08) excl = 0x40;
10384
10385     switch(chi[1] |0x98) {
10386     case 0x98: return 0;
10387     case 0x99:
10388       if (pchannelmap) *pchannelmap = 2;
10389       return excl |1;
10390     case 0x9a:
10391       if (pchannelmap) *pchannelmap = 4;
10392       return excl |2;
10393     case 0x9b: return 0xff;
10394     case 0x9c: return 0xfd; /* d-ch */
10395     default: return 0xfe;
10396     }
10397   }
10398 }
10399
10400
10401 static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id)
10402 {
10403   DIVA_CAPI_ADAPTER   *a;
10404   PLCI   *splci;
10405   byte old_id;
10406
10407   a = plci->adapter;
10408   old_id = plci->li_bchannel_id;
10409   if (a->li_pri)
10410   {
10411     if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10412       li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10413     plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10414     if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10415       li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10416   }
10417   else
10418   {
10419     if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10420     {
10421       if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10422         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10423       plci->li_bchannel_id = bchannel_id & 0x03;
10424       if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10425       {
10426         splci = a->AdvSignalPLCI;
10427         if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10428         {
10429           if ((splci->li_bchannel_id != 0)
10430            && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10431           {
10432             li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10433           }
10434           splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10435           li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10436           dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10437             (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10438             (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10439         }
10440       }
10441       if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10442         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10443     }
10444   }
10445   if ((old_id == 0) && (plci->li_bchannel_id != 0)
10446    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10447   {
10448     mixer_clear_config (plci);
10449   }
10450   dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10451     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10452     (char   *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10453 }
10454
10455
10456 static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi)
10457 {
10458   DIVA_CAPI_ADAPTER   *a;
10459   PLCI   *splci;
10460   byte ch, old_id;
10461
10462   a = plci->adapter;
10463   old_id = plci->li_bchannel_id;
10464   ch = chi_to_channel (chi, NULL);
10465   if (!(ch & 0x80))
10466   {
10467     if (a->li_pri)
10468     {
10469       if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10470         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10471       plci->li_bchannel_id = (ch & 0x1f) + 1;
10472       if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10473         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10474     }
10475     else
10476     {
10477       if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10478       {
10479         if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10480           li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10481         plci->li_bchannel_id = ch & 0x1f;
10482         if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10483         {
10484           splci = a->AdvSignalPLCI;
10485           if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10486           {
10487             if ((splci->li_bchannel_id != 0)
10488              && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10489             {
10490               li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10491             }
10492             splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10493             li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10494             dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10495               (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10496               (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10497           }
10498         }
10499         if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10500           li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10501       }
10502     }
10503   }
10504   if ((old_id == 0) && (plci->li_bchannel_id != 0)
10505    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10506   {
10507     mixer_clear_config (plci);
10508   }
10509   dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10510     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10511     (char   *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10512 }
10513
10514
10515 #define MIXER_MAX_DUMP_CHANNELS 34
10516
10517 static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER   *a)
10518 {
10519 static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10520   word n, i, j;
10521   char *p;
10522     char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10523
10524   dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10525     (dword)(UnMapController (a->Id)), (char   *)(FILE_), __LINE__));
10526
10527   for (i = 0; i < li_total_channels; i++)
10528   {
10529     li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10530     if (li_config_table[i].chflags != 0)
10531       li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10532     else
10533     {
10534       for (j = 0; j < li_total_channels; j++)
10535       {
10536         if (((li_config_table[i].flag_table[j]) != 0)
10537          || ((li_config_table[j].flag_table[i]) != 0))
10538         {
10539           li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10540         }
10541         if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10542          || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10543         {
10544           li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10545         }
10546       }
10547     }
10548   }
10549   for (i = 0; i < li_total_channels; i++)
10550   {
10551     for (j = 0; j < li_total_channels; j++)
10552     {
10553       li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10554       if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10555         li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10556     }
10557   }
10558   for (n = 0; n < li_total_channels; n++)
10559   {
10560     if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10561     {
10562       for (i = 0; i < li_total_channels; i++)
10563       {
10564         if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10565         {
10566           for (j = 0; j < li_total_channels; j++)
10567           {
10568             li_config_table[i].coef_table[j] |=
10569               li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10570           }
10571         }
10572       }
10573     }
10574   }
10575   for (i = 0; i < li_total_channels; i++)
10576   {
10577     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10578     {
10579       li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10580       for (j = 0; j < li_total_channels; j++)
10581       {
10582         if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10583           li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10584       }
10585       if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10586         li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10587     }
10588   }
10589   for (i = 0; i < li_total_channels; i++)
10590   {
10591     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10592     {
10593       for (j = 0; j < li_total_channels; j++)
10594       {
10595         if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10596           li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10597         if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10598           li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10599         if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10600           li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10601         if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10602           li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10603       }
10604       if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10605       {
10606         for (j = 0; j < li_total_channels; j++)
10607         {
10608           if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10609           {
10610             li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10611             if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10612               li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10613           }
10614         }
10615       }
10616       if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10617       {
10618         for (j = 0; j < li_total_channels; j++)
10619         {
10620           if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10621             li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10622         }
10623       }
10624       if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10625       {
10626         for (j = 0; j < li_total_channels; j++)
10627         {
10628           if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10629           {
10630             for (n = 0; n < li_total_channels; n++)
10631             {
10632               if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10633               {
10634                 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10635                 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10636                 {
10637                   li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10638                   if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10639                     li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10640                 }
10641                 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10642                   li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10643               }
10644             }
10645           }
10646         }
10647       }
10648     }
10649   }
10650   for (i = 0; i < li_total_channels; i++)
10651   {
10652     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10653     {
10654       if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10655         li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10656       if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10657         li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10658       if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10659         li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10660       for (j = 0; j < li_total_channels; j++)
10661       {
10662         if ((li_config_table[i].flag_table[j] &
10663           (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10664          || (li_config_table[j].flag_table[i] &
10665           (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10666         {
10667           li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10668         }
10669         if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10670           li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10671         if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10672           li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10673       }
10674       if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10675       {
10676         li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10677         li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10678       }
10679     }
10680   }
10681   for (i = 0; i < li_total_channels; i++)
10682   {
10683     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10684     {
10685       j = 0;
10686       while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10687         j++;
10688       if (j < li_total_channels)
10689       {
10690         for (j = 0; j < li_total_channels; j++)
10691         {
10692           li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10693           if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10694             li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10695         }
10696       }
10697     }
10698   }
10699   n = li_total_channels;
10700   if (n > MIXER_MAX_DUMP_CHANNELS)
10701     n = MIXER_MAX_DUMP_CHANNELS;
10702   p = hex_line;
10703   for (j = 0; j < n; j++)
10704   {
10705     if ((j & 0x7) == 0)
10706       *(p++) = ' ';
10707     *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10708     *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10709   }
10710   *p = '\0';
10711   dbug (1, dprintf ("[%06lx] CURRENT %s",
10712     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10713   p = hex_line;
10714   for (j = 0; j < n; j++)
10715   {
10716     if ((j & 0x7) == 0)
10717       *(p++) = ' ';
10718     *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10719     *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10720   }
10721   *p = '\0';
10722   dbug (1, dprintf ("[%06lx] CHANNEL %s",
10723     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10724   p = hex_line;
10725   for (j = 0; j < n; j++)
10726   {
10727     if ((j & 0x7) == 0)
10728       *(p++) = ' ';
10729     *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10730     *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10731   }
10732   *p = '\0';
10733   dbug (1, dprintf ("[%06lx] CHFLAG  %s",
10734     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10735   for (i = 0; i < n; i++)
10736   {
10737     p = hex_line;
10738     for (j = 0; j < n; j++)
10739     {
10740       if ((j & 0x7) == 0)
10741         *(p++) = ' ';
10742       *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10743       *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10744     }
10745     *p = '\0';
10746     dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10747       (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10748   }
10749   for (i = 0; i < n; i++)
10750   {
10751     p = hex_line;
10752     for (j = 0; j < n; j++)
10753     {
10754       if ((j & 0x7) == 0)
10755         *(p++) = ' ';
10756       *(p++) = hex_digit_table[li_config_table[i].coef_table[j] >> 4];
10757       *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10758     }
10759     *p = '\0';
10760     dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10761       (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10762   }
10763 }
10764
10765
10766 static struct
10767 {
10768   byte mask;
10769   byte line_flags;
10770 } mixer_write_prog_pri[] =
10771 {
10772   { LI_COEF_CH_CH, 0 },
10773   { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10774   { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10775   { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10776 };
10777
10778 static struct
10779 {
10780   byte from_ch;
10781   byte to_ch;
10782   byte mask;
10783   byte xconnect_override;
10784 } mixer_write_prog_bri[] =
10785 {
10786   { 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10787   { 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10788   { 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10789   { 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10790   { 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10791   { 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10792   { 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10793   { 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10794   { 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10795   { 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10796   { 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10797   { 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10798   { 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10799   { 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10800   { 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10801   { 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10802   { 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10803   { 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10804   { 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10805   { 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10806   { 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10807   { 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10808   { 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10809   { 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10810   { 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10811   { 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10812   { 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10813   { 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10814   { 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10815   { 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10816   { 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10817   { 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10818   { 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10819   { 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10820   { 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10821   { 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10822 };
10823
10824 static byte mixer_swapped_index_bri[] =
10825 {
10826   18,  /* B      to B      */
10827   19,  /* Alt B  to B      */
10828   20,  /* PC     to B      */
10829   21,  /* Alt PC to B      */
10830   22,  /* IC     to B      */
10831   23,  /* Alt IC to B      */
10832   24,  /* B      to PC     */
10833   25,  /* Alt B  to PC     */
10834   26,  /* PC     to PC     */
10835   27,  /* Alt PC to PC     */
10836   28,  /* IC     to PC     */
10837   29,  /* Alt IC to PC     */
10838   30,  /* B      to IC     */
10839   31,  /* Alt B  to IC     */
10840   32,  /* PC     to IC     */
10841   33,  /* Alt PC to IC     */
10842   34,  /* IC     to IC     */
10843   35,  /* Alt IC to IC     */
10844   0,   /* Alt B  to Alt B  */
10845   1,   /* B      to Alt B  */
10846   2,   /* Alt PC to Alt B  */
10847   3,   /* PC     to Alt B  */
10848   4,   /* Alt IC to Alt B  */
10849   5,   /* IC     to Alt B  */
10850   6,   /* Alt B  to Alt PC */
10851   7,   /* B      to Alt PC */
10852   8,   /* Alt PC to Alt PC */
10853   9,   /* PC     to Alt PC */
10854   10,  /* Alt IC to Alt PC */
10855   11,  /* IC     to Alt PC */
10856   12,  /* Alt B  to Alt IC */
10857   13,  /* B      to Alt IC */
10858   14,  /* Alt PC to Alt IC */
10859   15,  /* PC     to Alt IC */
10860   16,  /* Alt IC to Alt IC */
10861   17   /* IC     to Alt IC */
10862 };
10863
10864 static struct
10865 {
10866   byte mask;
10867   byte from_pc;
10868   byte to_pc;
10869 } xconnect_write_prog[] =
10870 {
10871   { LI_COEF_CH_CH, false, false },
10872   { LI_COEF_CH_PC, false, true },
10873   { LI_COEF_PC_CH, true, false },
10874   { LI_COEF_PC_PC, true, true }
10875 };
10876
10877
10878 static void xconnect_query_addresses (PLCI   *plci)
10879 {
10880   DIVA_CAPI_ADAPTER   *a;
10881   word w, ch;
10882   byte   *p;
10883
10884   dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10885     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10886     (char   *)(FILE_), __LINE__));
10887
10888   a = plci->adapter;
10889   if (a->li_pri && ((plci->li_bchannel_id == 0)
10890    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10891   {
10892     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10893       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10894       (char   *)(FILE_), __LINE__));
10895     return;
10896   }
10897   p = plci->internal_req_buffer;
10898   ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10899   *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10900   w = ch;
10901   *(p++) = (byte) w;
10902   *(p++) = (byte)(w >> 8);
10903   w = ch | XCONNECT_CHANNEL_PORT_PC;
10904   *(p++) = (byte) w;
10905   *(p++) = (byte)(w >> 8);
10906   plci->NData[0].P = plci->internal_req_buffer;
10907   plci->NData[0].PLength = p - plci->internal_req_buffer;
10908   plci->NL.X = plci->NData;
10909   plci->NL.ReqCh = 0;
10910   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10911   plci->adapter->request (&plci->NL);
10912 }
10913
10914
10915 static void xconnect_write_coefs (PLCI   *plci, word internal_command)
10916 {
10917
10918   dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10919     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10920     (char   *)(FILE_), __LINE__, internal_command));
10921
10922   plci->li_write_command = internal_command;
10923   plci->li_write_channel = 0;
10924 }
10925
10926
10927 static byte xconnect_write_coefs_process (dword Id, PLCI   *plci, byte Rc)
10928 {
10929   DIVA_CAPI_ADAPTER   *a;
10930   word w, n, i, j, r, s, to_ch;
10931   dword d;
10932   byte   *p;
10933   struct xconnect_transfer_address_s   *transfer_address;
10934   byte ch_map[MIXER_CHANNELS_BRI];
10935
10936   dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10937     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10938
10939   a = plci->adapter;
10940   if ((plci->li_bchannel_id == 0)
10941    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10942   {
10943     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10944       UnMapId (Id), (char   *)(FILE_), __LINE__));
10945     return (true);
10946   }
10947   i = a->li_base + (plci->li_bchannel_id - 1);
10948   j = plci->li_write_channel;
10949   p = plci->internal_req_buffer;
10950   if (j != 0)
10951   {
10952     if ((Rc != OK) && (Rc != OK_FC))
10953     {
10954       dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10955         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10956       return (false);
10957     }
10958   }
10959   if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10960   {
10961     r = 0;
10962     s = 0;
10963     if (j < li_total_channels)
10964     {
10965       if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10966       {
10967         s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10968             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10969           ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10970             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10971       }
10972       r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10973       while ((j < li_total_channels)
10974         && ((r == 0)
10975          || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10976          || (!li_config_table[j].adapter->li_pri
10977           && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10978          || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10979            || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10980           && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10981            || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10982          || ((li_config_table[j].adapter->li_base != a->li_base)
10983           && !(r & s &
10984             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10985               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10986             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10987               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10988       {
10989         j++;
10990         if (j < li_total_channels)
10991           r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10992       }
10993     }
10994     if (j < li_total_channels)
10995     {
10996       plci->internal_command = plci->li_write_command;
10997       if (plci_nl_busy (plci))
10998         return (true);
10999       to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
11000       *(p++) = UDATA_REQUEST_XCONNECT_TO;
11001       do
11002       {
11003         if (li_config_table[j].adapter->li_base != a->li_base)
11004         {
11005           r &= s &
11006             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11007               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11008             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11009               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
11010         }
11011         n = 0;
11012         do
11013         {
11014           if (r & xconnect_write_prog[n].mask)
11015           {
11016             if (xconnect_write_prog[n].from_pc)
11017               transfer_address = &(li_config_table[j].send_pc);
11018             else
11019               transfer_address = &(li_config_table[j].send_b);
11020             d = transfer_address->card_address.low;
11021             *(p++) = (byte) d;
11022             *(p++) = (byte)(d >> 8);
11023             *(p++) = (byte)(d >> 16);
11024             *(p++) = (byte)(d >> 24);
11025             d = transfer_address->card_address.high;
11026             *(p++) = (byte) d;
11027             *(p++) = (byte)(d >> 8);
11028             *(p++) = (byte)(d >> 16);
11029             *(p++) = (byte)(d >> 24);
11030             d = transfer_address->offset;
11031             *(p++) = (byte) d;
11032             *(p++) = (byte)(d >> 8);
11033             *(p++) = (byte)(d >> 16);
11034             *(p++) = (byte)(d >> 24);
11035             w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11036             *(p++) = (byte) w;
11037             *(p++) = (byte)(w >> 8);
11038             w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11039               (li_config_table[i].adapter->u_law ?
11040                  (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11041                  (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11042             *(p++) = (byte) w;
11043             *(p++) = (byte) 0;
11044             li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11045           }
11046           n++;
11047         } while ((n < ARRAY_SIZE(xconnect_write_prog))
11048           && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11049         if (n == ARRAY_SIZE(xconnect_write_prog))
11050         {
11051           do
11052           {
11053             j++;
11054             if (j < li_total_channels)
11055               r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11056           } while ((j < li_total_channels)
11057             && ((r == 0)
11058              || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11059              || (!li_config_table[j].adapter->li_pri
11060               && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11061              || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11062                || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11063               && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11064                || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11065              || ((li_config_table[j].adapter->li_base != a->li_base)
11066               && !(r & s &
11067                 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11068                   (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11069                 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11070                   (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11071         }
11072       } while ((j < li_total_channels)
11073         && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11074     }
11075     else if (j == li_total_channels)
11076     {
11077       plci->internal_command = plci->li_write_command;
11078       if (plci_nl_busy (plci))
11079         return (true);
11080       if (a->li_pri)
11081       {
11082         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11083         w = 0;
11084         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11085           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11086         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11087           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11088         *(p++) = (byte) w;
11089         *(p++) = (byte)(w >> 8);
11090       }
11091       else
11092       {
11093         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11094         w = 0;
11095         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11096          && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11097         {
11098           w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11099         }
11100         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11101           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11102         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11103           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11104         *(p++) = (byte) w;
11105         *(p++) = (byte)(w >> 8);
11106         for (j = 0; j < sizeof(ch_map); j += 2)
11107         {
11108           if (plci->li_bchannel_id == 2)
11109           {
11110             ch_map[j] = (byte)(j+1);
11111             ch_map[j+1] = (byte) j;
11112           }
11113           else
11114           {
11115             ch_map[j] = (byte) j;
11116             ch_map[j+1] = (byte)(j+1);
11117           }
11118         }
11119         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11120         {
11121           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11122           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11123           if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11124           {
11125             *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11126               mixer_write_prog_bri[n].xconnect_override :
11127               ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11128             if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11129             {
11130               w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11131               li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11132             }
11133           }
11134           else
11135           {
11136             *p = 0x00;
11137             if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11138             {
11139               w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11140               if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11141                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11142             }
11143           }
11144           p++;
11145         }
11146       }
11147       j = li_total_channels + 1;
11148     }
11149   }
11150   else
11151   {
11152     if (j <= li_total_channels)
11153     {
11154       plci->internal_command = plci->li_write_command;
11155       if (plci_nl_busy (plci))
11156         return (true);
11157       if (j < a->li_base)
11158         j = a->li_base;
11159       if (a->li_pri)
11160       {
11161         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11162         w = 0;
11163         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11164           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11165         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11166           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11167         *(p++) = (byte) w;
11168         *(p++) = (byte)(w >> 8);
11169         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11170         {
11171           *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11172           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11173           {
11174             w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11175             if (w & mixer_write_prog_pri[n].mask)
11176             {
11177               *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11178               li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11179             }
11180             else
11181               *(p++) = 0x00;
11182           }
11183           *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11184           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11185           {
11186             w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11187             if (w & mixer_write_prog_pri[n].mask)
11188             {
11189               *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11190               li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11191             }
11192             else
11193               *(p++) = 0x00;
11194           }
11195         }
11196       }
11197       else
11198       {
11199         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11200         w = 0;
11201         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11202          && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11203         {
11204           w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11205         }
11206         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11207           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11208         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11209           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11210         *(p++) = (byte) w;
11211         *(p++) = (byte)(w >> 8);
11212         for (j = 0; j < sizeof(ch_map); j += 2)
11213         {
11214           if (plci->li_bchannel_id == 2)
11215           {
11216             ch_map[j] = (byte)(j+1);
11217             ch_map[j+1] = (byte) j;
11218           }
11219           else
11220           {
11221             ch_map[j] = (byte) j;
11222             ch_map[j+1] = (byte)(j+1);
11223           }
11224         }
11225         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11226         {
11227           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11228           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11229           if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11230           {
11231             *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11232             w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11233             li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11234           }
11235           else
11236           {
11237             *p = 0x00;
11238             if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11239             {
11240               w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11241               if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11242                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11243             }
11244           }
11245           p++;
11246         }
11247       }
11248       j = li_total_channels + 1;
11249     }
11250   }
11251   plci->li_write_channel = j;
11252   if (p != plci->internal_req_buffer)
11253   {
11254     plci->NData[0].P = plci->internal_req_buffer;
11255     plci->NData[0].PLength = p - plci->internal_req_buffer;
11256     plci->NL.X = plci->NData;
11257     plci->NL.ReqCh = 0;
11258     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11259     plci->adapter->request (&plci->NL);
11260   }
11261   return (true);
11262 }
11263
11264
11265 static void mixer_notify_update (PLCI   *plci, byte others)
11266 {
11267   DIVA_CAPI_ADAPTER   *a;
11268   word i, w;
11269   PLCI   *notify_plci;
11270     byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11271
11272   dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11273     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11274     (char   *)(FILE_), __LINE__, others));
11275
11276   a = plci->adapter;
11277   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11278   {
11279     if (others)
11280       plci->li_notify_update = true;
11281     i = 0;
11282     do
11283     {
11284       notify_plci = NULL;
11285       if (others)
11286       {
11287         while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11288           i++;
11289         if (i < li_total_channels)
11290           notify_plci = li_config_table[i++].plci;
11291       }
11292       else
11293       {
11294         if ((plci->li_bchannel_id != 0)
11295          && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11296         {
11297           notify_plci = plci;
11298         }
11299       }
11300       if ((notify_plci != NULL)
11301        && !notify_plci->li_notify_update
11302        && (notify_plci->appl != NULL)
11303        && (notify_plci->State)
11304        && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11305       {
11306         notify_plci->li_notify_update = true;
11307         ((CAPI_MSG *) msg)->header.length = 18;
11308         ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11309         ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11310         ((CAPI_MSG *) msg)->header.number = 0;
11311         ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11312         ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11313         ((CAPI_MSG *) msg)->header.ncci = 0;
11314         ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11315         ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11316         PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11317         ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11318         w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11319         if (w != _QUEUE_FULL)
11320         {
11321           if (w != 0)
11322           {
11323             dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11324               (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11325               (char   *)(FILE_), __LINE__,
11326               (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11327           }
11328           notify_plci->li_notify_update = false;
11329         }
11330       }
11331     } while (others && (notify_plci != NULL));
11332     if (others)
11333       plci->li_notify_update = false;
11334   }
11335 }
11336
11337
11338 static void mixer_clear_config (PLCI   *plci)
11339 {
11340   DIVA_CAPI_ADAPTER   *a;
11341   word i, j;
11342
11343   dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11344     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11345     (char   *)(FILE_), __LINE__));
11346
11347   plci->li_notify_update = false;
11348   plci->li_plci_b_write_pos = 0;
11349   plci->li_plci_b_read_pos = 0;
11350   plci->li_plci_b_req_pos = 0;
11351   a = plci->adapter;
11352   if ((plci->li_bchannel_id != 0)
11353    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11354   {
11355     i = a->li_base + (plci->li_bchannel_id - 1);
11356     li_config_table[i].curchnl = 0;
11357     li_config_table[i].channel = 0;
11358     li_config_table[i].chflags = 0;
11359     for (j = 0; j < li_total_channels; j++)
11360     {
11361       li_config_table[j].flag_table[i] = 0;
11362       li_config_table[i].flag_table[j] = 0;
11363       li_config_table[i].coef_table[j] = 0;
11364       li_config_table[j].coef_table[i] = 0;
11365     }
11366     if (!a->li_pri)
11367     {
11368       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11369       if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11370       {
11371         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11372         li_config_table[i].curchnl = 0;
11373         li_config_table[i].channel = 0;
11374         li_config_table[i].chflags = 0;
11375         for (j = 0; j < li_total_channels; j++)
11376         {
11377           li_config_table[i].flag_table[j] = 0;
11378           li_config_table[j].flag_table[i] = 0;
11379           li_config_table[i].coef_table[j] = 0;
11380           li_config_table[j].coef_table[i] = 0;
11381         }
11382         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11383         {
11384           i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11385           li_config_table[i].curchnl = 0;
11386           li_config_table[i].channel = 0;
11387           li_config_table[i].chflags = 0;
11388           for (j = 0; j < li_total_channels; j++)
11389           {
11390             li_config_table[i].flag_table[j] = 0;
11391             li_config_table[j].flag_table[i] = 0;
11392             li_config_table[i].coef_table[j] = 0;
11393             li_config_table[j].coef_table[i] = 0;
11394           }
11395         }
11396       }
11397     }
11398   }
11399 }
11400
11401
11402 static void mixer_prepare_switch (dword Id, PLCI   *plci)
11403 {
11404
11405   dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11406     UnMapId (Id), (char   *)(FILE_), __LINE__));
11407
11408   do
11409   {
11410     mixer_indication_coefs_set (Id, plci);
11411   } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11412 }
11413
11414
11415 static word mixer_save_config (dword Id, PLCI   *plci, byte Rc)
11416 {
11417   DIVA_CAPI_ADAPTER   *a;
11418   word i, j;
11419
11420   dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11421     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11422
11423   a = plci->adapter;
11424   if ((plci->li_bchannel_id != 0)
11425    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11426   {
11427     i = a->li_base + (plci->li_bchannel_id - 1);
11428     for (j = 0; j < li_total_channels; j++)
11429     {
11430       li_config_table[i].coef_table[j] &= 0xf;
11431       li_config_table[j].coef_table[i] &= 0xf;
11432     }
11433     if (!a->li_pri)
11434       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11435   }
11436   return (GOOD);
11437 }
11438
11439
11440 static word mixer_restore_config (dword Id, PLCI   *plci, byte Rc)
11441 {
11442   DIVA_CAPI_ADAPTER   *a;
11443   word Info;
11444
11445   dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11446     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11447
11448   Info = GOOD;
11449   a = plci->adapter;
11450   if ((plci->B1_facilities & B1_FACILITY_MIXER)
11451    && (plci->li_bchannel_id != 0)
11452    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11453   {
11454     switch (plci->adjust_b_state)
11455     {
11456     case ADJUST_B_RESTORE_MIXER_1:
11457       if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11458       {
11459         plci->internal_command = plci->adjust_b_command;
11460         if (plci_nl_busy (plci))
11461         {
11462           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11463           break;
11464         }
11465         xconnect_query_addresses (plci);
11466         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11467         break;
11468       }
11469       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11470       Rc = OK;
11471     case ADJUST_B_RESTORE_MIXER_2:
11472     case ADJUST_B_RESTORE_MIXER_3:
11473     case ADJUST_B_RESTORE_MIXER_4:
11474       if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11475       {
11476         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11477           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
11478         Info = _WRONG_STATE;
11479         break;
11480       }
11481       if (Rc == OK)
11482       {
11483         if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11484           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11485         else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11486           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11487       }
11488       else if (Rc == 0)
11489       {
11490         if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11491           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11492         else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11493           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11494       }
11495       if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11496       {
11497         plci->internal_command = plci->adjust_b_command;
11498         break;
11499       }
11500     case ADJUST_B_RESTORE_MIXER_5:
11501       xconnect_write_coefs (plci, plci->adjust_b_command);
11502       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11503       Rc = OK;
11504     case ADJUST_B_RESTORE_MIXER_6:
11505       if (!xconnect_write_coefs_process (Id, plci, Rc))
11506       {
11507         dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11508           UnMapId (Id), (char   *)(FILE_), __LINE__));
11509         Info = _FACILITY_NOT_SUPPORTED;
11510         break;
11511       }
11512       if (plci->internal_command)
11513         break;
11514       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11515     case ADJUST_B_RESTORE_MIXER_7:
11516       break;
11517     }
11518   }
11519   return (Info);
11520 }
11521
11522
11523 static void mixer_command (dword Id, PLCI   *plci, byte Rc)
11524 {
11525   DIVA_CAPI_ADAPTER   *a;
11526   word i, internal_command, Info;
11527
11528   dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11529     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
11530     plci->li_cmd));
11531
11532   Info = GOOD;
11533   a = plci->adapter;
11534   internal_command = plci->internal_command;
11535   plci->internal_command = 0;
11536   switch (plci->li_cmd)
11537   {
11538   case LI_REQ_CONNECT:
11539   case LI_REQ_DISCONNECT:
11540   case LI_REQ_SILENT_UPDATE:
11541     switch (internal_command)
11542     {
11543     default:
11544       if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11545       {
11546         adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11547           B1_FACILITY_MIXER), MIXER_COMMAND_1);
11548       }
11549     case MIXER_COMMAND_1:
11550       if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11551       {
11552         if (adjust_b_process (Id, plci, Rc) != GOOD)
11553         {
11554           dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11555             UnMapId (Id), (char   *)(FILE_), __LINE__));
11556           Info = _FACILITY_NOT_SUPPORTED;
11557           break;
11558         }
11559         if (plci->internal_command)
11560           return;
11561       }
11562       plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11563       if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11564        || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11565         && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11566          ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11567       {
11568         xconnect_write_coefs (plci, MIXER_COMMAND_2);
11569       }
11570       else
11571       {
11572         do
11573         {
11574           mixer_indication_coefs_set (Id, plci);
11575         } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11576       }
11577     case MIXER_COMMAND_2:
11578       if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11579        || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11580         && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11581          ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11582       {
11583         if (!xconnect_write_coefs_process (Id, plci, Rc))
11584         {
11585           dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11586             UnMapId (Id), (char   *)(FILE_), __LINE__));
11587           if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11588           {
11589             do
11590             {
11591               plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11592                 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11593               i = (plci->li_plci_b_write_pos == 0) ?
11594                 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11595             } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11596               && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11597           }
11598           Info = _FACILITY_NOT_SUPPORTED;
11599           break;
11600         }
11601         if (plci->internal_command)
11602           return;
11603       }
11604       if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11605       {
11606         adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11607           ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11608       }
11609     case MIXER_COMMAND_3:
11610       if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11611       {
11612         if (adjust_b_process (Id, plci, Rc) != GOOD)
11613         {
11614           dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11615             UnMapId (Id), (char   *)(FILE_), __LINE__));
11616           Info = _FACILITY_NOT_SUPPORTED;
11617           break;
11618         }
11619         if (plci->internal_command)
11620           return;
11621       }
11622       break;
11623     }
11624     break;
11625   }
11626   if ((plci->li_bchannel_id == 0)
11627    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11628   {
11629     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11630       UnMapId (Id), (char   *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11631   }
11632   else
11633   {
11634     i = a->li_base + (plci->li_bchannel_id - 1);
11635     li_config_table[i].curchnl = plci->li_channel_bits;
11636     if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11637     {
11638       i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11639       li_config_table[i].curchnl = plci->li_channel_bits;
11640       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11641       {
11642         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11643         li_config_table[i].curchnl = plci->li_channel_bits;
11644       }
11645     }
11646   }
11647 }
11648
11649
11650 static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11651   dword plci_b_id, byte connect, dword li_flags)
11652 {
11653   word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11654   PLCI   *plci_b;
11655   DIVA_CAPI_ADAPTER   *a_b;
11656
11657   a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11658   plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11659   ch_a = a->li_base + (plci->li_bchannel_id - 1);
11660   if (!a->li_pri && (plci->tel == ADV_VOICE)
11661    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11662   {
11663     ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11664     ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11665       a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11666   }
11667   else
11668   {
11669     ch_a_v = ch_a;
11670     ch_a_s = ch_a;
11671   }
11672   ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11673   if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11674    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11675   {
11676     ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11677     ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11678       a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11679   }
11680   else
11681   {
11682     ch_b_v = ch_b;
11683     ch_b_s = ch_b;
11684   }
11685   if (connect)
11686   {
11687     li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11688     li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11689     li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11690     li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11691   }
11692   li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11693   li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11694   li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11695   li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11696   if (ch_a_v == ch_b_v)
11697   {
11698     li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11699     li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11700   }
11701   else
11702   {
11703     if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11704     {
11705       for (i = 0; i < li_total_channels; i++)
11706       {
11707         if (i != ch_a_v)
11708           li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11709       }
11710     }
11711     if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11712     {
11713       for (i = 0; i < li_total_channels; i++)
11714       {
11715         if (i != ch_a_s)
11716           li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11717       }
11718     }
11719     if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11720     {
11721       for (i = 0; i < li_total_channels; i++)
11722       {
11723         if (i != ch_a_v)
11724           li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11725       }
11726     }
11727     if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11728     {
11729       for (i = 0; i < li_total_channels; i++)
11730       {
11731         if (i != ch_a_s)
11732           li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11733       }
11734     }
11735   }
11736   if (li_flags & LI_FLAG_CONFERENCE_A_B)
11737   {
11738     li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11739     li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11740     li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11741     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11742   }
11743   if (li_flags & LI_FLAG_CONFERENCE_B_A)
11744   {
11745     li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11746     li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11747     li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11748     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11749   }
11750   if (li_flags & LI_FLAG_MONITOR_A)
11751   {
11752     li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11753     li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11754   }
11755   if (li_flags & LI_FLAG_MONITOR_B)
11756   {
11757     li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11758     li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11759   }
11760   if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11761   {
11762     li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11763     li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11764   }
11765   if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11766   {
11767     li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11768     li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11769   }
11770   if (li_flags & LI_FLAG_MIX_A)
11771   {
11772     li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11773     li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11774   }
11775   if (li_flags & LI_FLAG_MIX_B)
11776   {
11777     li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11778     li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11779   }
11780   if (ch_a_v != ch_a_s)
11781   {
11782     li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11783     li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11784   }
11785   if (ch_b_v != ch_b_s)
11786   {
11787     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11788     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11789   }
11790 }
11791
11792
11793 static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11794   dword plci_b_id, byte connect, dword li_flags)
11795 {
11796   word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11797   PLCI   *plci_b;
11798   DIVA_CAPI_ADAPTER   *a_b;
11799
11800   a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11801   plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11802   ch_a = a->li_base + (plci->li_bchannel_id - 1);
11803   if (!a->li_pri && (plci->tel == ADV_VOICE)
11804    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11805   {
11806     ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11807     ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11808       a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11809   }
11810   else
11811   {
11812     ch_a_v = ch_a;
11813     ch_a_s = ch_a;
11814   }
11815   ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11816   if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11817    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11818   {
11819     ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11820     ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11821       a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11822   }
11823   else
11824   {
11825     ch_b_v = ch_b;
11826     ch_b_s = ch_b;
11827   }
11828   if (connect)
11829   {
11830     li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11831     li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11832     li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11833     li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11834     li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11835     li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11836   }
11837   li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11838   li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11839   li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11840   li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11841   li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11842   li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11843   li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11844   li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11845   if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11846   {
11847     li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11848     li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11849     li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11850     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11851   }
11852   if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11853   {
11854     li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11855     li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11856     li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11857     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11858   }
11859   if (li_flags & LI2_FLAG_MONITOR_B)
11860   {
11861     li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11862     li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11863   }
11864   if (li_flags & LI2_FLAG_MIX_B)
11865   {
11866     li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11867     li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11868   }
11869   if (li_flags & LI2_FLAG_MONITOR_X)
11870     li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11871   if (li_flags & LI2_FLAG_MIX_X)
11872     li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11873   if (li_flags & LI2_FLAG_LOOP_B)
11874   {
11875     li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11876     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11877     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11878     li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11879   }
11880   if (li_flags & LI2_FLAG_LOOP_PC)
11881     li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11882   if (li_flags & LI2_FLAG_LOOP_X)
11883     li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11884   if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11885     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11886   if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11887     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11888   if (ch_a_v != ch_a_s)
11889   {
11890     li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11891     li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11892   }
11893   if (ch_b_v != ch_b_s)
11894   {
11895     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11896     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11897   }
11898 }
11899
11900
11901 static word li_check_main_plci (dword Id, PLCI   *plci)
11902 {
11903   if (plci == NULL)
11904   {
11905     dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11906       UnMapId (Id), (char   *)(FILE_), __LINE__));
11907     return (_WRONG_IDENTIFIER);
11908   }
11909   if (!plci->State
11910    || !plci->NL.Id || plci->nl_remove_id
11911    || (plci->li_bchannel_id == 0))
11912   {
11913     dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11914       UnMapId (Id), (char   *)(FILE_), __LINE__));
11915     return (_WRONG_STATE);
11916   }
11917   li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11918   return (GOOD);
11919 }
11920
11921
11922 static PLCI   *li_check_plci_b (dword Id, PLCI   *plci,
11923   dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11924 {
11925   byte ctlr_b;
11926   PLCI   *plci_b;
11927
11928   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11929     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11930   {
11931     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11932       UnMapId (Id), (char   *)(FILE_), __LINE__));
11933     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11934     return (NULL);
11935   }
11936   ctlr_b = 0;
11937   if ((plci_b_id & 0x7f) != 0)
11938   {
11939     ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11940     if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11941       ctlr_b = 0;
11942   }
11943   if ((ctlr_b == 0)
11944    || (((plci_b_id >> 8) & 0xff) == 0)
11945    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11946   {
11947     dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11948       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11949     PUT_WORD (p_result, _WRONG_IDENTIFIER);
11950     return (NULL);
11951   }
11952   plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11953   if (!plci_b->State
11954    || !plci_b->NL.Id || plci_b->nl_remove_id
11955    || (plci_b->li_bchannel_id == 0))
11956   {
11957     dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11958       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11959     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11960     return (NULL);
11961   }
11962   li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11963   if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11964     ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11965    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11966     || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11967   {
11968     dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11969       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11970     PUT_WORD (p_result, _WRONG_IDENTIFIER);
11971     return (NULL);
11972   }
11973   if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11974     (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11975   {
11976     dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11977       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
11978     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11979     return (NULL);
11980   }
11981   return (plci_b);
11982 }
11983
11984
11985 static PLCI   *li2_check_plci_b (dword Id, PLCI   *plci,
11986   dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11987 {
11988   byte ctlr_b;
11989   PLCI   *plci_b;
11990
11991   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11992     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11993   {
11994     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11995       UnMapId (Id), (char   *)(FILE_), __LINE__));
11996     PUT_WORD (p_result, _WRONG_STATE);
11997     return (NULL);
11998   }
11999   ctlr_b = 0;
12000   if ((plci_b_id & 0x7f) != 0)
12001   {
12002     ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
12003     if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
12004       ctlr_b = 0;
12005   }
12006   if ((ctlr_b == 0)
12007    || (((plci_b_id >> 8) & 0xff) == 0)
12008    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
12009   {
12010     dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
12011       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12012     PUT_WORD (p_result, _WRONG_IDENTIFIER);
12013     return (NULL);
12014   }
12015   plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
12016   if (!plci_b->State
12017    || !plci_b->NL.Id || plci_b->nl_remove_id
12018    || (plci_b->li_bchannel_id == 0)
12019    || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
12020   {
12021     dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
12022       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12023     PUT_WORD (p_result, _WRONG_STATE);
12024     return (NULL);
12025   }
12026   if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12027     ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12028    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12029     || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12030   {
12031     dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12032       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12033     PUT_WORD (p_result, _WRONG_IDENTIFIER);
12034     return (NULL);
12035   }
12036   if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12037     (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12038   {
12039     dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12040       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
12041     PUT_WORD (p_result, _WRONG_STATE);
12042     return (NULL);
12043   }
12044   return (plci_b);
12045 }
12046
12047
12048 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12049 {
12050   word Info;
12051   word i;
12052   dword d, li_flags, plci_b_id;
12053   PLCI   *plci_b;
12054     API_PARSE li_parms[3];
12055     API_PARSE li_req_parms[3];
12056     API_PARSE li_participant_struct[2];
12057     API_PARSE li_participant_parms[3];
12058   word participant_parms_pos;
12059   byte result_buffer[32];
12060   byte   *result;
12061   word result_pos;
12062   word plci_b_write_pos;
12063
12064   dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12065     UnMapId (Id), (char   *)(FILE_), __LINE__));
12066
12067   Info = GOOD;
12068   result = result_buffer;
12069   result_buffer[0] = 0;
12070   if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12071   {
12072     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12073       UnMapId (Id), (char   *)(FILE_), __LINE__));
12074     Info = _FACILITY_NOT_SUPPORTED;
12075   }
12076   else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12077   {
12078     dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12079       UnMapId (Id), (char   *)(FILE_), __LINE__));
12080     Info = _WRONG_MESSAGE_FORMAT;
12081   }
12082   else
12083   {
12084     result_buffer[0] = 3;
12085     PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info));
12086     result_buffer[3] = 0;
12087     switch (GET_WORD (li_parms[0].info))
12088     {
12089     case LI_GET_SUPPORTED_SERVICES:
12090       if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12091       {
12092         result_buffer[0] = 17;
12093         result_buffer[3] = 14;
12094         PUT_WORD (&result_buffer[4], GOOD);
12095         d = 0;
12096         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12097           d |= LI_CONFERENCING_SUPPORTED;
12098         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12099           d |= LI_MONITORING_SUPPORTED;
12100         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12101           d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12102         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12103           d |= LI_CROSS_CONTROLLER_SUPPORTED;
12104         PUT_DWORD (&result_buffer[6], d);
12105         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12106         {
12107           d = 0;
12108           for (i = 0; i < li_total_channels; i++)
12109           {
12110             if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12111              && (li_config_table[i].adapter->li_pri
12112               || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12113             {
12114               d++;
12115             }
12116           }
12117         }
12118         else
12119         {
12120           d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12121         }
12122         PUT_DWORD (&result_buffer[10], d / 2);
12123         PUT_DWORD (&result_buffer[14], d);
12124       }
12125       else
12126       {
12127         result_buffer[0] = 25;
12128         result_buffer[3] = 22;
12129         PUT_WORD (&result_buffer[4], GOOD);
12130         d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12131         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12132           d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12133         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12134           d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12135         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12136           d |= LI2_PC_LOOPING_SUPPORTED;
12137         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12138           d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12139         PUT_DWORD (&result_buffer[6], d);
12140         d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12141         PUT_DWORD (&result_buffer[10], d / 2);
12142         PUT_DWORD (&result_buffer[14], d - 1);
12143         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12144         {
12145           d = 0;
12146           for (i = 0; i < li_total_channels; i++)
12147           {
12148             if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12149              && (li_config_table[i].adapter->li_pri
12150               || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12151             {
12152               d++;
12153             }
12154           }
12155         }
12156         PUT_DWORD (&result_buffer[18], d / 2);
12157         PUT_DWORD (&result_buffer[22], d - 1);
12158       }
12159       break;
12160
12161     case LI_REQ_CONNECT:
12162       if (li_parms[1].length == 8)
12163       {
12164         appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12165         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12166         {
12167           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12168             UnMapId (Id), (char   *)(FILE_), __LINE__));
12169           Info = _WRONG_MESSAGE_FORMAT;
12170           break;
12171         }
12172         plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12173         li_flags = GET_DWORD (li_req_parms[1].info);
12174         Info = li_check_main_plci (Id, plci);
12175         result_buffer[0] = 9;
12176         result_buffer[3] = 6;
12177         PUT_DWORD (&result_buffer[4], plci_b_id);
12178         PUT_WORD (&result_buffer[8], GOOD);
12179         if (Info != GOOD)
12180           break;
12181         result = plci->saved_msg.info;
12182         for (i = 0; i <= result_buffer[0]; i++)
12183           result[i] = result_buffer[i];
12184         plci_b_write_pos = plci->li_plci_b_write_pos;
12185         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12186         if (plci_b == NULL)
12187           break;
12188         li_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12189         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12190         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12191         plci->li_plci_b_write_pos = plci_b_write_pos;
12192       }
12193       else
12194       {
12195         appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12196         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12197         {
12198           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12199             UnMapId (Id), (char   *)(FILE_), __LINE__));
12200           Info = _WRONG_MESSAGE_FORMAT;
12201           break;
12202         }
12203         li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12204         Info = li_check_main_plci (Id, plci);
12205         result_buffer[0] = 7;
12206         result_buffer[3] = 4;
12207         PUT_WORD (&result_buffer[4], Info);
12208         result_buffer[6] = 0;
12209         if (Info != GOOD)
12210           break;
12211         result = plci->saved_msg.info;
12212         for (i = 0; i <= result_buffer[0]; i++)
12213           result[i] = result_buffer[i];
12214         plci_b_write_pos = plci->li_plci_b_write_pos;
12215         participant_parms_pos = 0;
12216         result_pos = 7;
12217         li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags);
12218         while (participant_parms_pos < li_req_parms[1].length)
12219         {
12220           result[result_pos] = 6;
12221           result_pos += 7;
12222           PUT_DWORD (&result[result_pos - 6], 0);
12223           PUT_WORD (&result[result_pos - 2], GOOD);
12224           if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12225             (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12226           {
12227             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12228               UnMapId (Id), (char   *)(FILE_), __LINE__));
12229             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12230             break;
12231           }
12232           if (api_parse (&li_participant_struct[0].info[1],
12233             li_participant_struct[0].length, "dd", li_participant_parms))
12234           {
12235             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12236               UnMapId (Id), (char   *)(FILE_), __LINE__));
12237             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12238             break;
12239           }
12240           plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12241           li_flags = GET_DWORD (li_participant_parms[1].info);
12242           PUT_DWORD (&result[result_pos - 6], plci_b_id);
12243           if (sizeof(result) - result_pos < 7)
12244           {
12245             dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12246               UnMapId (Id), (char   *)(FILE_), __LINE__));
12247             PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12248             break;
12249           }
12250           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12251           if (plci_b != NULL)
12252           {
12253             li2_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12254             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12255               ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12256               LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12257             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12258           }
12259           participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12260             (&li_req_parms[1].info[1]));
12261         }
12262         result[0] = (byte)(result_pos - 1);
12263         result[3] = (byte)(result_pos - 4);
12264         result[6] = (byte)(result_pos - 7);
12265         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12266         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12267          || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12268         {
12269           plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12270           plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12271         }
12272         else
12273           plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12274         plci->li_plci_b_write_pos = plci_b_write_pos;
12275       }
12276       mixer_calculate_coefs (a);
12277       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12278       mixer_notify_update (plci, true);
12279       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12280         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12281       plci->command = 0;
12282       plci->li_cmd = GET_WORD (li_parms[0].info);
12283       start_internal_command (Id, plci, mixer_command);
12284       return (false);
12285
12286     case LI_REQ_DISCONNECT:
12287       if (li_parms[1].length == 4)
12288       {
12289         appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12290         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12291         {
12292           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12293             UnMapId (Id), (char   *)(FILE_), __LINE__));
12294           Info = _WRONG_MESSAGE_FORMAT;
12295           break;
12296         }
12297         plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12298         Info = li_check_main_plci (Id, plci);
12299         result_buffer[0] = 9;
12300         result_buffer[3] = 6;
12301         PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info));
12302         PUT_WORD (&result_buffer[8], GOOD);
12303         if (Info != GOOD)
12304           break;
12305         result = plci->saved_msg.info;
12306         for (i = 0; i <= result_buffer[0]; i++)
12307           result[i] = result_buffer[i];
12308         plci_b_write_pos = plci->li_plci_b_write_pos;
12309         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12310         if (plci_b == NULL)
12311           break;
12312         li_update_connect (Id, a, plci, plci_b_id, false, 0);
12313         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12314         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12315         plci->li_plci_b_write_pos = plci_b_write_pos;
12316       }
12317       else
12318       {
12319         appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12320         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12321         {
12322           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12323             UnMapId (Id), (char   *)(FILE_), __LINE__));
12324           Info = _WRONG_MESSAGE_FORMAT;
12325           break;
12326         }
12327         Info = li_check_main_plci (Id, plci);
12328         result_buffer[0] = 7;
12329         result_buffer[3] = 4;
12330         PUT_WORD (&result_buffer[4], Info);
12331         result_buffer[6] = 0;
12332         if (Info != GOOD)
12333           break;
12334         result = plci->saved_msg.info;
12335         for (i = 0; i <= result_buffer[0]; i++)
12336           result[i] = result_buffer[i];
12337         plci_b_write_pos = plci->li_plci_b_write_pos;
12338         participant_parms_pos = 0;
12339         result_pos = 7;
12340         while (participant_parms_pos < li_req_parms[0].length)
12341         {
12342           result[result_pos] = 6;
12343           result_pos += 7;
12344           PUT_DWORD (&result[result_pos - 6], 0);
12345           PUT_WORD (&result[result_pos - 2], GOOD);
12346           if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12347             (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12348           {
12349             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12350               UnMapId (Id), (char   *)(FILE_), __LINE__));
12351             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12352             break;
12353           }
12354           if (api_parse (&li_participant_struct[0].info[1],
12355             li_participant_struct[0].length, "d", li_participant_parms))
12356           {
12357             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12358               UnMapId (Id), (char   *)(FILE_), __LINE__));
12359             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12360             break;
12361           }
12362           plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12363           PUT_DWORD (&result[result_pos - 6], plci_b_id);
12364           if (sizeof(result) - result_pos < 7)
12365           {
12366             dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12367               UnMapId (Id), (char   *)(FILE_), __LINE__));
12368             PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12369             break;
12370           }
12371           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12372           if (plci_b != NULL)
12373           {
12374             li2_update_connect (Id, a, plci, plci_b_id, false, 0);
12375             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12376             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12377           }
12378           participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12379             (&li_req_parms[0].info[1]));
12380         }
12381         result[0] = (byte)(result_pos - 1);
12382         result[3] = (byte)(result_pos - 4);
12383         result[6] = (byte)(result_pos - 7);
12384         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12385         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12386          || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12387         {
12388           plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12389           plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12390         }
12391         else
12392           plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12393         plci->li_plci_b_write_pos = plci_b_write_pos;
12394       }
12395       mixer_calculate_coefs (a);
12396       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12397       mixer_notify_update (plci, true);
12398       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12399         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12400       plci->command = 0;
12401       plci->li_cmd = GET_WORD (li_parms[0].info);
12402       start_internal_command (Id, plci, mixer_command);
12403       return (false);
12404
12405     case LI_REQ_SILENT_UPDATE:
12406       if (!plci || !plci->State
12407        || !plci->NL.Id || plci->nl_remove_id
12408        || (plci->li_bchannel_id == 0)
12409        || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12410       {
12411         dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12412           UnMapId (Id), (char   *)(FILE_), __LINE__));
12413         return (false);
12414       }
12415       plci_b_write_pos = plci->li_plci_b_write_pos;
12416       if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12417         LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12418       {
12419         dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12420           UnMapId (Id), (char   *)(FILE_), __LINE__));
12421         return (false);
12422       }
12423       i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12424       if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12425        || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12426       {
12427         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12428         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12429       }
12430       else
12431         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12432       plci->li_plci_b_write_pos = plci_b_write_pos;
12433       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12434       plci->command = 0;
12435       plci->li_cmd = GET_WORD (li_parms[0].info);
12436       start_internal_command (Id, plci, mixer_command);
12437       return (false);
12438
12439     default:
12440       dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12441         UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (li_parms[0].info)));
12442       Info = _FACILITY_NOT_SUPPORTED;
12443     }
12444   }
12445   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12446     "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12447   return (false);
12448 }
12449
12450
12451 static void mixer_indication_coefs_set (dword Id, PLCI   *plci)
12452 {
12453   dword d;
12454   DIVA_CAPI_ADAPTER   *a;
12455     byte result[12];
12456
12457   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12458     UnMapId (Id), (char   *)(FILE_), __LINE__));
12459
12460   a = plci->adapter;
12461   if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12462   {
12463     do
12464     {
12465       d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12466       if (!(d & LI_PLCI_B_SKIP_FLAG))
12467       {
12468         if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12469         {
12470           if (d & LI_PLCI_B_DISC_FLAG)
12471           {
12472             result[0] = 5;
12473             PUT_WORD (&result[1], LI_IND_DISCONNECT);
12474             result[3] = 2;
12475             PUT_WORD (&result[4], _LI_USER_INITIATED);
12476           }
12477           else
12478           {
12479             result[0] = 7;
12480             PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12481             result[3] = 4;
12482             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12483           }
12484         }
12485         else
12486         {
12487           if (d & LI_PLCI_B_DISC_FLAG)
12488           {
12489             result[0] = 9;
12490             PUT_WORD (&result[1], LI_IND_DISCONNECT);
12491             result[3] = 6;
12492             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12493             PUT_WORD (&result[8], _LI_USER_INITIATED);
12494           }
12495           else
12496           {
12497             result[0] = 7;
12498             PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12499             result[3] = 4;
12500             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12501           }
12502         }
12503         sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12504           "ws", SELECTOR_LINE_INTERCONNECT, result);
12505       }
12506       plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12507         0 : plci->li_plci_b_read_pos + 1;
12508     } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12509   }
12510 }
12511
12512
12513 static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length)
12514 {
12515   word i, j, ch;
12516   struct xconnect_transfer_address_s s,   *p;
12517   DIVA_CAPI_ADAPTER   *a;
12518
12519   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12520     UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12521
12522   a = plci->adapter;
12523   i = 1;
12524   for (i = 1; i < length; i += 16)
12525   {
12526     s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12527     s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12528     s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12529     ch = msg[i+12] | (msg[i+13] << 8);
12530     j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12531     if (!a->li_pri && (plci->li_bchannel_id == 2))
12532       j = 1 - j;
12533     j += a->li_base;
12534     if (ch & XCONNECT_CHANNEL_PORT_PC)
12535       p = &(li_config_table[j].send_pc);
12536     else
12537       p = &(li_config_table[j].send_b);
12538     p->card_address.low = s.card_address.low;
12539     p->card_address.high = s.card_address.high;
12540     p->offset = s.offset;
12541     li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12542   }
12543   if (plci->internal_command_queue[0]
12544    && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12545     || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12546     || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12547   {
12548     (*(plci->internal_command_queue[0]))(Id, plci, 0);
12549     if (!plci->internal_command)
12550       next_internal_command (Id, plci);
12551   }
12552   mixer_notify_update (plci, true);
12553 }
12554
12555
12556 static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length)
12557 {
12558
12559   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12560     UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12561
12562 }
12563
12564
12565 static byte mixer_notify_source_removed (PLCI   *plci, dword plci_b_id)
12566 {
12567   word plci_b_write_pos;
12568
12569   plci_b_write_pos = plci->li_plci_b_write_pos;
12570   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12571     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12572   {
12573     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12574       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12575       (char   *)(FILE_), __LINE__));
12576     return (false);
12577   }
12578   plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12579   plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12580   plci->li_plci_b_write_pos = plci_b_write_pos;
12581   return (true);
12582 }
12583
12584
12585 static void mixer_remove (PLCI   *plci)
12586 {
12587   DIVA_CAPI_ADAPTER   *a;
12588   PLCI   *notify_plci;
12589   dword plci_b_id;
12590   word i, j;
12591
12592   dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12593     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12594     (char   *)(FILE_), __LINE__));
12595
12596   a = plci->adapter;
12597   plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12598   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12599   {
12600     if ((plci->li_bchannel_id != 0)
12601      && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12602     {
12603       i = a->li_base + (plci->li_bchannel_id - 1);
12604       if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12605       {
12606         for (j = 0; j < li_total_channels; j++)
12607         {
12608           if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12609            || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12610           {
12611             notify_plci = li_config_table[j].plci;
12612             if ((notify_plci != NULL)
12613              && (notify_plci != plci)
12614              && (notify_plci->appl != NULL)
12615              && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12616              && (notify_plci->State)
12617              && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12618             {
12619               mixer_notify_source_removed (notify_plci, plci_b_id);
12620             }
12621           }
12622         }
12623         mixer_clear_config (plci);
12624         mixer_calculate_coefs (a);
12625         mixer_notify_update (plci, true);
12626       }
12627       li_config_table[i].plci = NULL;
12628       plci->li_bchannel_id = 0;
12629     }
12630   }
12631 }
12632
12633
12634 /*------------------------------------------------------------------*/
12635 /* Echo canceller facilities                                        */
12636 /*------------------------------------------------------------------*/
12637
12638
12639 static void ec_write_parameters (PLCI   *plci)
12640 {
12641   word w;
12642     byte parameter_buffer[6];
12643
12644   dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12645     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12646     (char   *)(FILE_), __LINE__));
12647
12648   parameter_buffer[0] = 5;
12649   parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12650   PUT_WORD (&parameter_buffer[2], plci->ec_idi_options);
12651   plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12652   w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12653   PUT_WORD (&parameter_buffer[4], w);
12654   add_p (plci, FTY, parameter_buffer);
12655   sig_req (plci, TEL_CTRL, 0);
12656   send_req (plci);
12657 }
12658
12659
12660 static void ec_clear_config (PLCI   *plci)
12661 {
12662
12663   dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12664     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12665     (char   *)(FILE_), __LINE__));
12666
12667   plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12668     LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12669   plci->ec_tail_length = 0;
12670 }
12671
12672
12673 static void ec_prepare_switch (dword Id, PLCI   *plci)
12674 {
12675
12676   dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12677     UnMapId (Id), (char   *)(FILE_), __LINE__));
12678
12679 }
12680
12681
12682 static word ec_save_config (dword Id, PLCI   *plci, byte Rc)
12683 {
12684
12685   dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12686     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12687
12688   return (GOOD);
12689 }
12690
12691
12692 static word ec_restore_config (dword Id, PLCI   *plci, byte Rc)
12693 {
12694   word Info;
12695
12696   dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12697     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12698
12699   Info = GOOD;
12700   if (plci->B1_facilities & B1_FACILITY_EC)
12701   {
12702     switch (plci->adjust_b_state)
12703     {
12704     case ADJUST_B_RESTORE_EC_1:
12705       plci->internal_command = plci->adjust_b_command;
12706       if (plci->sig_req)
12707       {
12708         plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12709         break;
12710       }
12711       ec_write_parameters (plci);
12712       plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12713       break;
12714     case ADJUST_B_RESTORE_EC_2:
12715       if ((Rc != OK) && (Rc != OK_FC))
12716       {
12717         dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12718           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12719         Info = _WRONG_STATE;
12720         break;
12721       }
12722       break;
12723     }
12724   }
12725   return (Info);
12726 }
12727
12728
12729 static void ec_command (dword Id, PLCI   *plci, byte Rc)
12730 {
12731   word internal_command, Info;
12732     byte result[8];
12733
12734   dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12735     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
12736     plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12737
12738   Info = GOOD;
12739   if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12740   {
12741     result[0] = 2;
12742     PUT_WORD (&result[1], EC_SUCCESS);
12743   }
12744   else
12745   {
12746     result[0] = 5;
12747     PUT_WORD (&result[1], plci->ec_cmd);
12748     result[3] = 2;
12749     PUT_WORD (&result[4], GOOD);
12750   }
12751   internal_command = plci->internal_command;
12752   plci->internal_command = 0;
12753   switch (plci->ec_cmd)
12754   {
12755   case EC_ENABLE_OPERATION:
12756   case EC_FREEZE_COEFFICIENTS:
12757   case EC_RESUME_COEFFICIENT_UPDATE:
12758   case EC_RESET_COEFFICIENTS:
12759     switch (internal_command)
12760     {
12761     default:
12762       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12763         B1_FACILITY_EC), EC_COMMAND_1);
12764     case EC_COMMAND_1:
12765       if (adjust_b_process (Id, plci, Rc) != GOOD)
12766       {
12767         dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12768           UnMapId (Id), (char   *)(FILE_), __LINE__));
12769         Info = _FACILITY_NOT_SUPPORTED;
12770         break;
12771       }
12772       if (plci->internal_command)
12773         return;
12774     case EC_COMMAND_2:
12775       if (plci->sig_req)
12776       {
12777         plci->internal_command = EC_COMMAND_2;
12778         return;
12779       }
12780       plci->internal_command = EC_COMMAND_3;
12781       ec_write_parameters (plci);
12782       return;
12783     case EC_COMMAND_3:
12784       if ((Rc != OK) && (Rc != OK_FC))
12785       {
12786         dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12787           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12788         Info = _FACILITY_NOT_SUPPORTED;
12789         break;
12790       }
12791       break;
12792     }
12793     break;
12794
12795   case EC_DISABLE_OPERATION:
12796     switch (internal_command)
12797     {
12798     default:
12799     case EC_COMMAND_1:
12800       if (plci->B1_facilities & B1_FACILITY_EC)
12801       {
12802         if (plci->sig_req)
12803         {
12804           plci->internal_command = EC_COMMAND_1;
12805           return;
12806         }
12807         plci->internal_command = EC_COMMAND_2;
12808         ec_write_parameters (plci);
12809         return;
12810       }
12811       Rc = OK;
12812     case EC_COMMAND_2:
12813       if ((Rc != OK) && (Rc != OK_FC))
12814       {
12815         dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12816           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12817         Info = _FACILITY_NOT_SUPPORTED;
12818         break;
12819       }
12820       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12821         ~B1_FACILITY_EC), EC_COMMAND_3);
12822     case EC_COMMAND_3:
12823       if (adjust_b_process (Id, plci, Rc) != GOOD)
12824       {
12825         dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12826           UnMapId (Id), (char   *)(FILE_), __LINE__));
12827         Info = _FACILITY_NOT_SUPPORTED;
12828         break;
12829       }
12830       if (plci->internal_command)
12831         return;
12832       break;
12833     }
12834     break;
12835   }
12836   sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12837     "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12838     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12839 }
12840
12841
12842 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12843 {
12844   word Info;
12845   word opt;
12846     API_PARSE ec_parms[3];
12847     byte result[16];
12848
12849   dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12850     UnMapId (Id), (char   *)(FILE_), __LINE__));
12851
12852   Info = GOOD;
12853   result[0] = 0;
12854   if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12855   {
12856     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12857       UnMapId (Id), (char   *)(FILE_), __LINE__));
12858     Info = _FACILITY_NOT_SUPPORTED;
12859   }
12860   else
12861   {
12862     if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12863     {
12864       if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12865       {
12866         dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12867           UnMapId (Id), (char   *)(FILE_), __LINE__));
12868         Info = _WRONG_MESSAGE_FORMAT;
12869       }
12870       else
12871       {
12872         if (plci == NULL)
12873         {
12874           dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12875             UnMapId (Id), (char   *)(FILE_), __LINE__));
12876           Info = _WRONG_IDENTIFIER;
12877         }
12878         else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12879         {
12880           dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12881             UnMapId (Id), (char   *)(FILE_), __LINE__));
12882           Info = _WRONG_STATE;
12883         }
12884         else
12885         {
12886           plci->command = 0;
12887           plci->ec_cmd = GET_WORD (ec_parms[0].info);
12888           plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12889           result[0] = 2;
12890           PUT_WORD (&result[1], EC_SUCCESS);
12891           if (msg[1].length >= 4)
12892           {
12893             opt = GET_WORD (&ec_parms[0].info[2]);
12894             plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12895               LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12896             if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12897               plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12898             if (opt & EC_DETECT_DISABLE_TONE)
12899               plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12900             if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12901               plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12902             if (msg[1].length >= 6)
12903             {
12904               plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]);
12905             }
12906           }
12907           switch (plci->ec_cmd)
12908           {
12909           case EC_ENABLE_OPERATION:
12910             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12911             start_internal_command (Id, plci, ec_command);
12912             return (false);
12913
12914           case EC_DISABLE_OPERATION:
12915             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12916               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12917               LEC_RESET_COEFFICIENTS;
12918             start_internal_command (Id, plci, ec_command);
12919             return (false);
12920
12921           case EC_FREEZE_COEFFICIENTS:
12922             plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12923             start_internal_command (Id, plci, ec_command);
12924             return (false);
12925
12926           case EC_RESUME_COEFFICIENT_UPDATE:
12927             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12928             start_internal_command (Id, plci, ec_command);
12929             return (false);
12930
12931           case EC_RESET_COEFFICIENTS:
12932             plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12933             start_internal_command (Id, plci, ec_command);
12934             return (false);
12935
12936           default:
12937             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12938               UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
12939             PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12940           }
12941         }
12942       }
12943     }
12944     else
12945     {
12946       if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12947       {
12948         dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12949           UnMapId (Id), (char   *)(FILE_), __LINE__));
12950         Info = _WRONG_MESSAGE_FORMAT;
12951       }
12952       else
12953       {
12954         if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12955         {
12956           result[0] = 11;
12957           PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12958           result[3] = 8;
12959           PUT_WORD (&result[4], GOOD);
12960           PUT_WORD (&result[6], 0x0007);
12961           PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12962           PUT_WORD (&result[10], 0);
12963         }
12964         else if (plci == NULL)
12965         {
12966           dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12967             UnMapId (Id), (char   *)(FILE_), __LINE__));
12968           Info = _WRONG_IDENTIFIER;
12969         }
12970         else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12971         {
12972           dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12973             UnMapId (Id), (char   *)(FILE_), __LINE__));
12974           Info = _WRONG_STATE;
12975         }
12976         else
12977         {
12978           plci->command = 0;
12979           plci->ec_cmd = GET_WORD (ec_parms[0].info);
12980           plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12981           result[0] = 5;
12982           PUT_WORD (&result[1], plci->ec_cmd);
12983           result[3] = 2;
12984           PUT_WORD (&result[4], GOOD);
12985           plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12986             LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12987           plci->ec_tail_length = 0;
12988           if (ec_parms[1].length >= 2)
12989           {
12990             opt = GET_WORD (&ec_parms[1].info[1]);
12991             if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12992               plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12993             if (opt & EC_DETECT_DISABLE_TONE)
12994               plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12995             if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12996               plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12997             if (ec_parms[1].length >= 4)
12998             {
12999               plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]);
13000             }
13001           }
13002           switch (plci->ec_cmd)
13003           {
13004           case EC_ENABLE_OPERATION:
13005             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
13006             start_internal_command (Id, plci, ec_command);
13007             return (false);
13008
13009           case EC_DISABLE_OPERATION:
13010             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
13011               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
13012               LEC_RESET_COEFFICIENTS;
13013             start_internal_command (Id, plci, ec_command);
13014             return (false);
13015
13016           default:
13017             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
13018               UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
13019             PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
13020           }
13021         }
13022       }
13023     }
13024   }
13025   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
13026     "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13027     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13028   return (false);
13029 }
13030
13031
13032 static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length)
13033 {
13034     byte result[8];
13035
13036   dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13037     UnMapId (Id), (char   *)(FILE_), __LINE__));
13038
13039   if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13040   {
13041     if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13042     {
13043       result[0] = 2;
13044       PUT_WORD (&result[1], 0);
13045       switch (msg[1])
13046       {
13047       case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13048         PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13049         break;
13050       case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13051         PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13052         break;
13053       case LEC_DISABLE_RELEASED:
13054         PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13055         break;
13056       }
13057     }
13058     else
13059     {
13060       result[0] = 5;
13061       PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13062       result[3] = 2;
13063       PUT_WORD (&result[4], 0);
13064       switch (msg[1])
13065       {
13066       case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13067         PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13068         break;
13069       case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13070         PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13071         break;
13072       case LEC_DISABLE_RELEASED:
13073         PUT_WORD (&result[4], EC_BYPASS_RELEASED);
13074         break;
13075       }
13076     }
13077     sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13078       PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13079   }
13080 }
13081
13082
13083
13084 /*------------------------------------------------------------------*/
13085 /* Advanced voice                                                   */
13086 /*------------------------------------------------------------------*/
13087
13088 static void adv_voice_write_coefs (PLCI   *plci, word write_command)
13089 {
13090   DIVA_CAPI_ADAPTER   *a;
13091   word i;
13092   byte *p;
13093
13094   word w, n, j, k;
13095   byte ch_map[MIXER_CHANNELS_BRI];
13096
13097     byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13098
13099   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13100     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13101     (char   *)(FILE_), __LINE__, write_command));
13102
13103   a = plci->adapter;
13104   p = coef_buffer + 1;
13105   *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13106   i = 0;
13107   while (i + sizeof(word) <= a->adv_voice_coef_length)
13108   {
13109     PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13110     p += 2;
13111     i += 2;
13112   }
13113   while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13114   {
13115     PUT_WORD (p, 0x8000);
13116     p += 2;
13117     i += 2;
13118   }
13119
13120   if (!a->li_pri && (plci->li_bchannel_id == 0))
13121   {
13122     if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13123     {
13124       plci->li_bchannel_id = 1;
13125       li_config_table[a->li_base].plci = plci;
13126       dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13127         (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13128         (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13129     }
13130     else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13131     {
13132       plci->li_bchannel_id = 2;
13133       li_config_table[a->li_base + 1].plci = plci;
13134       dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13135         (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13136         (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13137     }
13138   }
13139   if (!a->li_pri && (plci->li_bchannel_id != 0)
13140    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13141   {
13142     i = a->li_base + (plci->li_bchannel_id - 1);
13143     switch (write_command)
13144     {
13145     case ADV_VOICE_WRITE_ACTIVATION:
13146       j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13147       k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13148       if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13149       {
13150         li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13151         li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13152       }
13153       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13154       {
13155         li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13156         li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13157         li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13158         li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13159       }
13160       mixer_calculate_coefs (a);
13161       li_config_table[i].curchnl = li_config_table[i].channel;
13162       li_config_table[j].curchnl = li_config_table[j].channel;
13163       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13164         li_config_table[k].curchnl = li_config_table[k].channel;
13165       break;
13166
13167     case ADV_VOICE_WRITE_DEACTIVATION:
13168       for (j = 0; j < li_total_channels; j++)
13169       {
13170         li_config_table[i].flag_table[j] = 0;
13171         li_config_table[j].flag_table[i] = 0;
13172       }
13173       k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13174       for (j = 0; j < li_total_channels; j++)
13175       {
13176         li_config_table[k].flag_table[j] = 0;
13177         li_config_table[j].flag_table[k] = 0;
13178       }
13179       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13180       {
13181         k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13182         for (j = 0; j < li_total_channels; j++)
13183         {
13184           li_config_table[k].flag_table[j] = 0;
13185           li_config_table[j].flag_table[k] = 0;
13186         }
13187       }
13188       mixer_calculate_coefs (a);
13189       break;
13190     }
13191     if (plci->B1_facilities & B1_FACILITY_MIXER)
13192     {
13193       w = 0;
13194       if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13195         w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13196       if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13197         w |= MIXER_FEATURE_ENABLE_TX_DATA;
13198       if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13199         w |= MIXER_FEATURE_ENABLE_RX_DATA;
13200       *(p++) = (byte) w;
13201       *(p++) = (byte)(w >> 8);
13202       for (j = 0; j < sizeof(ch_map); j += 2)
13203       {
13204         ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13205         ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13206       }
13207       for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13208       {
13209         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13210         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13211         if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13212         {
13213           *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13214           w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13215           li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13216         }
13217         else
13218         {
13219           *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13220             a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13221         }
13222       }
13223     }
13224     else
13225     {
13226       for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13227         *(p++) = a->adv_voice_coef_buffer[i];
13228     }
13229   }
13230   else
13231
13232   {
13233     for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13234       *(p++) = a->adv_voice_coef_buffer[i];
13235   }
13236   coef_buffer[0] = (p - coef_buffer) - 1;
13237   add_p (plci, FTY, coef_buffer);
13238   sig_req (plci, TEL_CTRL, 0);
13239   send_req (plci);
13240 }
13241
13242
13243 static void adv_voice_clear_config (PLCI   *plci)
13244 {
13245   DIVA_CAPI_ADAPTER   *a;
13246
13247   word i, j;
13248
13249
13250   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13251     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13252     (char   *)(FILE_), __LINE__));
13253
13254   a = plci->adapter;
13255   if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13256   {
13257     a->adv_voice_coef_length = 0;
13258
13259     if (!a->li_pri && (plci->li_bchannel_id != 0)
13260      && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13261     {
13262       i = a->li_base + (plci->li_bchannel_id - 1);
13263       li_config_table[i].curchnl = 0;
13264       li_config_table[i].channel = 0;
13265       li_config_table[i].chflags = 0;
13266       for (j = 0; j < li_total_channels; j++)
13267       {
13268         li_config_table[i].flag_table[j] = 0;
13269         li_config_table[j].flag_table[i] = 0;
13270         li_config_table[i].coef_table[j] = 0;
13271         li_config_table[j].coef_table[i] = 0;
13272       }
13273       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13274       i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13275       li_config_table[i].curchnl = 0;
13276       li_config_table[i].channel = 0;
13277       li_config_table[i].chflags = 0;
13278       for (j = 0; j < li_total_channels; j++)
13279       {
13280         li_config_table[i].flag_table[j] = 0;
13281         li_config_table[j].flag_table[i] = 0;
13282         li_config_table[i].coef_table[j] = 0;
13283         li_config_table[j].coef_table[i] = 0;
13284       }
13285       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13286       {
13287         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13288         li_config_table[i].curchnl = 0;
13289         li_config_table[i].channel = 0;
13290         li_config_table[i].chflags = 0;
13291         for (j = 0; j < li_total_channels; j++)
13292         {
13293           li_config_table[i].flag_table[j] = 0;
13294           li_config_table[j].flag_table[i] = 0;
13295           li_config_table[i].coef_table[j] = 0;
13296           li_config_table[j].coef_table[i] = 0;
13297         }
13298       }
13299     }
13300
13301   }
13302 }
13303
13304
13305 static void adv_voice_prepare_switch (dword Id, PLCI   *plci)
13306 {
13307
13308   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13309     UnMapId (Id), (char   *)(FILE_), __LINE__));
13310
13311 }
13312
13313
13314 static word adv_voice_save_config (dword Id, PLCI   *plci, byte Rc)
13315 {
13316
13317   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13318     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13319
13320   return (GOOD);
13321 }
13322
13323
13324 static word adv_voice_restore_config (dword Id, PLCI   *plci, byte Rc)
13325 {
13326   DIVA_CAPI_ADAPTER   *a;
13327   word Info;
13328
13329   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13330     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13331
13332   Info = GOOD;
13333   a = plci->adapter;
13334   if ((plci->B1_facilities & B1_FACILITY_VOICE)
13335    && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13336   {
13337     switch (plci->adjust_b_state)
13338     {
13339     case ADJUST_B_RESTORE_VOICE_1:
13340       plci->internal_command = plci->adjust_b_command;
13341       if (plci->sig_req)
13342       {
13343         plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13344         break;
13345       }
13346       adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13347       plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13348       break;
13349     case ADJUST_B_RESTORE_VOICE_2:
13350       if ((Rc != OK) && (Rc != OK_FC))
13351       {
13352         dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13353           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13354         Info = _WRONG_STATE;
13355         break;
13356       }
13357       break;
13358     }
13359   }
13360   return (Info);
13361 }
13362
13363
13364
13365
13366 /*------------------------------------------------------------------*/
13367 /* B1 resource switching                                            */
13368 /*------------------------------------------------------------------*/
13369
13370 static byte b1_facilities_table[] =
13371 {
13372   0x00,  /* 0  No bchannel resources      */
13373   0x00,  /* 1  Codec (automatic law)      */
13374   0x00,  /* 2  Codec (A-law)              */
13375   0x00,  /* 3  Codec (y-law)              */
13376   0x00,  /* 4  HDLC for X.21              */
13377   0x00,  /* 5  HDLC                       */
13378   0x00,  /* 6  External Device 0          */
13379   0x00,  /* 7  External Device 1          */
13380   0x00,  /* 8  HDLC 56k                   */
13381   0x00,  /* 9  Transparent                */
13382   0x00,  /* 10 Loopback to network        */
13383   0x00,  /* 11 Test pattern to net        */
13384   0x00,  /* 12 Rate adaptation sync       */
13385   0x00,  /* 13 Rate adaptation async      */
13386   0x00,  /* 14 R-Interface                */
13387   0x00,  /* 15 HDLC 128k leased line      */
13388   0x00,  /* 16 FAX                        */
13389   0x00,  /* 17 Modem async                */
13390   0x00,  /* 18 Modem sync HDLC            */
13391   0x00,  /* 19 V.110 async HDLC           */
13392   0x12,  /* 20 Adv voice (Trans,mixer)    */
13393   0x00,  /* 21 Codec connected to IC      */
13394   0x0c,  /* 22 Trans,DTMF                 */
13395   0x1e,  /* 23 Trans,DTMF+mixer           */
13396   0x1f,  /* 24 Trans,DTMF+mixer+local     */
13397   0x13,  /* 25 Trans,mixer+local          */
13398   0x12,  /* 26 HDLC,mixer                 */
13399   0x12,  /* 27 HDLC 56k,mixer             */
13400   0x2c,  /* 28 Trans,LEC+DTMF             */
13401   0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13402   0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13403   0x2c,  /* 31 RTP,LEC+DTMF               */
13404   0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13405   0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13406   0x00,  /* 34 Signaling task             */
13407   0x00,  /* 35 PIAFS                      */
13408   0x0c,  /* 36 Trans,DTMF+TONE            */
13409   0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13410   0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13411 };
13412
13413
13414 static word get_b1_facilities (PLCI   * plci, byte b1_resource)
13415 {
13416   word b1_facilities;
13417
13418   b1_facilities = b1_facilities_table[b1_resource];
13419   if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13420   {
13421
13422     if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13423        || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13424
13425     {
13426       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13427         b1_facilities |= B1_FACILITY_DTMFX;
13428       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13429         b1_facilities |= B1_FACILITY_DTMFR;
13430     }
13431   }
13432   if ((b1_resource == 17) || (b1_resource == 18))
13433   {
13434     if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13435       b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13436   }
13437 /*
13438   dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13439     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13440     (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13441 */
13442   return (b1_facilities);
13443 }
13444
13445
13446 static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities)
13447 {
13448   byte b;
13449
13450   switch (b1_resource)
13451   {
13452   case 5:
13453   case 26:
13454     if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13455       b = 26;
13456     else
13457       b = 5;
13458     break;
13459
13460   case 8:
13461   case 27:
13462     if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13463       b = 27;
13464     else
13465       b = 8;
13466     break;
13467
13468   case 9:
13469   case 20:
13470   case 22:
13471   case 23:
13472   case 24:
13473   case 25:
13474   case 28:
13475   case 29:
13476   case 30:
13477   case 36:
13478   case 37:
13479   case 38:
13480     if (b1_facilities & B1_FACILITY_EC)
13481     {
13482       if (b1_facilities & B1_FACILITY_LOCAL)
13483         b = 30;
13484       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13485         b = 29;
13486       else
13487         b = 28;
13488     }
13489
13490     else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13491       && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13492        || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13493     {
13494       if (b1_facilities & B1_FACILITY_LOCAL)
13495         b = 38;
13496       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13497         b = 37;
13498       else
13499         b = 36;
13500     }
13501
13502     else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13503       && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13504      || ((b1_facilities & B1_FACILITY_DTMFR)
13505       && ((b1_facilities & B1_FACILITY_MIXER)
13506        || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13507      || ((b1_facilities & B1_FACILITY_DTMFX)
13508       && ((b1_facilities & B1_FACILITY_MIXER)
13509        || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13510     {
13511       if (b1_facilities & B1_FACILITY_LOCAL)
13512         b = 24;
13513       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13514         b = 23;
13515       else
13516         b = 22;
13517     }
13518     else
13519     {
13520       if (b1_facilities & B1_FACILITY_LOCAL)
13521         b = 25;
13522       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13523         b = 20;
13524       else
13525         b = 9;
13526     }
13527     break;
13528
13529   case 31:
13530   case 32:
13531   case 33:
13532     if (b1_facilities & B1_FACILITY_LOCAL)
13533       b = 33;
13534     else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13535       b = 32;
13536     else
13537       b = 31;
13538     break;
13539
13540   default:
13541     b = b1_resource;
13542   }
13543   dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13544     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13545     (char   *)(FILE_), __LINE__,
13546     b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13547   return (b);
13548 }
13549
13550
13551 static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities)
13552 {
13553   word removed_facilities;
13554
13555   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13556     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13557     (char   *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13558     new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13559
13560   new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13561   removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13562
13563   if (removed_facilities & B1_FACILITY_EC)
13564     ec_clear_config (plci);
13565
13566
13567   if (removed_facilities & B1_FACILITY_DTMFR)
13568   {
13569     dtmf_rec_clear_config (plci);
13570     dtmf_parameter_clear_config (plci);
13571   }
13572   if (removed_facilities & B1_FACILITY_DTMFX)
13573     dtmf_send_clear_config (plci);
13574
13575
13576   if (removed_facilities & B1_FACILITY_MIXER)
13577     mixer_clear_config (plci);
13578
13579   if (removed_facilities & B1_FACILITY_VOICE)
13580     adv_voice_clear_config (plci);
13581   plci->B1_facilities = new_b1_facilities;
13582 }
13583
13584
13585 static void adjust_b_clear (PLCI   *plci)
13586 {
13587
13588   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13589     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13590     (char   *)(FILE_), __LINE__));
13591
13592   plci->adjust_b_restore = false;
13593 }
13594
13595
13596 static word adjust_b_process (dword Id, PLCI   *plci, byte Rc)
13597 {
13598   word Info;
13599   byte b1_resource;
13600   NCCI   * ncci_ptr;
13601     API_PARSE bp[2];
13602
13603   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13604     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13605
13606   Info = GOOD;
13607   switch (plci->adjust_b_state)
13608   {
13609   case ADJUST_B_START:
13610     if ((plci->adjust_b_parms_msg == NULL)
13611      && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13612      && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13613       ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13614     {
13615       b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13616         0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13617       if (b1_resource == plci->B1_resource)
13618       {
13619         adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13620         break;
13621       }
13622       if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13623       {
13624         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13625           UnMapId (Id), (char   *)(FILE_), __LINE__,
13626           plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13627         Info = _WRONG_STATE;
13628         break;
13629       }
13630     }
13631     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13632     {
13633
13634       mixer_prepare_switch (Id, plci);
13635
13636
13637       dtmf_prepare_switch (Id, plci);
13638       dtmf_parameter_prepare_switch (Id, plci);
13639
13640
13641       ec_prepare_switch (Id, plci);
13642
13643       adv_voice_prepare_switch (Id, plci);
13644     }
13645     plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13646     Rc = OK;
13647   case ADJUST_B_SAVE_MIXER_1:
13648     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13649     {
13650
13651       Info = mixer_save_config (Id, plci, Rc);
13652       if ((Info != GOOD) || plci->internal_command)
13653         break;
13654
13655     }
13656     plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13657     Rc = OK;
13658   case ADJUST_B_SAVE_DTMF_1:
13659     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13660     {
13661
13662       Info = dtmf_save_config (Id, plci, Rc);
13663       if ((Info != GOOD) || plci->internal_command)
13664         break;
13665
13666     }
13667     plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13668   case ADJUST_B_REMOVE_L23_1:
13669     if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13670      && plci->NL.Id && !plci->nl_remove_id)
13671     {
13672       plci->internal_command = plci->adjust_b_command;
13673       if (plci->adjust_b_ncci != 0)
13674       {
13675         ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13676         while (ncci_ptr->data_pending)
13677         {
13678           plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13679           data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13680         }
13681         while (ncci_ptr->data_ack_pending)
13682           data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13683       }
13684       nl_req_ncci (plci, REMOVE,
13685         (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13686       send_req (plci);
13687       plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13688       break;
13689     }
13690     plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13691     Rc = OK;
13692   case ADJUST_B_REMOVE_L23_2:
13693     if ((Rc != OK) && (Rc != OK_FC))
13694     {
13695       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13696         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13697       Info = _WRONG_STATE;
13698       break;
13699     }
13700     if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13701     {
13702       if (plci_nl_busy (plci))
13703       {
13704         plci->internal_command = plci->adjust_b_command;
13705         break;
13706       }
13707     }
13708     plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13709     Rc = OK;
13710   case ADJUST_B_SAVE_EC_1:
13711     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13712     {
13713
13714       Info = ec_save_config (Id, plci, Rc);
13715       if ((Info != GOOD) || plci->internal_command)
13716         break;
13717
13718     }
13719     plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13720     Rc = OK;
13721   case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13722     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13723     {
13724
13725       Info = dtmf_parameter_save_config (Id, plci, Rc);
13726       if ((Info != GOOD) || plci->internal_command)
13727         break;
13728
13729     }
13730     plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13731     Rc = OK;
13732   case ADJUST_B_SAVE_VOICE_1:
13733     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13734     {
13735       Info = adv_voice_save_config (Id, plci, Rc);
13736       if ((Info != GOOD) || plci->internal_command)
13737         break;
13738     }
13739     plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13740   case ADJUST_B_SWITCH_L1_1:
13741     if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13742     {
13743       if (plci->sig_req)
13744       {
13745         plci->internal_command = plci->adjust_b_command;
13746         break;
13747       }
13748       if (plci->adjust_b_parms_msg != NULL)
13749         api_load_msg (plci->adjust_b_parms_msg, bp);
13750       else
13751         api_load_msg (&plci->B_protocol, bp);
13752       Info = add_b1 (plci, bp,
13753         (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13754         plci->adjust_b_facilities);
13755       if (Info != GOOD)
13756       {
13757         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13758           UnMapId (Id), (char   *)(FILE_), __LINE__,
13759           plci->B1_resource, plci->adjust_b_facilities));
13760         break;
13761       }
13762       plci->internal_command = plci->adjust_b_command;
13763       sig_req (plci, RESOURCES, 0);
13764       send_req (plci);
13765       plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13766       break;
13767     }
13768     plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13769     Rc = OK;
13770   case ADJUST_B_SWITCH_L1_2:
13771     if ((Rc != OK) && (Rc != OK_FC))
13772     {
13773       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13774         UnMapId (Id), (char   *)(FILE_), __LINE__,
13775         Rc, plci->B1_resource, plci->adjust_b_facilities));
13776       Info = _WRONG_STATE;
13777       break;
13778     }
13779     plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13780     Rc = OK;
13781   case ADJUST_B_RESTORE_VOICE_1:
13782   case ADJUST_B_RESTORE_VOICE_2:
13783     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13784     {
13785       Info = adv_voice_restore_config (Id, plci, Rc);
13786       if ((Info != GOOD) || plci->internal_command)
13787         break;
13788     }
13789     plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13790     Rc = OK;
13791   case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13792   case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13793     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13794     {
13795
13796       Info = dtmf_parameter_restore_config (Id, plci, Rc);
13797       if ((Info != GOOD) || plci->internal_command)
13798         break;
13799
13800     }
13801     plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13802     Rc = OK;
13803   case ADJUST_B_RESTORE_EC_1:
13804   case ADJUST_B_RESTORE_EC_2:
13805     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13806     {
13807
13808       Info = ec_restore_config (Id, plci, Rc);
13809       if ((Info != GOOD) || plci->internal_command)
13810         break;
13811
13812     }
13813     plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13814   case ADJUST_B_ASSIGN_L23_1:
13815     if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13816     {
13817       if (plci_nl_busy (plci))
13818       {
13819         plci->internal_command = plci->adjust_b_command;
13820         break;
13821       }
13822       if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13823         plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13824       if (plci->adjust_b_parms_msg != NULL)
13825         api_load_msg (plci->adjust_b_parms_msg, bp);
13826       else
13827         api_load_msg (&plci->B_protocol, bp);
13828       Info = add_b23 (plci, bp);
13829       if (Info != GOOD)
13830       {
13831         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13832           UnMapId (Id), (char   *)(FILE_), __LINE__, Info));
13833         break;
13834       }
13835       plci->internal_command = plci->adjust_b_command;
13836       nl_req_ncci (plci, ASSIGN, 0);
13837       send_req (plci);
13838       plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13839       break;
13840     }
13841     plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13842     Rc = ASSIGN_OK;
13843   case ADJUST_B_ASSIGN_L23_2:
13844     if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13845     {
13846       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13847         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13848       Info = _WRONG_STATE;
13849       break;
13850     }
13851     if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13852     {
13853       if (Rc != ASSIGN_OK)
13854       {
13855         plci->internal_command = plci->adjust_b_command;
13856         break;
13857       }
13858     }
13859     if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13860     {
13861       plci->adjust_b_restore = true;
13862       break;
13863     }
13864     plci->adjust_b_state = ADJUST_B_CONNECT_1;
13865   case ADJUST_B_CONNECT_1:
13866     if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13867     {
13868       plci->internal_command = plci->adjust_b_command;
13869       if (plci_nl_busy (plci))
13870         break;
13871       nl_req_ncci (plci, N_CONNECT, 0);
13872       send_req (plci);
13873       plci->adjust_b_state = ADJUST_B_CONNECT_2;
13874       break;
13875     }
13876     plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13877     Rc = OK;
13878   case ADJUST_B_CONNECT_2:
13879   case ADJUST_B_CONNECT_3:
13880   case ADJUST_B_CONNECT_4:
13881     if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13882     {
13883       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13884         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13885       Info = _WRONG_STATE;
13886       break;
13887     }
13888     if (Rc == OK)
13889     {
13890       if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13891       {
13892         get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13893         Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13894       }
13895       if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13896         plci->adjust_b_state = ADJUST_B_CONNECT_3;
13897       else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13898         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13899     }
13900     else if (Rc == 0)
13901     {
13902       if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13903         plci->adjust_b_state = ADJUST_B_CONNECT_4;
13904       else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13905         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13906     }
13907     if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13908     {
13909       plci->internal_command = plci->adjust_b_command;
13910       break;
13911     }
13912     Rc = OK;
13913   case ADJUST_B_RESTORE_DTMF_1:
13914   case ADJUST_B_RESTORE_DTMF_2:
13915     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13916     {
13917
13918       Info = dtmf_restore_config (Id, plci, Rc);
13919       if ((Info != GOOD) || plci->internal_command)
13920         break;
13921
13922     }
13923     plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13924     Rc = OK;
13925   case ADJUST_B_RESTORE_MIXER_1:
13926   case ADJUST_B_RESTORE_MIXER_2:
13927   case ADJUST_B_RESTORE_MIXER_3:
13928   case ADJUST_B_RESTORE_MIXER_4:
13929   case ADJUST_B_RESTORE_MIXER_5:
13930   case ADJUST_B_RESTORE_MIXER_6:
13931   case ADJUST_B_RESTORE_MIXER_7:
13932     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13933     {
13934
13935       Info = mixer_restore_config (Id, plci, Rc);
13936       if ((Info != GOOD) || plci->internal_command)
13937         break;
13938
13939     }
13940     plci->adjust_b_state = ADJUST_B_END;
13941   case ADJUST_B_END:
13942     break;
13943   }
13944   return (Info);
13945 }
13946
13947
13948 static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13949 {
13950
13951   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13952     UnMapId (Id), (char   *)(FILE_), __LINE__,
13953     plci->B1_resource, b1_facilities));
13954
13955   plci->adjust_b_parms_msg = bp_msg;
13956   plci->adjust_b_facilities = b1_facilities;
13957   plci->adjust_b_command = internal_command;
13958   plci->adjust_b_ncci = (word)(Id >> 16);
13959   if ((bp_msg == NULL) && (plci->B1_resource == 0))
13960     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13961   else
13962     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13963   plci->adjust_b_state = ADJUST_B_START;
13964   dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13965     UnMapId (Id), (char   *)(FILE_), __LINE__,
13966     plci->B1_resource, b1_facilities));
13967 }
13968
13969
13970 static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc)
13971 {
13972   word internal_command;
13973
13974   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13975     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
13976
13977   internal_command = plci->internal_command;
13978   plci->internal_command = 0;
13979   switch (internal_command)
13980   {
13981   default:
13982     plci->command = 0;
13983     if (plci->req_in != 0)
13984     {
13985       plci->internal_command = ADJUST_B_RESTORE_1;
13986       break;
13987     }
13988     Rc = OK;
13989   case ADJUST_B_RESTORE_1:
13990     if ((Rc != OK) && (Rc != OK_FC))
13991     {
13992       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13993         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13994     }
13995     plci->adjust_b_parms_msg = NULL;
13996     plci->adjust_b_facilities = plci->B1_facilities;
13997     plci->adjust_b_command = ADJUST_B_RESTORE_2;
13998     plci->adjust_b_ncci = (word)(Id >> 16);
13999     plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
14000     plci->adjust_b_state = ADJUST_B_START;
14001     dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
14002       UnMapId (Id), (char   *)(FILE_), __LINE__));
14003   case ADJUST_B_RESTORE_2:
14004     if (adjust_b_process (Id, plci, Rc) != GOOD)
14005     {
14006       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
14007         UnMapId (Id), (char   *)(FILE_), __LINE__));
14008     }
14009     if (plci->internal_command)
14010       break;
14011     break;
14012   }
14013 }
14014
14015
14016 static void reset_b3_command (dword Id, PLCI   *plci, byte Rc)
14017 {
14018   word Info;
14019   word internal_command;
14020
14021   dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
14022     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14023
14024   Info = GOOD;
14025   internal_command = plci->internal_command;
14026   plci->internal_command = 0;
14027   switch (internal_command)
14028   {
14029   default:
14030     plci->command = 0;
14031     plci->adjust_b_parms_msg = NULL;
14032     plci->adjust_b_facilities = plci->B1_facilities;
14033     plci->adjust_b_command = RESET_B3_COMMAND_1;
14034     plci->adjust_b_ncci = (word)(Id >> 16);
14035     plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14036     plci->adjust_b_state = ADJUST_B_START;
14037     dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14038       UnMapId (Id), (char   *)(FILE_), __LINE__));
14039   case RESET_B3_COMMAND_1:
14040     Info = adjust_b_process (Id, plci, Rc);
14041     if (Info != GOOD)
14042     {
14043       dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14044         UnMapId (Id), (char   *)(FILE_), __LINE__));
14045       break;
14046     }
14047     if (plci->internal_command)
14048       return;
14049     break;
14050   }
14051 /*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14052   sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14053 }
14054
14055
14056 static void select_b_command (dword Id, PLCI   *plci, byte Rc)
14057 {
14058   word Info;
14059   word internal_command;
14060   byte esc_chi[3];
14061
14062   dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14063     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14064
14065   Info = GOOD;
14066   internal_command = plci->internal_command;
14067   plci->internal_command = 0;
14068   switch (internal_command)
14069   {
14070   default:
14071     plci->command = 0;
14072     plci->adjust_b_parms_msg = &plci->saved_msg;
14073     if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14074       plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14075     else
14076       plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14077     plci->adjust_b_command = SELECT_B_COMMAND_1;
14078     plci->adjust_b_ncci = (word)(Id >> 16);
14079     if (plci->saved_msg.parms[0].length == 0)
14080     {
14081       plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14082         ADJUST_B_MODE_NO_RESOURCE;
14083     }
14084     else
14085     {
14086       plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14087         ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14088     }
14089     plci->adjust_b_state = ADJUST_B_START;
14090     dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14091       UnMapId (Id), (char   *)(FILE_), __LINE__));
14092   case SELECT_B_COMMAND_1:
14093     Info = adjust_b_process (Id, plci, Rc);
14094     if (Info != GOOD)
14095     {
14096       dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14097         UnMapId (Id), (char   *)(FILE_), __LINE__));
14098       break;
14099     }
14100     if (plci->internal_command)
14101       return;
14102     if (plci->tel == ADV_VOICE)
14103     {
14104       esc_chi[0] = 0x02;
14105       esc_chi[1] = 0x18;
14106       esc_chi[2] = plci->b_channel;
14107       SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14108     }
14109     break;
14110   }
14111   sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14112 }
14113
14114
14115 static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc)
14116 {
14117   word Info;
14118   word internal_command;
14119
14120   dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14121     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14122
14123   Info = GOOD;
14124   internal_command = plci->internal_command;
14125   plci->internal_command = 0;
14126   switch (internal_command)
14127   {
14128   default:
14129     plci->command = 0;
14130   case FAX_CONNECT_ACK_COMMAND_1:
14131     if (plci_nl_busy (plci))
14132     {
14133       plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14134       return;
14135     }
14136     plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14137     plci->NData[0].P = plci->fax_connect_info_buffer;
14138     plci->NData[0].PLength = plci->fax_connect_info_length;
14139     plci->NL.X = plci->NData;
14140     plci->NL.ReqCh = 0;
14141     plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14142     plci->adapter->request (&plci->NL);
14143     return;
14144   case FAX_CONNECT_ACK_COMMAND_2:
14145     if ((Rc != OK) && (Rc != OK_FC))
14146     {
14147       dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14148         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14149       break;
14150     }
14151   }
14152   if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14153    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14154   {
14155     if (plci->B3_prot == 4)
14156       sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14157     else
14158       sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14159     plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14160   }
14161 }
14162
14163
14164 static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc)
14165 {
14166   word Info;
14167   word internal_command;
14168
14169   dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14170     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14171
14172   Info = GOOD;
14173   internal_command = plci->internal_command;
14174   plci->internal_command = 0;
14175   switch (internal_command)
14176   {
14177   default:
14178     plci->command = 0;
14179   case FAX_EDATA_ACK_COMMAND_1:
14180     if (plci_nl_busy (plci))
14181     {
14182       plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14183       return;
14184     }
14185     plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14186     plci->NData[0].P = plci->fax_connect_info_buffer;
14187     plci->NData[0].PLength = plci->fax_edata_ack_length;
14188     plci->NL.X = plci->NData;
14189     plci->NL.ReqCh = 0;
14190     plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14191     plci->adapter->request (&plci->NL);
14192     return;
14193   case FAX_EDATA_ACK_COMMAND_2:
14194     if ((Rc != OK) && (Rc != OK_FC))
14195     {
14196       dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14197         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14198       break;
14199     }
14200   }
14201 }
14202
14203
14204 static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc)
14205 {
14206   word Info;
14207   word internal_command;
14208
14209   dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14210     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14211
14212   Info = GOOD;
14213   internal_command = plci->internal_command;
14214   plci->internal_command = 0;
14215   switch (internal_command)
14216   {
14217   default:
14218     plci->command = 0;
14219   case FAX_CONNECT_INFO_COMMAND_1:
14220     if (plci_nl_busy (plci))
14221     {
14222       plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14223       return;
14224     }
14225     plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14226     plci->NData[0].P = plci->fax_connect_info_buffer;
14227     plci->NData[0].PLength = plci->fax_connect_info_length;
14228     plci->NL.X = plci->NData;
14229     plci->NL.ReqCh = 0;
14230     plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14231     plci->adapter->request (&plci->NL);
14232     return;
14233   case FAX_CONNECT_INFO_COMMAND_2:
14234     if ((Rc != OK) && (Rc != OK_FC))
14235     {
14236       dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14237         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14238       Info = _WRONG_STATE;
14239       break;
14240     }
14241     if (plci_nl_busy (plci))
14242     {
14243       plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14244       return;
14245     }
14246     plci->command = _CONNECT_B3_R;
14247     nl_req_ncci (plci, N_CONNECT, 0);
14248     send_req (plci);
14249     return;
14250   }
14251   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14252 }
14253
14254
14255 static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc)
14256 {
14257   word Info;
14258   word internal_command;
14259
14260   dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14261     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14262
14263   Info = GOOD;
14264   internal_command = plci->internal_command;
14265   plci->internal_command = 0;
14266   switch (internal_command)
14267   {
14268   default:
14269     plci->command = 0;
14270     plci->adjust_b_parms_msg = NULL;
14271     plci->adjust_b_facilities = plci->B1_facilities;
14272     plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14273     plci->adjust_b_ncci = (word)(Id >> 16);
14274     plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14275     plci->adjust_b_state = ADJUST_B_START;
14276     dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14277       UnMapId (Id), (char   *)(FILE_), __LINE__));
14278   case FAX_ADJUST_B23_COMMAND_1:
14279     Info = adjust_b_process (Id, plci, Rc);
14280     if (Info != GOOD)
14281     {
14282       dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14283         UnMapId (Id), (char   *)(FILE_), __LINE__));
14284       break;
14285     }
14286     if (plci->internal_command)
14287       return;
14288   case FAX_ADJUST_B23_COMMAND_2:
14289     if (plci_nl_busy (plci))
14290     {
14291       plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14292       return;
14293     }
14294     plci->command = _CONNECT_B3_R;
14295     nl_req_ncci (plci, N_CONNECT, 0);
14296     send_req (plci);
14297     return;
14298   }
14299   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14300 }
14301
14302
14303 static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc)
14304 {
14305   word internal_command;
14306
14307   dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14308     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14309
14310   internal_command = plci->internal_command;
14311   plci->internal_command = 0;
14312   switch (internal_command)
14313   {
14314   default:
14315     plci->command = 0;
14316     plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14317     return;
14318   case FAX_DISCONNECT_COMMAND_1:
14319   case FAX_DISCONNECT_COMMAND_2:
14320   case FAX_DISCONNECT_COMMAND_3:
14321     if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14322     {
14323       dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14324         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14325       break;
14326     }
14327     if (Rc == OK)
14328     {
14329       if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14330        || (internal_command == FAX_DISCONNECT_COMMAND_2))
14331       {
14332         plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14333       }
14334     }
14335     else if (Rc == 0)
14336     {
14337       if (internal_command == FAX_DISCONNECT_COMMAND_1)
14338         plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14339     }
14340     return;
14341   }
14342 }
14343
14344
14345
14346 static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc)
14347 {
14348   word Info;
14349   word internal_command;
14350
14351   dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14352     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14353
14354   Info = GOOD;
14355   internal_command = plci->internal_command;
14356   plci->internal_command = 0;
14357   switch (internal_command)
14358   {
14359   default:
14360     plci->command = 0;
14361   case RTP_CONNECT_B3_REQ_COMMAND_1:
14362     if (plci_nl_busy (plci))
14363     {
14364       plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14365       return;
14366     }
14367     plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14368     nl_req_ncci (plci, N_CONNECT, 0);
14369     send_req (plci);
14370     return;
14371   case RTP_CONNECT_B3_REQ_COMMAND_2:
14372     if ((Rc != OK) && (Rc != OK_FC))
14373     {
14374       dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14375         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14376       Info = _WRONG_STATE;
14377       break;
14378     }
14379     if (plci_nl_busy (plci))
14380     {
14381       plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14382       return;
14383     }
14384     plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14385     plci->NData[0].PLength = plci->internal_req_buffer[0];
14386     plci->NData[0].P = plci->internal_req_buffer + 1;
14387     plci->NL.X = plci->NData;
14388     plci->NL.ReqCh = 0;
14389     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14390     plci->adapter->request (&plci->NL);
14391     break;
14392   case RTP_CONNECT_B3_REQ_COMMAND_3:
14393     return;
14394   }
14395   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14396 }
14397
14398
14399 static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc)
14400 {
14401   word Info;
14402   word internal_command;
14403
14404   dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14405     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14406
14407   Info = GOOD;
14408   internal_command = plci->internal_command;
14409   plci->internal_command = 0;
14410   switch (internal_command)
14411   {
14412   default:
14413     plci->command = 0;
14414   case RTP_CONNECT_B3_RES_COMMAND_1:
14415     if (plci_nl_busy (plci))
14416     {
14417       plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14418       return;
14419     }
14420     plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14421     nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14422     send_req (plci);
14423     return;
14424   case RTP_CONNECT_B3_RES_COMMAND_2:
14425     if ((Rc != OK) && (Rc != OK_FC))
14426     {
14427       dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14428         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14429       Info = _WRONG_STATE;
14430       break;
14431     }
14432     if (plci_nl_busy (plci))
14433     {
14434       plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14435       return;
14436     }
14437     sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14438     plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14439     plci->NData[0].PLength = plci->internal_req_buffer[0];
14440     plci->NData[0].P = plci->internal_req_buffer + 1;
14441     plci->NL.X = plci->NData;
14442     plci->NL.ReqCh = 0;
14443     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14444     plci->adapter->request (&plci->NL);
14445     return;
14446   case RTP_CONNECT_B3_RES_COMMAND_3:
14447     return;
14448   }
14449 }
14450
14451
14452
14453 static void hold_save_command (dword Id, PLCI   *plci, byte Rc)
14454 {
14455     byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14456   word Info;
14457   word internal_command;
14458
14459   dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14460     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14461
14462   Info = GOOD;
14463   internal_command = plci->internal_command;
14464   plci->internal_command = 0;
14465   switch (internal_command)
14466   {
14467   default:
14468     if (!plci->NL.Id)
14469       break;
14470     plci->command = 0;
14471     plci->adjust_b_parms_msg = NULL;
14472     plci->adjust_b_facilities = plci->B1_facilities;
14473     plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14474     plci->adjust_b_ncci = (word)(Id >> 16);
14475     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14476     plci->adjust_b_state = ADJUST_B_START;
14477     dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14478       UnMapId (Id), (char   *)(FILE_), __LINE__));
14479   case HOLD_SAVE_COMMAND_1:
14480     Info = adjust_b_process (Id, plci, Rc);
14481     if (Info != GOOD)
14482     {
14483       dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14484         UnMapId (Id), (char   *)(FILE_), __LINE__));
14485       break;
14486     }
14487     if (plci->internal_command)
14488       return;
14489   }
14490   sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14491 }
14492
14493
14494 static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc)
14495 {
14496     byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14497   word Info;
14498   word internal_command;
14499
14500   dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14501     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14502
14503   Info = GOOD;
14504   internal_command = plci->internal_command;
14505   plci->internal_command = 0;
14506   switch (internal_command)
14507   {
14508   default:
14509     plci->command = 0;
14510     plci->adjust_b_parms_msg = NULL;
14511     plci->adjust_b_facilities = plci->B1_facilities;
14512     plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14513     plci->adjust_b_ncci = (word)(Id >> 16);
14514     plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14515     plci->adjust_b_state = ADJUST_B_START;
14516     dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14517       UnMapId (Id), (char   *)(FILE_), __LINE__));
14518   case RETRIEVE_RESTORE_COMMAND_1:
14519     Info = adjust_b_process (Id, plci, Rc);
14520     if (Info != GOOD)
14521     {
14522       dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14523         UnMapId (Id), (char   *)(FILE_), __LINE__));
14524       break;
14525     }
14526     if (plci->internal_command)
14527       return;
14528   }
14529   sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14530 }
14531
14532
14533 static void init_b1_config (PLCI   *plci)
14534 {
14535
14536   dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14537     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14538     (char   *)(FILE_), __LINE__));
14539
14540   plci->B1_resource = 0;
14541   plci->B1_facilities = 0;
14542
14543   plci->li_bchannel_id = 0;
14544   mixer_clear_config (plci);
14545
14546
14547   ec_clear_config (plci);
14548
14549
14550   dtmf_rec_clear_config (plci);
14551   dtmf_send_clear_config (plci);
14552   dtmf_parameter_clear_config (plci);
14553
14554   adv_voice_clear_config (plci);
14555   adjust_b_clear (plci);
14556 }
14557
14558
14559 static void clear_b1_config (PLCI   *plci)
14560 {
14561
14562   dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14563     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14564     (char   *)(FILE_), __LINE__));
14565
14566   adv_voice_clear_config (plci);
14567   adjust_b_clear (plci);
14568
14569   ec_clear_config (plci);
14570
14571
14572   dtmf_rec_clear_config (plci);
14573   dtmf_send_clear_config (plci);
14574   dtmf_parameter_clear_config (plci);
14575
14576
14577   if ((plci->li_bchannel_id != 0)
14578    && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14579   {
14580     mixer_clear_config (plci);
14581     li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14582     plci->li_bchannel_id = 0;
14583   }
14584
14585   plci->B1_resource = 0;
14586   plci->B1_facilities = 0;
14587 }
14588
14589
14590 /* -----------------------------------------------------------------
14591                 XON protocol local helpers
14592    ----------------------------------------------------------------- */
14593 static void channel_flow_control_remove (PLCI   * plci) {
14594   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14595   word i;
14596   for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14597     if (a->ch_flow_plci[i] == plci->Id) {
14598       a->ch_flow_plci[i] = 0;
14599       a->ch_flow_control[i] = 0;
14600     }
14601   }
14602 }
14603
14604 static void channel_x_on (PLCI   * plci, byte ch) {
14605   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14606   if (a->ch_flow_control[ch] & N_XON_SENT) {
14607     a->ch_flow_control[ch] &= ~N_XON_SENT;
14608   }
14609 }
14610
14611 static void channel_x_off (PLCI   * plci, byte ch, byte flag) {
14612   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14613   if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14614     a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14615     a->ch_flow_plci[ch] = plci->Id;
14616     a->ch_flow_control_pending++;
14617   }
14618 }
14619
14620 static void channel_request_xon (PLCI   * plci, byte ch) {
14621   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14622
14623   if (a->ch_flow_control[ch] & N_CH_XOFF) {
14624     a->ch_flow_control[ch] |= N_XON_REQ;
14625     a->ch_flow_control[ch] &= ~N_CH_XOFF;
14626     a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14627   }
14628 }
14629
14630 static void channel_xmit_extended_xon (PLCI   * plci) {
14631   DIVA_CAPI_ADAPTER   * a;
14632   int max_ch = ARRAY_SIZE(a->ch_flow_control);
14633   int i, one_requested = 0;
14634
14635   if ((!plci) || (!plci->Id) || ((a = plci->adapter) == NULL)) {
14636     return;
14637   }
14638
14639   for (i = 0; i < max_ch; i++) {
14640     if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14641         (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14642         (plci->Id == a->ch_flow_plci[i])) {
14643       channel_request_xon (plci, (byte)i);
14644       one_requested = 1;
14645     }
14646   }
14647
14648   if (one_requested) {
14649     channel_xmit_xon (plci);
14650   }
14651 }
14652
14653 /*
14654   Try to xmit next X_ON
14655   */
14656 static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER   * a, PLCI   * plci) {
14657   int max_ch = ARRAY_SIZE(a->ch_flow_control);
14658   int i;
14659
14660   if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14661     return (0);
14662   }
14663
14664   if (a->last_flow_control_ch >= max_ch) {
14665     a->last_flow_control_ch = 1;
14666   }
14667   for (i=a->last_flow_control_ch; i < max_ch; i++) {
14668     if ((a->ch_flow_control[i] & N_XON_REQ) &&
14669         (plci->Id == a->ch_flow_plci[i])) {
14670       a->last_flow_control_ch = i+1;
14671       return (i);
14672     }
14673   }
14674
14675   for (i = 1; i < a->last_flow_control_ch; i++) {
14676     if ((a->ch_flow_control[i] & N_XON_REQ) &&
14677         (plci->Id == a->ch_flow_plci[i])) {
14678       a->last_flow_control_ch = i+1;
14679       return (i);
14680     }
14681   }
14682
14683   return (0);
14684 }
14685
14686 static void channel_xmit_xon (PLCI   * plci) {
14687   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14688   byte ch;
14689
14690   if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14691     return;
14692   }
14693   if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14694     return;
14695   }
14696   a->ch_flow_control[ch] &= ~N_XON_REQ;
14697   a->ch_flow_control[ch] |= N_XON_SENT;
14698
14699   plci->NL.Req = plci->nl_req = (byte)N_XON;
14700   plci->NL.ReqCh         = ch;
14701   plci->NL.X             = plci->NData;
14702   plci->NL.XNum          = 1;
14703   plci->NData[0].P       = &plci->RBuffer[0];
14704   plci->NData[0].PLength = 0;
14705
14706   plci->adapter->request(&plci->NL);
14707 }
14708
14709 static int channel_can_xon (PLCI   * plci, byte ch) {
14710   APPL   * APPLptr;
14711   DIVA_CAPI_ADAPTER   * a;
14712   word NCCIcode;
14713   dword count;
14714   word Num;
14715   word i;
14716
14717   APPLptr = plci->appl;
14718   a = plci->adapter;
14719
14720   if (!APPLptr)
14721     return (0);
14722
14723   NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14724
14725                 /* count all buffers within the Application pool    */
14726                 /* belonging to the same NCCI. XON if a first is    */
14727                 /* used.                                            */
14728   count = 0;
14729   Num = 0xffff;
14730   for(i=0; i<APPLptr->MaxBuffer; i++) {
14731     if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14732     if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14733   }
14734   if ((count > 2) || (Num == 0xffff)) {
14735     return (0);
14736   }
14737   return (1);
14738 }
14739
14740
14741 /*------------------------------------------------------------------*/
14742
14743 static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   * a,word offset)
14744 {
14745   return 1;
14746 }
14747
14748
14749
14750 /**********************************************************************************/
14751 /* function groups the listening applications according to the CIP mask and the   */
14752 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14753 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14754 /* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14755 /* function must be enabled by setting "a->group_optimization_enabled" from the   */
14756 /* OS specific part (per adapter).                                                */
14757 /**********************************************************************************/
14758 static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci)
14759 {
14760   word i,j,k,busy,group_found;
14761   dword info_mask_group[MAX_CIP_TYPES];
14762   dword cip_mask_group[MAX_CIP_TYPES];
14763   word appl_number_group_type[MAX_APPL];
14764   PLCI   *auxplci;
14765
14766   set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14767
14768   if(!a->group_optimization_enabled)
14769   {
14770     dbug(1,dprintf("No group optimization"));
14771     return;
14772   }
14773
14774   dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14775
14776   for(i=0;i<MAX_CIP_TYPES;i++)
14777   {
14778     info_mask_group[i] = 0;
14779     cip_mask_group [i] = 0;
14780   }
14781   for(i=0;i<MAX_APPL;i++)
14782   {
14783     appl_number_group_type[i] = 0;
14784   }
14785   for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14786   {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14787     if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i])  && (a->group_optimization_enabled ==1) )
14788     {
14789       dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14790       return; /* allow good application unfiltered access */
14791     }
14792   }
14793   for(i=0; i<max_appl; i++) /* Build CIP Groups */
14794   {
14795     if(application[i].Id && a->CIP_Mask[i] )
14796     {
14797       for(k=0,busy=false; k<a->max_plci; k++)
14798       {
14799         if(a->plci[k].Id) 
14800         {
14801           auxplci = &a->plci[k];
14802           if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14803           {
14804             busy = true;
14805             dbug(1,dprintf("Appl 0x%x is busy",i+1));
14806           }
14807           else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14808           {
14809             busy = true;
14810             dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14811           }
14812         }
14813       }
14814
14815       for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++)     /* build groups with free applications only */
14816       {
14817         if(j==MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14818         {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14819           appl_number_group_type[i] = MAX_CIP_TYPES;
14820           group_found=true;
14821           dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14822         }
14823         else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )  
14824         {                                      /* is group already present ?                  */
14825           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14826           group_found=true;
14827           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]));
14828         }
14829         else if(!info_mask_group[j])
14830         {                                      /* establish a new group                       */
14831           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14832           info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14833           cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14834           group_found=true;
14835           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]));
14836         }
14837       }
14838     }
14839   }
14840         
14841   for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14842   {
14843     if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14844     {
14845       if(appl_number_group_type[i] == MAX_CIP_TYPES)
14846       {
14847         dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14848       }
14849       else
14850       {
14851         dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14852         for(j=i+1; j<max_appl; j++)   /* search other group members and mark them as busy        */
14853         {
14854           if(appl_number_group_type[i] == appl_number_group_type[j]) 
14855           {
14856             dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14857             clear_group_ind_mask_bit (plci, j);           /* disable call on other group members */
14858             appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14859           }
14860         }
14861       }
14862     }
14863     else                                                 /* application should not get a call */
14864     {
14865       clear_group_ind_mask_bit (plci, i);
14866     }
14867   }
14868
14869 }
14870
14871
14872
14873 /* OS notifies the driver about a application Capi_Register */
14874 word CapiRegister(word id)
14875 {
14876   word i,j,appls_found;
14877
14878   PLCI   *plci;
14879   DIVA_CAPI_ADAPTER   *a;
14880
14881   for(i=0,appls_found=0; i<max_appl; i++)
14882   {
14883     if( application[i].Id && (application[i].Id!=id) )
14884     {
14885       appls_found++;                       /* an application has been found */
14886     }
14887   }
14888
14889   if(appls_found) return true;
14890   for(i=0; i<max_adapter; i++)                   /* scan all adapters...    */
14891   {
14892     a = &adapter[i];
14893     if(a->request)
14894     {
14895       if(a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14896       {
14897         if(!appls_found)           /* first application does a capi register   */
14898         {
14899           if((j=get_plci(a)))                    /* activate L1 of all adapters */
14900           {
14901             plci = &a->plci[j-1];
14902             plci->command = 0;
14903             add_p(plci,OAD,"\x01\xfd");
14904             add_p(plci,CAI,"\x01\x80");
14905             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14906             add_p(plci,SHIFT|6,NULL);
14907             add_p(plci,SIN,"\x02\x00\x00");
14908             plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14909             sig_req(plci,ASSIGN,DSIG_ID);
14910             add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14911             sig_req(plci,SIG_CTRL,0);
14912             send_req(plci);
14913           }
14914         }
14915       }
14916     }
14917   }
14918   return false;
14919 }
14920
14921 /*------------------------------------------------------------------*/
14922
14923 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14924
14925 static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms)
14926 {
14927  word i;
14928  /* Format of vswitch_t:
14929  0 byte length
14930  1 byte VSWITCHIE
14931  2 byte VSWITCH_REQ/VSWITCH_IND
14932  3 byte reserved
14933  4 word VSwitchcommand
14934  6 word returnerror
14935  8... Params
14936  */
14937  if(!plci ||
14938   !plci->appl ||
14939   !plci->State ||
14940   plci->Sig.Ind==NCR_FACILITY
14941   )
14942   return;
14943  
14944  for(i=0;i<MAX_MULTI_IE;i++)
14945  {
14946         if(!parms[i][0]) continue;
14947   if(parms[i][0]<7)
14948   {
14949    parms[i][0]=0; /* kill it */
14950    continue;
14951   }
14952   dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14953   switch(parms[i][4])
14954   {
14955   case VSJOIN:
14956    if(!plci->relatedPTYPLCI ||
14957     (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14958    { /* Error */
14959     break;
14960    }
14961    /* remember all necessary informations */
14962    if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
14963    {
14964     break;
14965    }
14966    if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
14967    {   /* first indication after ECT-Request on Consultation Call */
14968     plci->vswitchstate=parms[i][9];
14969     parms[i][9]=2; /* State */
14970     /* now ask first Call to join */
14971    }
14972    else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
14973    { /* Answer of VSWITCH_REQ from first Call */
14974     plci->vswitchstate=parms[i][9];
14975     /* tell consultation call to join
14976     and the protocol capabilities of the first call */
14977    }
14978    else
14979    { /* Error */
14980     break;
14981    }    
14982    plci->vsprot=parms[i][10]; /* protocol */
14983    plci->vsprotdialect=parms[i][11]; /* protocoldialect */
14984    /* send join request to related PLCI */
14985    parms[i][1]=VSWITCHIE;
14986    parms[i][2]=VSWITCH_REQ;
14987    
14988    plci->relatedPTYPLCI->command = 0;
14989    plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14990    add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14991    sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14992    send_req(plci->relatedPTYPLCI);
14993    break;
14994   case VSTRANSPORT:
14995   default:
14996    if(plci->relatedPTYPLCI &&
14997     plci->vswitchstate==3 &&
14998     plci->relatedPTYPLCI->vswitchstate==3)
14999    {
15000     add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
15001     sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
15002     send_req(plci->relatedPTYPLCI);
15003    }
15004    break;
15005   }  
15006   parms[i][0]=0; /* kill it */
15007  }
15008 }
15009
15010
15011 /*------------------------------------------------------------------*/
15012
15013 static int diva_get_dma_descriptor (PLCI   *plci, dword   *dma_magic) {
15014   ENTITY e;
15015   IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15016
15017   if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
15018     return (-1);
15019   }
15020
15021   pReq->xdi_dma_descriptor_operation.Req = 0;
15022   pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15023
15024   pReq->xdi_dma_descriptor_operation.info.operation =     IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
15025   pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
15026   pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15027   pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15028
15029   e.user[0] = plci->adapter->Id - 1;
15030   plci->adapter->request((ENTITY*)pReq);
15031
15032   if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15033       (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15034       pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15035     *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15036     dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15037          plci->adapter->Id,
15038          pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15039          *dma_magic));
15040     return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15041   } else {
15042     dbug(1,dprintf("dma_alloc failed"));
15043     return (-1);
15044   }
15045 }
15046
15047 static void diva_free_dma_descriptor (PLCI   *plci, int nr) {
15048   ENTITY e;
15049   IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15050
15051   if (nr < 0) {
15052     return;
15053   }
15054
15055   pReq->xdi_dma_descriptor_operation.Req = 0;
15056   pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15057
15058   pReq->xdi_dma_descriptor_operation.info.operation =                                                IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15059   pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
15060   pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15061   pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15062
15063   e.user[0] = plci->adapter->Id - 1;
15064   plci->adapter->request((ENTITY*)pReq);
15065
15066   if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15067     dbug(1,dprintf("dma_free(%d)", nr));
15068   } else {
15069     dbug(1,dprintf("dma_free failed (%d)", nr));
15070   }
15071 }
15072
15073 /*------------------------------------------------------------------*/