Merge master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog
[pandora-kernel.git] / drivers / isdn / hardware / eicon / message.c
1
2 /*
3  *
4   Copyright (c) Eicon Networks, 2002.
5  *
6   This source file is supplied for the use with
7   Eicon Networks range of DIVA Server Adapters.
8  *
9   Eicon File Revision :    2.1
10  *
11   This program is free software; you can redistribute it and/or modify
12   it under the terms of the GNU General Public License as published by
13   the Free Software Foundation; either version 2, or (at your option)
14   any later version.
15  *
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19   See the GNU General Public License for more details.
20  *
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  */
26
27
28
29
30
31 #include "platform.h"
32 #include "di_defs.h"
33 #include "pc.h"
34 #include "capi20.h"
35 #include "divacapi.h"
36 #include "mdm_msg.h"
37 #include "divasync.h"
38
39
40
41 #define FILE_ "MESSAGE.C"
42 #define dprintf
43
44
45
46
47
48
49
50
51
52 /*------------------------------------------------------------------*/
53 /* This is options supported for all adapters that are server by    */
54 /* XDI driver. Allo it is not necessary to ask it from every adapter*/
55 /* and it is not necessary to save it separate for every adapter    */
56 /* Macrose defined here have only local meaning                     */
57 /*------------------------------------------------------------------*/
58 static dword diva_xdi_extended_features = 0;
59
60 #define DIVA_CAPI_USE_CMA                 0x00000001
61 #define DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR  0x00000002
62 #define DIVA_CAPI_XDI_PROVIDES_NO_CANCEL  0x00000004
63 #define DIVA_CAPI_XDI_PROVIDES_RX_DMA     0x00000008
64
65 /*
66   CAPI can request to process all return codes self only if:
67   protocol code supports this && xdi supports this
68  */
69 #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))
70
71 /*------------------------------------------------------------------*/
72 /* local function prototypes                                        */
73 /*------------------------------------------------------------------*/
74
75 static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci);
76 static void set_group_ind_mask (PLCI   *plci);
77 static void clear_group_ind_mask_bit (PLCI   *plci, word b);
78 static byte test_group_ind_mask_bit (PLCI   *plci, word b);
79 void AutomaticLaw(DIVA_CAPI_ADAPTER   *);
80 word CapiRelease(word);
81 word CapiRegister(word);
82 word api_put(APPL   *, CAPI_MSG   *);
83 static word api_parse(byte   *, word, byte *, API_PARSE *);
84 static void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out);
85 static void api_load_msg(API_SAVE   *in, API_PARSE   *out);
86
87 word api_remove_start(void);
88 void api_remove_complete(void);
89
90 static void plci_remove(PLCI   *);
91 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a);
92 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  *, IDI_SYNC_REQ  *);
93
94 void   callback(ENTITY   *);
95
96 static void control_rc(PLCI   *, byte, byte, byte, byte, byte);
97 static void data_rc(PLCI   *, byte);
98 static void data_ack(PLCI   *, byte);
99 static void sig_ind(PLCI   *);
100 static void SendInfo(PLCI   *, dword, byte   * *, byte);
101 static void SendSetupInfo(APPL   *, PLCI   *, dword, byte   * *, byte);
102 static void SendSSExtInd(APPL   *, PLCI   * plci, dword Id, byte   * * parms);
103
104 static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms);
105
106 static void nl_ind(PLCI   *);
107
108 static byte connect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
109 static byte connect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
110 static byte connect_a_res(dword,word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
111 static byte disconnect_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
112 static byte disconnect_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
113 static byte listen_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
114 static byte info_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
115 static byte info_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
116 static byte alert_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
117 static byte facility_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
118 static byte facility_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
119 static byte connect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
120 static byte connect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
121 static byte connect_b3_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
122 static byte disconnect_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
123 static byte disconnect_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
124 static byte data_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
125 static byte data_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
126 static byte reset_b3_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
127 static byte reset_b3_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
128 static byte connect_b3_t90_a_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
129 static byte select_b_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
130 static byte manufacturer_req(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
131 static byte manufacturer_res(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
132
133 static word get_plci(DIVA_CAPI_ADAPTER   *);
134 static void add_p(PLCI   *, byte, byte   *);
135 static void add_s(PLCI   * plci, byte code, API_PARSE * p);
136 static void add_ss(PLCI   * plci, byte code, API_PARSE * p);
137 static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length);
138 static void add_d(PLCI   *, word, byte   *);
139 static void add_ai(PLCI   *, API_PARSE *);
140 static word add_b1(PLCI   *, API_PARSE *, word, word);
141 static word add_b23(PLCI   *, API_PARSE *);
142 static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms);
143 static void sig_req(PLCI   *, byte, byte);
144 static void nl_req_ncci(PLCI   *, byte, byte);
145 static void send_req(PLCI   *);
146 static void send_data(PLCI   *);
147 static word plci_remove_check(PLCI   *);
148 static void listen_check(DIVA_CAPI_ADAPTER   *);
149 static byte AddInfo(byte   **, byte   **, byte   *, byte *);
150 static byte getChannel(API_PARSE *);
151 static void IndParse(PLCI   *, word *, byte   **, byte);
152 static byte ie_compare(byte   *, byte *);
153 static word find_cip(DIVA_CAPI_ADAPTER   *, byte   *, byte   *);
154 static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   *,word);
155
156 /*
157   XON protocol helpers
158   */
159 static void channel_flow_control_remove (PLCI   * plci);
160 static void channel_x_off (PLCI   * plci, byte ch, byte flag);
161 static void channel_x_on (PLCI   * plci, byte ch);
162 static void channel_request_xon (PLCI   * plci, byte ch);
163 static void channel_xmit_xon (PLCI   * plci);
164 static int channel_can_xon (PLCI   * plci, byte ch);
165 static void channel_xmit_extended_xon (PLCI   * plci);
166
167 static byte SendMultiIE(PLCI   * plci, dword Id, byte   * * parms, byte ie_type, dword info_mask, byte setupParse);
168 static word AdvCodecSupport(DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, byte);
169 static void CodecIdCheck(DIVA_CAPI_ADAPTER   *, PLCI   *);
170 static void SetVoiceChannel(PLCI   *, byte   *, DIVA_CAPI_ADAPTER   * );
171 static void VoiceChannelOff(PLCI   *plci);
172 static void adv_voice_write_coefs (PLCI   *plci, word write_command);
173 static void adv_voice_clear_config (PLCI   *plci);
174
175 static word get_b1_facilities (PLCI   * plci, byte b1_resource);
176 static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities);
177 static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities);
178 static word adjust_b_process (dword Id, PLCI   *plci, byte Rc);
179 static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command);
180 static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc);
181 static void reset_b3_command (dword Id, PLCI   *plci, byte Rc);
182 static void select_b_command (dword Id, PLCI   *plci, byte Rc);
183 static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc);
184 static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc);
185 static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc);
186 static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc);
187 static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc);
188 static void hold_save_command (dword Id, PLCI   *plci, byte Rc);
189 static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc);
190 static void init_b1_config (PLCI   *plci);
191 static void clear_b1_config (PLCI   *plci);
192
193 static void dtmf_command (dword Id, PLCI   *plci, byte Rc);
194 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
195 static void dtmf_confirmation (dword Id, PLCI   *plci);
196 static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length);
197 static void dtmf_parameter_write (PLCI   *plci);
198
199
200 static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id);
201 static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi);
202 static void mixer_clear_config (PLCI   *plci);
203 static void mixer_notify_update (PLCI   *plci, byte others);
204 static void mixer_command (dword Id, PLCI   *plci, byte Rc);
205 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
206 static void mixer_indication_coefs_set (dword Id, PLCI   *plci);
207 static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length);
208 static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length);
209 static void mixer_remove (PLCI   *plci);
210
211
212 static void ec_command (dword Id, PLCI   *plci, byte Rc);
213 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg);
214 static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length);
215
216
217 static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc);
218 static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc);
219
220
221 static int  diva_get_dma_descriptor  (PLCI   *plci, dword   *dma_magic);
222 static void diva_free_dma_descriptor (PLCI   *plci, int nr);
223
224 /*------------------------------------------------------------------*/
225 /* external function prototypes                                     */
226 /*------------------------------------------------------------------*/
227
228 extern byte MapController (byte);
229 extern byte UnMapController (byte);
230 #define MapId(Id) (((Id) & 0xffffff00L) | MapController ((byte)(Id)))
231 #define UnMapId(Id) (((Id) & 0xffffff00L) | UnMapController ((byte)(Id)))
232
233 void   sendf(APPL   *, word, dword, word, byte *, ...);
234 void   * TransmitBufferSet(APPL   * appl, dword ref);
235 void   * TransmitBufferGet(APPL   * appl, void   * p);
236 void TransmitBufferFree(APPL   * appl, void   * p);
237 void   * ReceiveBufferGet(APPL   * appl, int Num);
238
239 int fax_head_line_time (char *buffer);
240
241
242 /*------------------------------------------------------------------*/
243 /* Global data definitions                                          */
244 /*------------------------------------------------------------------*/
245 extern byte max_adapter;
246 extern byte max_appl;
247 extern DIVA_CAPI_ADAPTER   * adapter;
248 extern APPL   * application;
249
250
251
252
253
254
255
256 static byte remove_started = false;
257 static PLCI dummy_plci;
258
259
260 static struct _ftable {
261   word command;
262   byte * format;
263   byte (* function)(dword, word, DIVA_CAPI_ADAPTER   *, PLCI   *, APPL   *, API_PARSE *);
264 } ftable[] = {
265   {_DATA_B3_R,                          "dwww",         data_b3_req},
266   {_DATA_B3_I|RESPONSE,                 "w",            data_b3_res},
267   {_INFO_R,                             "ss",           info_req},
268   {_INFO_I|RESPONSE,                    "",             info_res},
269   {_CONNECT_R,                          "wsssssssss",   connect_req},
270   {_CONNECT_I|RESPONSE,                 "wsssss",       connect_res},
271   {_CONNECT_ACTIVE_I|RESPONSE,          "",             connect_a_res},
272   {_DISCONNECT_R,                       "s",            disconnect_req},
273   {_DISCONNECT_I|RESPONSE,              "",             disconnect_res},
274   {_LISTEN_R,                           "dddss",        listen_req},
275   {_ALERT_R,                            "s",            alert_req},
276   {_FACILITY_R,                         "ws",           facility_req},
277   {_FACILITY_I|RESPONSE,                "ws",           facility_res},
278   {_CONNECT_B3_R,                       "s",            connect_b3_req},
279   {_CONNECT_B3_I|RESPONSE,              "ws",           connect_b3_res},
280   {_CONNECT_B3_ACTIVE_I|RESPONSE,       "",             connect_b3_a_res},
281   {_DISCONNECT_B3_R,                    "s",            disconnect_b3_req},
282   {_DISCONNECT_B3_I|RESPONSE,           "",             disconnect_b3_res},
283   {_RESET_B3_R,                         "s",            reset_b3_req},
284   {_RESET_B3_I|RESPONSE,                "",             reset_b3_res},
285   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "ws",           connect_b3_t90_a_res},
286   {_CONNECT_B3_T90_ACTIVE_I|RESPONSE,   "",             connect_b3_t90_a_res},
287   {_SELECT_B_REQ,                       "s",            select_b_req},
288   {_MANUFACTURER_R,                     "dws",          manufacturer_req},
289   {_MANUFACTURER_I|RESPONSE,            "dws",          manufacturer_res},
290   {_MANUFACTURER_I|RESPONSE,            "",             manufacturer_res}
291 };
292
293 static byte * cip_bc[29][2] = {
294   { "",                     ""                     }, /* 0 */
295   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 1 */
296   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 2 */
297   { "\x02\x89\x90",         "\x02\x89\x90"         }, /* 3 */
298   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 4 */
299   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 5 */
300   { "\x02\x98\x90",         "\x02\x98\x90"         }, /* 6 */
301   { "\x04\x88\xc0\xc6\xe6", "\x04\x88\xc0\xc6\xe6" }, /* 7 */
302   { "\x04\x88\x90\x21\x8f", "\x04\x88\x90\x21\x8f" }, /* 8 */
303   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 9 */
304   { "",                     ""                     }, /* 10 */
305   { "",                     ""                     }, /* 11 */
306   { "",                     ""                     }, /* 12 */
307   { "",                     ""                     }, /* 13 */
308   { "",                     ""                     }, /* 14 */
309   { "",                     ""                     }, /* 15 */
310
311   { "\x03\x80\x90\xa3",     "\x03\x80\x90\xa2"     }, /* 16 */
312   { "\x03\x90\x90\xa3",     "\x03\x90\x90\xa2"     }, /* 17 */
313   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 18 */
314   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 19 */
315   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 20 */
316   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 21 */
317   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 22 */
318   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 23 */
319   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 24 */
320   { "\x02\x88\x90",         "\x02\x88\x90"         }, /* 25 */
321   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 26 */
322   { "\x03\x91\x90\xa5",     "\x03\x91\x90\xa5"     }, /* 27 */
323   { "\x02\x88\x90",         "\x02\x88\x90"         }  /* 28 */
324 };
325
326 static byte * cip_hlc[29] = {
327   "",                           /* 0 */
328   "",                           /* 1 */
329   "",                           /* 2 */
330   "",                           /* 3 */
331   "",                           /* 4 */
332   "",                           /* 5 */
333   "",                           /* 6 */
334   "",                           /* 7 */
335   "",                           /* 8 */
336   "",                           /* 9 */
337   "",                           /* 10 */
338   "",                           /* 11 */
339   "",                           /* 12 */
340   "",                           /* 13 */
341   "",                           /* 14 */
342   "",                           /* 15 */
343
344   "\x02\x91\x81",               /* 16 */
345   "\x02\x91\x84",               /* 17 */
346   "\x02\x91\xa1",               /* 18 */
347   "\x02\x91\xa4",               /* 19 */
348   "\x02\x91\xa8",               /* 20 */
349   "\x02\x91\xb1",               /* 21 */
350   "\x02\x91\xb2",               /* 22 */
351   "\x02\x91\xb5",               /* 23 */
352   "\x02\x91\xb8",               /* 24 */
353   "\x02\x91\xc1",               /* 25 */
354   "\x02\x91\x81",               /* 26 */
355   "\x03\x91\xe0\x01",           /* 27 */
356   "\x03\x91\xe0\x02"            /* 28 */
357 };
358
359 /*------------------------------------------------------------------*/
360
361 #define V120_HEADER_LENGTH 1
362 #define V120_HEADER_EXTEND_BIT  0x80
363 #define V120_HEADER_BREAK_BIT   0x40
364 #define V120_HEADER_C1_BIT      0x04
365 #define V120_HEADER_C2_BIT      0x08
366 #define V120_HEADER_FLUSH_COND  (V120_HEADER_BREAK_BIT | V120_HEADER_C1_BIT | V120_HEADER_C2_BIT)
367
368 static byte v120_default_header[] =
369 {
370
371   0x83                          /*  Ext, BR , res, res, C2 , C1 , B  , F   */
372
373 };
374
375 static byte v120_break_header[] =
376 {
377
378   0xc3 | V120_HEADER_BREAK_BIT  /*  Ext, BR , res, res, C2 , C1 , B  , F   */
379
380 };
381
382
383 /*------------------------------------------------------------------*/
384 /* API_PUT function                                                 */
385 /*------------------------------------------------------------------*/
386
387 word api_put(APPL   * appl, CAPI_MSG   * msg)
388 {
389   word i, j, k, l, n;
390   word ret;
391   byte c;
392   byte controller;
393   DIVA_CAPI_ADAPTER   * a;
394   PLCI   * plci;
395   NCCI   * ncci_ptr;
396   word ncci;
397   CAPI_MSG   *m;
398     API_PARSE msg_parms[MAX_MSG_PARMS+1];
399
400   if (msg->header.length < sizeof (msg->header) ||
401       msg->header.length > MAX_MSG_SIZE) {
402     dbug(1,dprintf("bad len"));
403     return _BAD_MSG;
404   }
405
406   controller = (byte)((msg->header.controller &0x7f)-1);
407
408   /* controller starts with 0 up to (max_adapter - 1) */
409   if ( controller >= max_adapter )
410   {
411     dbug(1,dprintf("invalid ctrl"));
412     return _BAD_MSG;
413   }
414   
415   a = &adapter[controller];
416   plci = NULL;
417   if ((msg->header.plci != 0) && (msg->header.plci <= a->max_plci) && !a->adapter_disabled)
418   {
419     dbug(1,dprintf("plci=%x",msg->header.plci));
420     plci = &a->plci[msg->header.plci-1];
421     ncci = GET_WORD(&msg->header.ncci);
422     if (plci->Id
423      && (plci->appl
424       || (plci->State == INC_CON_PENDING)
425       || (plci->State == INC_CON_ALERT)
426       || (msg->header.command == (_DISCONNECT_I|RESPONSE)))
427      && ((ncci == 0)
428       || (msg->header.command == (_DISCONNECT_B3_I|RESPONSE))
429       || ((ncci < MAX_NCCI+1) && (a->ncci_plci[ncci] == plci->Id))))
430     {
431       i = plci->msg_in_read_pos;
432       j = plci->msg_in_write_pos;
433       if (j >= i)
434       {
435         if (j + msg->header.length + MSG_IN_OVERHEAD <= MSG_IN_QUEUE_SIZE)
436           i += MSG_IN_QUEUE_SIZE - j;
437         else
438           j = 0;
439       }
440       else
441       {
442
443         n = (((CAPI_MSG   *)(plci->msg_in_queue))->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc;
444
445         if (i > MSG_IN_QUEUE_SIZE - n)
446           i = MSG_IN_QUEUE_SIZE - n + 1;
447         i -= j;
448       }
449
450       if (i <= ((msg->header.length + MSG_IN_OVERHEAD + 3) & 0xfffc))
451
452       {
453         dbug(0,dprintf("Q-FULL1(msg) - len=%d write=%d read=%d wrap=%d free=%d",
454           msg->header.length, plci->msg_in_write_pos,
455           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
456
457         return _QUEUE_FULL;
458       }
459       c = false;
460       if ((((byte   *) msg) < ((byte   *)(plci->msg_in_queue)))
461        || (((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
462       {
463         if (plci->msg_in_write_pos != plci->msg_in_read_pos)
464           c = true;
465       }
466       if (msg->header.command == _DATA_B3_R)
467       {
468         if (msg->header.length < 20)
469         {
470           dbug(1,dprintf("DATA_B3 REQ wrong length %d", msg->header.length));
471           return _BAD_MSG;
472         }
473         ncci_ptr = &(a->ncci[ncci]);
474         n = ncci_ptr->data_pending;
475         l = ncci_ptr->data_ack_pending;
476         k = plci->msg_in_read_pos;
477         while (k != plci->msg_in_write_pos)
478         {
479           if (k == plci->msg_in_wrap_pos)
480             k = 0;
481           if ((((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.command == _DATA_B3_R)
482            && (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.ncci == ncci))
483           {
484             n++;
485             if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->info.data_b3_req.Flags & 0x0004)
486               l++;
487           }
488
489           k += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[k]))->header.length +
490             MSG_IN_OVERHEAD + 3) & 0xfffc;
491
492         }
493         if ((n >= MAX_DATA_B3) || (l >= MAX_DATA_ACK))
494         {
495           dbug(0,dprintf("Q-FULL2(data) - pending=%d/%d ack_pending=%d/%d",
496                           ncci_ptr->data_pending, n, ncci_ptr->data_ack_pending, l));
497
498           return _QUEUE_FULL;
499         }
500         if (plci->req_in || plci->internal_command)
501         {
502           if ((((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)))
503            && (((byte   *) msg) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
504           {
505             dbug(0,dprintf("Q-FULL3(requeue)"));
506
507             return _QUEUE_FULL;
508           }
509           c = true;
510         }
511       }
512       else
513       {
514         if (plci->req_in || plci->internal_command)
515           c = true;
516         else
517         {
518           plci->command = msg->header.command;
519           plci->number = msg->header.number;
520         }
521       }
522       if (c)
523       {
524         dbug(1,dprintf("enqueue msg(0x%04x,0x%x,0x%x) - len=%d write=%d read=%d wrap=%d free=%d",
525           msg->header.command, plci->req_in, plci->internal_command,
526           msg->header.length, plci->msg_in_write_pos,
527           plci->msg_in_read_pos, plci->msg_in_wrap_pos, i));
528         if (j == 0)
529           plci->msg_in_wrap_pos = plci->msg_in_write_pos;
530         m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
531         for (i = 0; i < msg->header.length; i++)
532           ((byte   *)(plci->msg_in_queue))[j++] = ((byte   *) msg)[i];
533         if (m->header.command == _DATA_B3_R)
534         {
535
536           m->info.data_b3_req.Data = (dword)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
537
538         }
539
540         j = (j + 3) & 0xfffc;
541
542         *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j])) = appl;
543         plci->msg_in_write_pos = j + MSG_IN_OVERHEAD;
544         return 0;
545       }
546     }
547     else
548     {
549       plci = NULL;
550     }
551   }
552   dbug(1,dprintf("com=%x",msg->header.command));
553
554   for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
555   for(i=0, ret = _BAD_MSG;
556       i<(sizeof(ftable)/sizeof(struct _ftable));
557       i++) {
558
559     if(ftable[i].command==msg->header.command) {
560       /* break loop if the message is correct, otherwise continue scan  */
561       /* (for example: CONNECT_B3_T90_ACT_RES has two specifications)   */
562       if(!api_parse(msg->info.b,(word)(msg->header.length-12),ftable[i].format,msg_parms)) {
563         ret = 0;
564         break;
565       }
566       for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
567     }
568   }
569   if(ret) {
570     dbug(1,dprintf("BAD_MSG"));
571     if(plci) plci->command = 0;
572     return ret;
573   }
574
575
576   c = ftable[i].function(GET_DWORD(&msg->header.controller),
577                          msg->header.number,
578                          a,
579                          plci,
580                          appl,
581                          msg_parms);
582
583   channel_xmit_extended_xon (plci);
584
585   if(c==1) send_req(plci);
586   if(c==2 && plci) plci->req_in = plci->req_in_start = plci->req_out = 0;
587   if(plci && !plci->req_in) plci->command = 0;
588   return 0;
589 }
590
591
592 /*------------------------------------------------------------------*/
593 /* api_parse function, check the format of api messages             */
594 /*------------------------------------------------------------------*/
595
596 word api_parse(byte   * msg, word length, byte * format, API_PARSE * parms)
597 {
598   word i;
599   word p;
600
601   for(i=0,p=0; format[i]; i++) {
602     if(parms)
603     {
604       parms[i].info = &msg[p];
605     }
606     switch(format[i]) {
607     case 'b':
608       p +=1;
609       break;
610     case 'w':
611       p +=2;
612       break;
613     case 'd':
614       p +=4;
615       break;
616     case 's':
617       if(msg[p]==0xff) {
618         parms[i].info +=2;
619         parms[i].length = msg[p+1] + (msg[p+2]<<8);
620         p +=(parms[i].length +3);
621       }
622       else {
623         parms[i].length = msg[p];
624         p +=(parms[i].length +1);
625       }
626       break;
627     }
628
629     if(p>length) return true;
630   }
631   if(parms) parms[i].info = NULL;
632   return false;
633 }
634
635 void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out)
636 {
637   word i, j, n = 0;
638   byte   *p;
639
640   p = out->info;
641   for (i = 0; format[i] != '\0'; i++)
642   {
643     out->parms[i].info = p;
644     out->parms[i].length = in[i].length;
645     switch (format[i])
646     {
647     case 'b':
648       n = 1;
649       break;
650     case 'w':
651       n = 2;
652       break;
653     case 'd':
654       n = 4;
655       break;
656     case 's':
657       n = in[i].length + 1;
658       break;
659     }
660     for (j = 0; j < n; j++)
661       *(p++) = in[i].info[j];
662   }
663   out->parms[i].info = NULL;
664   out->parms[i].length = 0;
665 }
666
667 void api_load_msg(API_SAVE   *in, API_PARSE   *out)
668 {
669   word i;
670
671   i = 0;
672   do
673   {
674     out[i].info = in->parms[i].info;
675     out[i].length = in->parms[i].length;
676   } while (in->parms[i++].info);
677 }
678
679
680 /*------------------------------------------------------------------*/
681 /* CAPI remove function                                             */
682 /*------------------------------------------------------------------*/
683
684 word api_remove_start(void)
685 {
686   word i;
687   word j;
688
689   if(!remove_started) {
690     remove_started = true;
691     for(i=0;i<max_adapter;i++) {
692       if(adapter[i].request) {
693         for(j=0;j<adapter[i].max_plci;j++) {
694           if(adapter[i].plci[j].Sig.Id) plci_remove(&adapter[i].plci[j]);
695         }
696       }
697     }
698     return 1;
699   }
700   else {
701     for(i=0;i<max_adapter;i++) {
702       if(adapter[i].request) {
703         for(j=0;j<adapter[i].max_plci;j++) {
704           if(adapter[i].plci[j].Sig.Id) return 1;
705         }
706       }
707     }
708   }
709   api_remove_complete();
710   return 0;
711 }
712
713
714 /*------------------------------------------------------------------*/
715 /* internal command queue                                           */
716 /*------------------------------------------------------------------*/
717
718 static void init_internal_command_queue (PLCI   *plci)
719 {
720   word i;
721
722   dbug (1, dprintf ("%s,%d: init_internal_command_queue",
723     (char   *)(FILE_), __LINE__));
724
725   plci->internal_command = 0;
726   for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS; i++)
727     plci->internal_command_queue[i] = NULL;
728 }
729
730
731 static void start_internal_command (dword Id, PLCI   *plci, t_std_internal_command command_function)
732 {
733   word i;
734
735   dbug (1, dprintf ("[%06lx] %s,%d: start_internal_command",
736     UnMapId (Id), (char   *)(FILE_), __LINE__));
737
738   if (plci->internal_command == 0)
739   {
740     plci->internal_command_queue[0] = command_function;
741     (* command_function)(Id, plci, OK);
742   }
743   else
744   {
745     i = 1;
746     while (plci->internal_command_queue[i] != 0)
747       i++;
748     plci->internal_command_queue[i] = command_function;
749   }
750 }
751
752
753 static void next_internal_command (dword Id, PLCI   *plci)
754 {
755   word i;
756
757   dbug (1, dprintf ("[%06lx] %s,%d: next_internal_command",
758     UnMapId (Id), (char   *)(FILE_), __LINE__));
759
760   plci->internal_command = 0;
761   plci->internal_command_queue[0] = NULL;
762   while (plci->internal_command_queue[1] != 0)
763   {
764     for (i = 0; i < MAX_INTERNAL_COMMAND_LEVELS - 1; i++)
765       plci->internal_command_queue[i] = plci->internal_command_queue[i+1];
766     plci->internal_command_queue[MAX_INTERNAL_COMMAND_LEVELS - 1] = NULL;
767     (*(plci->internal_command_queue[0]))(Id, plci, OK);
768     if (plci->internal_command != 0)
769       return;
770     plci->internal_command_queue[0] = NULL;
771   }
772 }
773
774
775 /*------------------------------------------------------------------*/
776 /* NCCI allocate/remove function                                    */
777 /*------------------------------------------------------------------*/
778
779 static dword ncci_mapping_bug = 0;
780
781 static word get_ncci (PLCI   *plci, byte ch, word force_ncci)
782 {
783   DIVA_CAPI_ADAPTER   *a;
784   word ncci, i, j, k;
785
786   a = plci->adapter;
787   if (!ch || a->ch_ncci[ch])
788   {
789     ncci_mapping_bug++;
790     dbug(1,dprintf("NCCI mapping exists %ld %02x %02x %02x-%02x",
791       ncci_mapping_bug, ch, force_ncci, a->ncci_ch[a->ch_ncci[ch]], a->ch_ncci[ch]));
792     ncci = ch;
793   }
794   else
795   {
796     if (force_ncci)
797       ncci = force_ncci;
798     else
799     {
800       if ((ch < MAX_NCCI+1) && !a->ncci_ch[ch])
801         ncci = ch;
802       else
803       {
804         ncci = 1;
805         while ((ncci < MAX_NCCI+1) && a->ncci_ch[ncci])
806           ncci++;
807         if (ncci == MAX_NCCI+1)
808         {
809           ncci_mapping_bug++;
810           i = 1;
811           do
812           {
813             j = 1;
814             while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i))
815               j++;
816             k = j;
817             if (j < MAX_NCCI+1)
818             {
819               do
820               {
821                 j++;
822               } while ((j < MAX_NCCI+1) && (a->ncci_ch[j] != i));
823             }
824           } while ((i < MAX_NL_CHANNEL+1) && (j < MAX_NCCI+1));
825           if (i < MAX_NL_CHANNEL+1)
826           {
827             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x %02x-%02x-%02x",
828               ncci_mapping_bug, ch, force_ncci, i, k, j));
829           }
830           else
831           {
832             dbug(1,dprintf("NCCI mapping overflow %ld %02x %02x",
833               ncci_mapping_bug, ch, force_ncci));
834           }
835           ncci = ch;
836         }
837       }
838       a->ncci_plci[ncci] = plci->Id;
839       a->ncci_state[ncci] = IDLE;
840       if (!plci->ncci_ring_list)
841         plci->ncci_ring_list = ncci;
842       else
843         a->ncci_next[ncci] = a->ncci_next[plci->ncci_ring_list];
844       a->ncci_next[plci->ncci_ring_list] = (byte) ncci;
845     }
846     a->ncci_ch[ncci] = ch;
847     a->ch_ncci[ch] = (byte) ncci;
848     dbug(1,dprintf("NCCI mapping established %ld %02x %02x %02x-%02x",
849       ncci_mapping_bug, ch, force_ncci, ch, ncci));
850   }
851   return (ncci);
852 }
853
854
855 static void ncci_free_receive_buffers (PLCI   *plci, word ncci)
856 {
857   DIVA_CAPI_ADAPTER   *a;
858   APPL   *appl;
859   word i, ncci_code;
860   dword Id;
861
862   a = plci->adapter;
863   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
864   if (ncci)
865   {
866     if (a->ncci_plci[ncci] == plci->Id)
867     {
868       if (!plci->appl)
869       {
870         ncci_mapping_bug++;
871         dbug(1,dprintf("NCCI mapping appl expected %ld %08lx",
872           ncci_mapping_bug, Id));
873       }
874       else
875       {
876         appl = plci->appl;
877         ncci_code = ncci | (((word) a->Id) << 8);
878         for (i = 0; i < appl->MaxBuffer; i++)
879         {
880           if ((appl->DataNCCI[i] == ncci_code)
881            && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
882           {
883             appl->DataNCCI[i] = 0;
884           }
885         }
886       }
887     }
888   }
889   else
890   {
891     for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
892     {
893       if (a->ncci_plci[ncci] == plci->Id)
894       {
895         if (!plci->appl)
896         {
897           ncci_mapping_bug++;
898           dbug(1,dprintf("NCCI mapping no appl %ld %08lx",
899             ncci_mapping_bug, Id));
900         }
901         else
902         {
903           appl = plci->appl;
904           ncci_code = ncci | (((word) a->Id) << 8);
905           for (i = 0; i < appl->MaxBuffer; i++)
906           {
907             if ((appl->DataNCCI[i] == ncci_code)
908              && (((byte)(appl->DataFlags[i] >> 8)) == plci->Id))
909             {
910               appl->DataNCCI[i] = 0;
911             }
912           }
913         }
914       }
915     }
916   }
917 }
918
919
920 static void cleanup_ncci_data (PLCI   *plci, word ncci)
921 {
922   NCCI   *ncci_ptr;
923
924   if (ncci && (plci->adapter->ncci_plci[ncci] == plci->Id))
925   {
926     ncci_ptr = &(plci->adapter->ncci[ncci]);
927     if (plci->appl)
928     {
929       while (ncci_ptr->data_pending != 0)
930       {
931         if (!plci->data_sent || (ncci_ptr->DBuffer[ncci_ptr->data_out].P != plci->data_sent_ptr))
932           TransmitBufferFree (plci->appl, ncci_ptr->DBuffer[ncci_ptr->data_out].P);
933         (ncci_ptr->data_out)++;
934         if (ncci_ptr->data_out == MAX_DATA_B3)
935           ncci_ptr->data_out = 0;
936         (ncci_ptr->data_pending)--;
937       }
938     }
939     ncci_ptr->data_out = 0;
940     ncci_ptr->data_pending = 0;
941     ncci_ptr->data_ack_out = 0;
942     ncci_ptr->data_ack_pending = 0;
943   }
944 }
945
946
947 static void ncci_remove (PLCI   *plci, word ncci, byte preserve_ncci)
948 {
949   DIVA_CAPI_ADAPTER   *a;
950   dword Id;
951   word i;
952
953   a = plci->adapter;
954   Id = (((dword) ncci) << 16) | (((word)(plci->Id)) << 8) | a->Id;
955   if (!preserve_ncci)
956     ncci_free_receive_buffers (plci, ncci);
957   if (ncci)
958   {
959     if (a->ncci_plci[ncci] != plci->Id)
960     {
961       ncci_mapping_bug++;
962       dbug(1,dprintf("NCCI mapping doesn't exist %ld %08lx %02x",
963         ncci_mapping_bug, Id, preserve_ncci));
964     }
965     else
966     {
967       cleanup_ncci_data (plci, ncci);
968       dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
969         ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
970       a->ch_ncci[a->ncci_ch[ncci]] = 0;
971       if (!preserve_ncci)
972       {
973         a->ncci_ch[ncci] = 0;
974         a->ncci_plci[ncci] = 0;
975         a->ncci_state[ncci] = IDLE;
976         i = plci->ncci_ring_list;
977         while ((i != 0) && (a->ncci_next[i] != plci->ncci_ring_list) && (a->ncci_next[i] != ncci))
978           i = a->ncci_next[i];
979         if ((i != 0) && (a->ncci_next[i] == ncci))
980         {
981           if (i == ncci)
982             plci->ncci_ring_list = 0;
983           else if (plci->ncci_ring_list == ncci)
984             plci->ncci_ring_list = i;
985           a->ncci_next[i] = a->ncci_next[ncci];
986         }
987         a->ncci_next[ncci] = 0;
988       }
989     }
990   }
991   else
992   {
993     for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
994     {
995       if (a->ncci_plci[ncci] == plci->Id)
996       {
997         cleanup_ncci_data (plci, ncci);
998         dbug(1,dprintf("NCCI mapping released %ld %08lx %02x %02x-%02x",
999           ncci_mapping_bug, Id, preserve_ncci, a->ncci_ch[ncci], ncci));
1000         a->ch_ncci[a->ncci_ch[ncci]] = 0;
1001         if (!preserve_ncci)
1002         {
1003           a->ncci_ch[ncci] = 0;
1004           a->ncci_plci[ncci] = 0;
1005           a->ncci_state[ncci] = IDLE;
1006           a->ncci_next[ncci] = 0;
1007         }
1008       }
1009     }
1010     if (!preserve_ncci)
1011       plci->ncci_ring_list = 0;
1012   }
1013 }
1014
1015
1016 /*------------------------------------------------------------------*/
1017 /* PLCI remove function                                             */
1018 /*------------------------------------------------------------------*/
1019
1020 static void plci_free_msg_in_queue (PLCI   *plci)
1021 {
1022   word i;
1023
1024   if (plci->appl)
1025   {
1026     i = plci->msg_in_read_pos;
1027     while (i != plci->msg_in_write_pos)
1028     {
1029       if (i == plci->msg_in_wrap_pos)
1030         i = 0;
1031       if (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.command == _DATA_B3_R)
1032       {
1033
1034         TransmitBufferFree (plci->appl,
1035           (byte   *)(((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
1036
1037       }
1038
1039       i += (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->header.length +
1040         MSG_IN_OVERHEAD + 3) & 0xfffc;
1041
1042     }
1043   }
1044   plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
1045   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
1046   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
1047 }
1048
1049
1050 static void plci_remove(PLCI   * plci)
1051 {
1052
1053   if(!plci) {
1054     dbug(1,dprintf("plci_remove(no plci)"));
1055     return;
1056   }
1057   init_internal_command_queue (plci);
1058   dbug(1,dprintf("plci_remove(%x,tel=%x)",plci->Id,plci->tel));
1059   if(plci_remove_check(plci))
1060   {
1061     return;
1062   }
1063   if (plci->Sig.Id == 0xff)
1064   {
1065     dbug(1,dprintf("D-channel X.25 plci->NL.Id:%0x", plci->NL.Id));
1066     if (plci->NL.Id && !plci->nl_remove_id)
1067     {
1068       nl_req_ncci(plci,REMOVE,0);
1069       send_req(plci);
1070     }
1071   }
1072   else
1073   {
1074     if (!plci->sig_remove_id
1075      && (plci->Sig.Id
1076       || (plci->req_in!=plci->req_out)
1077       || (plci->nl_req || plci->sig_req)))
1078     {
1079       sig_req(plci,HANGUP,0);
1080       send_req(plci);
1081     }
1082   }
1083   ncci_remove (plci, 0, false);
1084   plci_free_msg_in_queue (plci);
1085
1086   plci->channels = 0;
1087   plci->appl = NULL;
1088   if ((plci->State == INC_CON_PENDING) || (plci->State == INC_CON_ALERT))
1089     plci->State = OUTG_DIS_PENDING;
1090 }
1091
1092 /*------------------------------------------------------------------*/
1093 /* Application Group function helpers                               */
1094 /*------------------------------------------------------------------*/
1095
1096 static void set_group_ind_mask (PLCI   *plci)
1097 {
1098   word i;
1099
1100   for (i = 0; i < C_IND_MASK_DWORDS; i++)
1101     plci->group_optimization_mask_table[i] = 0xffffffffL;
1102 }
1103
1104 static void clear_group_ind_mask_bit (PLCI   *plci, word b)
1105 {
1106   plci->group_optimization_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1107 }
1108
1109 static byte test_group_ind_mask_bit (PLCI   *plci, word b)
1110 {
1111   return ((plci->group_optimization_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1112 }
1113
1114 /*------------------------------------------------------------------*/
1115 /* c_ind_mask operations for arbitrary MAX_APPL                     */
1116 /*------------------------------------------------------------------*/
1117
1118 static void clear_c_ind_mask (PLCI   *plci)
1119 {
1120   word i;
1121
1122   for (i = 0; i < C_IND_MASK_DWORDS; i++)
1123     plci->c_ind_mask_table[i] = 0;
1124 }
1125
1126 static byte c_ind_mask_empty (PLCI   *plci)
1127 {
1128   word i;
1129
1130   i = 0;
1131   while ((i < C_IND_MASK_DWORDS) && (plci->c_ind_mask_table[i] == 0))
1132     i++;
1133   return (i == C_IND_MASK_DWORDS);
1134 }
1135
1136 static void set_c_ind_mask_bit (PLCI   *plci, word b)
1137 {
1138   plci->c_ind_mask_table[b >> 5] |= (1L << (b & 0x1f));
1139 }
1140
1141 static void clear_c_ind_mask_bit (PLCI   *plci, word b)
1142 {
1143   plci->c_ind_mask_table[b >> 5] &= ~(1L << (b & 0x1f));
1144 }
1145
1146 static byte test_c_ind_mask_bit (PLCI   *plci, word b)
1147 {
1148   return ((plci->c_ind_mask_table[b >> 5] & (1L << (b & 0x1f))) != 0);
1149 }
1150
1151 static void dump_c_ind_mask (PLCI   *plci)
1152 {
1153 static char hex_digit_table[0x10] =
1154   {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
1155   word i, j, k;
1156   dword d;
1157     char *p;
1158     char buf[40];
1159
1160   for (i = 0; i < C_IND_MASK_DWORDS; i += 4)
1161   {
1162     p = buf + 36;
1163     *p = '\0';
1164     for (j = 0; j < 4; j++)
1165     {
1166       if (i+j < C_IND_MASK_DWORDS)
1167       {
1168         d = plci->c_ind_mask_table[i+j];
1169         for (k = 0; k < 8; k++)
1170         {
1171           *(--p) = hex_digit_table[d & 0xf];
1172           d >>= 4;
1173         }
1174       }
1175       else if (i != 0)
1176       {
1177         for (k = 0; k < 8; k++)
1178           *(--p) = ' ';
1179       }
1180       *(--p) = ' ';
1181     }
1182     dbug(1,dprintf ("c_ind_mask =%s", (char   *) p));
1183   }
1184 }
1185
1186
1187
1188
1189
1190 #define dump_plcis(a)
1191
1192
1193
1194 /*------------------------------------------------------------------*/
1195 /* translation function for each message                            */
1196 /*------------------------------------------------------------------*/
1197
1198 byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, 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 byte connect_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1416 {
1417   word i, Info;
1418   word Reject;
1419   static byte cau_t[] = {0,0,0x90,0x91,0xac,0x9d,0x86,0xd8,0x9b};
1420   static byte esc_t[] = {0x03,0x08,0x00,0x00};
1421   API_PARSE * ai;
1422     API_PARSE ai_parms[5];
1423   word ch=0;
1424
1425   if(!plci) {
1426     dbug(1,dprintf("connect_res(no plci)"));
1427     return 0;  /* no plci, no send */
1428   }
1429
1430   dbug(1,dprintf("connect_res(State=0x%x)",plci->State));
1431   for(i=0;i<5;i++) ai_parms[i].length = 0;
1432   ai = &parms[5];
1433   dbug(1,dprintf("ai->length=%d",ai->length));
1434
1435   if(ai->length)
1436   {
1437     if(!api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1438     {
1439       dbug(1,dprintf("ai_parms[0].length=%d/0x%x",ai_parms[0].length,GET_WORD(ai_parms[0].info+1)));
1440       ch = 0;
1441       if(ai_parms[0].length)
1442       {
1443         ch = GET_WORD(ai_parms[0].info+1);
1444         dbug(1,dprintf("BCH-I=0x%x",ch));
1445       }
1446     }
1447   }
1448
1449   if(plci->State==INC_CON_CONNECTED_ALERT)
1450   {
1451     dbug(1,dprintf("Connected Alert Call_Res"));
1452     if (a->Info_Mask[appl->Id-1] & 0x200)
1453     {
1454     /* early B3 connect (CIP mask bit 9) no release after a disc */
1455       add_p(plci,LLI,"\x01\x01");
1456     }
1457     add_s(plci, CONN_NR, &parms[2]);
1458     add_s(plci, LLC, &parms[4]);
1459     add_ai(plci, &parms[5]);
1460     plci->State = INC_CON_ACCEPT;
1461     sig_req(plci, CALL_RES,0);
1462     return 1;
1463   }
1464   else if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT) {
1465     clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1466     dump_c_ind_mask (plci);
1467     Reject = GET_WORD(parms[0].info);
1468     dbug(1,dprintf("Reject=0x%x",Reject));
1469     if(Reject) 
1470     {
1471       if(c_ind_mask_empty (plci)) 
1472       {
1473         if((Reject&0xff00)==0x3400) 
1474         {
1475           esc_t[2] = ((byte)(Reject&0x00ff)) | 0x80;
1476           add_p(plci,ESC,esc_t);
1477           add_ai(plci, &parms[5]);
1478           sig_req(plci,REJECT,0);
1479         }      
1480         else if(Reject==1 || Reject>9) 
1481         {
1482           add_ai(plci, &parms[5]);
1483           sig_req(plci,HANGUP,0);
1484         }
1485         else 
1486         {
1487           esc_t[2] = cau_t[(Reject&0x000f)];
1488           add_p(plci,ESC,esc_t);
1489           add_ai(plci, &parms[5]);
1490           sig_req(plci,REJECT,0);
1491         }
1492         plci->appl = appl;
1493       }
1494       else 
1495       {
1496         sendf(appl, _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1497       }
1498     }
1499     else {
1500       plci->appl = appl;
1501       if(Id & EXT_CONTROLLER){
1502         if(AdvCodecSupport(a, plci, appl, 0)){
1503           dbug(1,dprintf("connect_res(error from AdvCodecSupport)"));
1504           sig_req(plci,HANGUP,0);
1505           return 1;
1506         }
1507         if(plci->tel == ADV_VOICE && a->AdvCodecPLCI)
1508         {
1509           Info = add_b23(plci, &parms[1]);
1510           if (Info)
1511           {
1512             dbug(1,dprintf("connect_res(error from add_b23)"));
1513             sig_req(plci,HANGUP,0);
1514             return 1;
1515           }
1516           if(plci->adv_nl)
1517           {
1518             nl_req_ncci(plci, ASSIGN, 0);
1519           }
1520         }
1521       }
1522       else
1523       {
1524         plci->tel = 0;
1525         if(ch!=2)
1526         {
1527           Info = add_b23(plci, &parms[1]);
1528           if (Info)
1529           {
1530             dbug(1,dprintf("connect_res(error from add_b23 2)"));
1531             sig_req(plci,HANGUP,0);
1532             return 1;
1533           }
1534         }
1535         nl_req_ncci(plci, ASSIGN, 0);
1536       }
1537
1538       if(plci->spoofed_msg==SPOOFING_REQUIRED)
1539       {
1540         api_save_msg(parms, "wsssss", &plci->saved_msg);
1541         plci->spoofed_msg = CALL_RES;
1542         plci->internal_command = BLOCK_PLCI;
1543         plci->command = 0;
1544         dbug(1,dprintf("Spoof"));
1545       }
1546       else
1547       {
1548         add_b1 (plci, &parms[1], ch, plci->B1_facilities);
1549         if (a->Info_Mask[appl->Id-1] & 0x200)
1550         {
1551           /* early B3 connect (CIP mask bit 9) no release after a disc */
1552           add_p(plci,LLI,"\x01\x01");
1553         }
1554         add_s(plci, CONN_NR, &parms[2]);
1555         add_s(plci, LLC, &parms[4]);
1556         add_ai(plci, &parms[5]);
1557         plci->State = INC_CON_ACCEPT;
1558         sig_req(plci, CALL_RES,0);
1559       }
1560
1561       for(i=0; i<max_appl; i++) {
1562         if(test_c_ind_mask_bit (plci, i)) {
1563           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
1564         }
1565       }
1566     }
1567   }
1568   return 1;
1569 }
1570
1571 byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1572 {
1573   dbug(1,dprintf("connect_a_res"));
1574   return false;
1575 }
1576
1577 byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1578 {
1579   word Info;
1580   word i;
1581
1582   dbug(1,dprintf("disconnect_req"));
1583
1584   Info = _WRONG_IDENTIFIER;
1585
1586   if(plci)
1587   {
1588     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
1589     {
1590       clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1591       plci->appl = appl;
1592       for(i=0; i<max_appl; i++)
1593       {
1594         if(test_c_ind_mask_bit (plci, i))
1595           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
1596       }
1597       plci->State = OUTG_DIS_PENDING;
1598     }
1599     if(plci->Sig.Id && plci->appl)
1600     {
1601       Info = 0;
1602         if(plci->Sig.Id!=0xff)
1603         {
1604           if(plci->State!=INC_DIS_PENDING)
1605           {
1606             add_ai(plci, &msg[0]);
1607             sig_req(plci,HANGUP,0);
1608             plci->State = OUTG_DIS_PENDING;
1609             return 1;
1610           }
1611         }
1612         else
1613         {
1614           if (plci->NL.Id && !plci->nl_remove_id)
1615           {
1616             mixer_remove (plci);
1617             nl_req_ncci(plci,REMOVE,0);
1618           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
1619           sendf(appl, _DISCONNECT_I, Id, 0, "w", 0);
1620           plci->State = INC_DIS_PENDING;
1621           }
1622           return 1;
1623         }
1624       }
1625     }
1626
1627   if(!appl)  return false;
1628   sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
1629   return false;
1630 }
1631
1632 byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1633 {
1634   dbug(1,dprintf("disconnect_res"));
1635   if(plci)
1636   {
1637         /* clear ind mask bit, just in case of collsion of          */
1638         /* DISCONNECT_IND and CONNECT_RES                           */
1639     clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
1640     ncci_free_receive_buffers (plci, 0);
1641     if(plci_remove_check(plci))
1642     {
1643       return 0;
1644     }
1645     if(plci->State==INC_DIS_PENDING
1646     || plci->State==SUSPENDING) {
1647       if(c_ind_mask_empty (plci)) {
1648         if(plci->State!=SUSPENDING)plci->State = IDLE;
1649         dbug(1,dprintf("chs=%d",plci->channels));
1650         if(!plci->channels) {
1651           plci_remove(plci);
1652         }
1653       }
1654     }
1655   }
1656   return 0;
1657 }
1658
1659 byte listen_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
1660 {
1661   word Info;
1662   byte i;
1663
1664   dbug(1,dprintf("listen_req(Appl=0x%x)",appl->Id));
1665
1666   Info = _WRONG_IDENTIFIER;
1667   if(a) {
1668     Info = 0;
1669     a->Info_Mask[appl->Id-1] = GET_DWORD(parms[0].info);
1670     a->CIP_Mask[appl->Id-1] = GET_DWORD(parms[1].info);
1671     dbug(1,dprintf("CIP_MASK=0x%lx",GET_DWORD(parms[1].info)));
1672     if (a->Info_Mask[appl->Id-1] & 0x200){ /* early B3 connect provides */
1673       a->Info_Mask[appl->Id-1] |=  0x10;   /* call progression infos    */
1674     }
1675
1676     /* check if external controller listen and switch listen on or off*/
1677     if(Id&EXT_CONTROLLER && GET_DWORD(parms[1].info)){
1678       if(a->profile.Global_Options & ON_BOARD_CODEC) {
1679         dummy_plci.State = IDLE;
1680         a->codec_listen[appl->Id-1] = &dummy_plci;
1681         a->TelOAD[0] = (byte)(parms[3].length);
1682         for(i=1;parms[3].length>=i && i<22;i++) {
1683           a->TelOAD[i] = parms[3].info[i];
1684         }
1685         a->TelOAD[i] = 0;
1686         a->TelOSA[0] = (byte)(parms[4].length);
1687         for(i=1;parms[4].length>=i && i<22;i++) {
1688           a->TelOSA[i] = parms[4].info[i];
1689         }
1690         a->TelOSA[i] = 0;
1691       }
1692       else Info = 0x2002; /* wrong controller, codec not supported */
1693     }
1694     else{               /* clear listen */
1695       a->codec_listen[appl->Id-1] = (PLCI   *)0;
1696     }
1697   }
1698   sendf(appl,
1699         _LISTEN_R|CONFIRM,
1700         Id,
1701         Number,
1702         "w",Info);
1703
1704   if (a) listen_check(a);
1705   return false;
1706 }
1707
1708 byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1709 {
1710   word i;
1711   API_PARSE * ai;
1712   PLCI   * rc_plci = NULL;
1713     API_PARSE ai_parms[5];
1714   word Info = 0;
1715
1716   dbug(1,dprintf("info_req"));
1717   for(i=0;i<5;i++) ai_parms[i].length = 0;
1718
1719   ai = &msg[1];
1720
1721   if(ai->length)
1722   {
1723     if(api_parse(&ai->info[1],(word)ai->length,"ssss",ai_parms))
1724     {
1725       dbug(1,dprintf("AddInfo wrong"));
1726       Info = _WRONG_MESSAGE_FORMAT;
1727     }
1728   }
1729   if(!a) Info = _WRONG_STATE;
1730
1731   if(!Info && plci)
1732   {                /* no fac, with CPN, or KEY */
1733     rc_plci = plci;
1734     if(!ai_parms[3].length && plci->State && (msg[0].length || ai_parms[1].length) )
1735     {
1736       /* overlap sending option */
1737       dbug(1,dprintf("OvlSnd"));
1738       add_s(plci,CPN,&msg[0]);
1739       add_s(plci,KEY,&ai_parms[1]);
1740       sig_req(plci,INFO_REQ,0);
1741       send_req(plci);
1742       return false;
1743     }
1744
1745     if(plci->State && ai_parms[2].length)
1746     {
1747       /* User_Info option */
1748       dbug(1,dprintf("UUI"));
1749       add_s(plci,UUI,&ai_parms[2]);
1750       sig_req(plci,USER_DATA,0);
1751     }
1752     else if(plci->State && ai_parms[3].length)
1753     {
1754       /* Facility option */
1755       dbug(1,dprintf("FAC"));
1756       add_s(plci,CPN,&msg[0]);
1757       add_ai(plci, &msg[1]);
1758       sig_req(plci,FACILITY_REQ,0);
1759     }
1760     else
1761     {
1762       Info = _WRONG_STATE;
1763     }
1764   }
1765   else if((ai_parms[1].length || ai_parms[2].length || ai_parms[3].length) && !Info)
1766   {
1767     /* NCR_Facility option -> send UUI and Keypad too */
1768     dbug(1,dprintf("NCR_FAC"));
1769     if((i=get_plci(a)))
1770     {
1771       rc_plci = &a->plci[i-1];
1772       appl->NullCREnable  = true;
1773       rc_plci->internal_command = C_NCR_FAC_REQ;
1774       rc_plci->appl = appl;
1775       add_p(rc_plci,CAI,"\x01\x80");
1776       add_p(rc_plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1777       sig_req(rc_plci,ASSIGN,DSIG_ID);
1778       send_req(rc_plci);
1779     }
1780     else
1781     {
1782       Info = _OUT_OF_PLCI;
1783     }
1784
1785     if(!Info)
1786     {
1787       add_s(rc_plci,CPN,&msg[0]);
1788       add_ai(rc_plci, &msg[1]);
1789       sig_req(rc_plci,NCR_FACILITY,0);
1790       send_req(rc_plci);
1791       return false;
1792      /* for application controlled supplementary services    */
1793     }
1794   }
1795
1796   if (!rc_plci)
1797   {
1798     Info = _WRONG_MESSAGE_FORMAT;
1799   }
1800
1801   if(!Info)
1802   {
1803     send_req(rc_plci);
1804   }
1805   else
1806   {  /* appl is not assigned to a PLCI or error condition */
1807     dbug(1,dprintf("localInfoCon"));
1808     sendf(appl,
1809           _INFO_R|CONFIRM,
1810           Id,
1811           Number,
1812           "w",Info);
1813   }
1814   return false;
1815 }
1816
1817 byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1818 {
1819   dbug(1,dprintf("info_res"));
1820   return false;
1821 }
1822
1823 byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1824 {
1825   word Info;
1826   byte ret;
1827
1828   dbug(1,dprintf("alert_req"));
1829
1830   Info = _WRONG_IDENTIFIER;
1831   ret = false;
1832   if(plci) {
1833     Info = _ALERT_IGNORED;
1834     if(plci->State!=INC_CON_ALERT) {
1835       Info = _WRONG_STATE;
1836       if(plci->State==INC_CON_PENDING) {
1837         Info = 0;
1838         plci->State=INC_CON_ALERT;
1839         add_ai(plci, &msg[0]);
1840         sig_req(plci,CALL_ALERT,0);
1841         ret = 1;
1842       }
1843     }
1844   }
1845   sendf(appl,
1846         _ALERT_R|CONFIRM,
1847         Id,
1848         Number,
1849         "w",Info);
1850   return ret;
1851 }
1852
1853 byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
1854 {
1855   word Info = 0;
1856   word i    = 0;
1857
1858   word selector;
1859   word SSreq;
1860   long relatedPLCIvalue;
1861   DIVA_CAPI_ADAPTER   * relatedadapter;
1862   byte * SSparms  = "";
1863     byte RCparms[]  = "\x05\x00\x00\x02\x00\x00";
1864     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
1865   API_PARSE * parms;
1866     API_PARSE ss_parms[11];
1867   PLCI   *rplci;
1868     byte cai[15];
1869   dword d;
1870     API_PARSE dummy;
1871
1872   dbug(1,dprintf("facility_req"));
1873   for(i=0;i<9;i++) ss_parms[i].length = 0;
1874
1875   parms = &msg[1];
1876
1877   if(!a)
1878   {
1879     dbug(1,dprintf("wrong Ctrl"));
1880     Info = _WRONG_IDENTIFIER;
1881   }
1882
1883   selector = GET_WORD(msg[0].info);
1884
1885   if(!Info)
1886   {
1887     switch(selector)
1888     {
1889       case SELECTOR_HANDSET:
1890         Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
1891         break;
1892
1893       case SELECTOR_SU_SERV:
1894         if(!msg[1].length)
1895         {
1896           Info = _WRONG_MESSAGE_FORMAT;
1897           break;
1898         }
1899         SSreq = GET_WORD(&(msg[1].info[1]));
1900         PUT_WORD(&RCparms[1],SSreq);
1901         SSparms = RCparms;
1902         switch(SSreq)
1903         {
1904           case S_GET_SUPPORTED_SERVICES:
1905             if((i=get_plci(a)))
1906             {
1907               rplci = &a->plci[i-1];
1908               rplci->appl = appl;
1909               add_p(rplci,CAI,"\x01\x80");
1910               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1911               sig_req(rplci,ASSIGN,DSIG_ID);
1912               send_req(rplci);
1913             }
1914             else
1915             {
1916               PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
1917               SSparms = (byte *)SSstruct;
1918               break;
1919             }
1920             rplci->internal_command = GETSERV_REQ_PEND;
1921             rplci->number = Number;
1922             rplci->appl = appl;
1923             sig_req(rplci,S_SUPPORTED,0);
1924             send_req(rplci);
1925             return false;
1926             break;
1927
1928           case S_LISTEN:
1929             if(parms->length==7)
1930             {
1931               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
1932               {
1933                 dbug(1,dprintf("format wrong"));
1934                 Info = _WRONG_MESSAGE_FORMAT;
1935                 break;
1936               }
1937             }
1938             else
1939             {
1940               Info = _WRONG_MESSAGE_FORMAT;
1941               break;
1942             }
1943             a->Notification_Mask[appl->Id-1] = GET_DWORD(ss_parms[2].info);
1944             if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
1945             {
1946               if((i=get_plci(a)))
1947               {
1948                 rplci = &a->plci[i-1];
1949                 rplci->appl = appl;
1950                 add_p(rplci,CAI,"\x01\x80");
1951                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
1952                 sig_req(rplci,ASSIGN,DSIG_ID);
1953                 send_req(rplci);
1954               }
1955               else
1956               {
1957                 break;
1958               }
1959               rplci->internal_command = GET_MWI_STATE;
1960               rplci->number = Number;
1961               sig_req(rplci,MWI_POLL,0);
1962               send_req(rplci);
1963             }
1964             break;
1965
1966           case S_HOLD:
1967             api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
1968             if(plci && plci->State && plci->SuppState==IDLE)
1969             {
1970               plci->SuppState = HOLD_REQUEST;
1971               plci->command = C_HOLD_REQ;
1972               add_s(plci,CAI,&ss_parms[1]);
1973               sig_req(plci,CALL_HOLD,0);
1974               send_req(plci);
1975               return false;
1976             }
1977             else Info = 0x3010;                    /* wrong state           */
1978             break;
1979           case S_RETRIEVE:
1980             if(plci && plci->State && plci->SuppState==CALL_HELD)
1981             {
1982               if(Id & EXT_CONTROLLER)
1983               {
1984                 if(AdvCodecSupport(a, plci, appl, 0))
1985                 {
1986                   Info = 0x3010;                    /* wrong state           */
1987                   break;
1988                 }
1989               }
1990               else plci->tel = 0;
1991
1992               plci->SuppState = RETRIEVE_REQUEST;
1993               plci->command = C_RETRIEVE_REQ;
1994               if(plci->spoofed_msg==SPOOFING_REQUIRED)
1995               {
1996                 plci->spoofed_msg = CALL_RETRIEVE;
1997                 plci->internal_command = BLOCK_PLCI;
1998                 plci->command = 0;
1999                 dbug(1,dprintf("Spoof"));
2000                 return false;
2001               }
2002               else
2003               {
2004                 sig_req(plci,CALL_RETRIEVE,0);
2005                 send_req(plci);
2006                 return false;
2007               }
2008             }
2009             else Info = 0x3010;                    /* wrong state           */
2010             break;
2011           case S_SUSPEND:
2012             if(parms->length)
2013             {
2014               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2015               {
2016                 dbug(1,dprintf("format wrong"));
2017                 Info = _WRONG_MESSAGE_FORMAT;
2018                 break;
2019               }
2020             }
2021             if(plci && plci->State)
2022             {
2023               add_s(plci,CAI,&ss_parms[2]);
2024               plci->command = SUSPEND_REQ;
2025               sig_req(plci,SUSPEND,0);
2026               plci->State = SUSPENDING;
2027               send_req(plci);
2028             }
2029             else Info = 0x3010;                    /* wrong state           */
2030             break;
2031
2032           case S_RESUME:
2033             if(!(i=get_plci(a)) )
2034             {
2035               Info = _OUT_OF_PLCI;
2036               break;
2037             }
2038             rplci = &a->plci[i-1];
2039             rplci->appl = appl;
2040             rplci->number = Number;
2041             rplci->tel = 0;
2042             rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
2043             /* check 'external controller' bit for codec support */
2044             if(Id & EXT_CONTROLLER)
2045             {
2046               if(AdvCodecSupport(a, rplci, appl, 0) )
2047               {
2048                 rplci->Id = 0;
2049                 Info = 0x300A;
2050                 break;
2051               }
2052             }
2053             if(parms->length)
2054             {
2055               if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
2056               {
2057                 dbug(1,dprintf("format wrong"));
2058                 rplci->Id = 0;
2059                 Info = _WRONG_MESSAGE_FORMAT;
2060                 break;
2061               }
2062             }
2063             dummy.length = 0;
2064             dummy.info = "\x00";
2065             add_b1(rplci, &dummy, 0, 0);
2066             if (a->Info_Mask[appl->Id-1] & 0x200)
2067             {
2068               /* early B3 connect (CIP mask bit 9) no release after a disc */
2069               add_p(rplci,LLI,"\x01\x01");
2070             }
2071             add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2072             sig_req(rplci,ASSIGN,DSIG_ID);
2073             send_req(rplci);
2074             add_s(rplci,CAI,&ss_parms[2]);
2075             rplci->command = RESUME_REQ;
2076             sig_req(rplci,RESUME,0);
2077             rplci->State = RESUMING;
2078             send_req(rplci);
2079             break;
2080
2081           case S_CONF_BEGIN: /* Request */
2082           case S_CONF_DROP:
2083           case S_CONF_ISOLATE:
2084           case S_CONF_REATTACH:
2085             if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2086             {
2087               dbug(1,dprintf("format wrong"));
2088               Info = _WRONG_MESSAGE_FORMAT;
2089               break;
2090             }
2091             if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
2092             {
2093               d = GET_DWORD(ss_parms[2].info);     
2094               if(d>=0x80)
2095               {
2096                 dbug(1,dprintf("format wrong"));
2097                 Info = _WRONG_MESSAGE_FORMAT;
2098                 break;
2099               }
2100               plci->ptyState = (byte)SSreq;
2101               plci->command = 0;
2102               cai[0] = 2;
2103               switch(SSreq)
2104               {
2105               case S_CONF_BEGIN:
2106                   cai[1] = CONF_BEGIN;
2107                   plci->internal_command = CONF_BEGIN_REQ_PEND;
2108                   break;
2109               case S_CONF_DROP:
2110                   cai[1] = CONF_DROP;
2111                   plci->internal_command = CONF_DROP_REQ_PEND;
2112                   break;
2113               case S_CONF_ISOLATE:
2114                   cai[1] = CONF_ISOLATE;
2115                   plci->internal_command = CONF_ISOLATE_REQ_PEND;
2116                   break;
2117               case S_CONF_REATTACH:
2118                   cai[1] = CONF_REATTACH;
2119                   plci->internal_command = CONF_REATTACH_REQ_PEND;
2120                   break;
2121               }
2122               cai[2] = (byte)d; /* Conference Size resp. PartyId */
2123               add_p(plci,CAI,cai);
2124               sig_req(plci,S_SERVICE,0);
2125               send_req(plci);
2126               return false;
2127             }
2128             else Info = 0x3010;                    /* wrong state           */
2129             break;
2130
2131           case S_ECT:
2132           case S_3PTY_BEGIN:
2133           case S_3PTY_END:
2134           case S_CONF_ADD:
2135             if(parms->length==7)
2136             {
2137               if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2138               {
2139                 dbug(1,dprintf("format wrong"));
2140                 Info = _WRONG_MESSAGE_FORMAT;
2141                 break;
2142               }
2143             }
2144             else if(parms->length==8) /* workaround for the T-View-S */
2145             {
2146               if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
2147               {
2148                 dbug(1,dprintf("format wrong"));
2149                 Info = _WRONG_MESSAGE_FORMAT;
2150                 break;
2151               }
2152             }
2153             else
2154             {
2155               Info = _WRONG_MESSAGE_FORMAT;
2156               break;
2157             }
2158             if(!msg[1].length)
2159             {
2160               Info = _WRONG_MESSAGE_FORMAT;
2161               break;
2162             }
2163             if (!plci)
2164             {
2165               Info = _WRONG_IDENTIFIER;
2166               break;
2167             }
2168             relatedPLCIvalue = GET_DWORD(ss_parms[2].info);
2169             relatedPLCIvalue &= 0x0000FFFF;
2170             dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
2171             /* controller starts with 0 up to (max_adapter - 1) */
2172             if (((relatedPLCIvalue & 0x7f) == 0)
2173              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
2174              || (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
2175             {
2176               if(SSreq==S_3PTY_END)
2177               {
2178                 dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
2179                 rplci = plci;
2180               }
2181               else
2182               {
2183                 Info = 0x3010;                    /* wrong state           */
2184                 break;
2185               }
2186             }
2187             else
2188             {  
2189               relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
2190               relatedPLCIvalue >>=8;
2191               /* find PLCI PTR*/
2192               for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
2193               {
2194                 if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
2195                 {
2196                   rplci = &relatedadapter->plci[i];
2197                 }
2198               }
2199               if(!rplci || !relatedPLCIvalue)
2200               {
2201                 if(SSreq==S_3PTY_END)
2202                 {
2203                   dbug(1, dprintf("use 2nd PLCI=PLCI"));
2204                   rplci = plci;
2205                 }
2206                 else
2207                 {
2208                   Info = 0x3010;                    /* wrong state           */
2209                   break;
2210                 }
2211               }
2212             }
2213 /*
2214             dbug(1,dprintf("rplci:%x",rplci));
2215             dbug(1,dprintf("plci:%x",plci));
2216             dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
2217             dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
2218             dbug(1,dprintf("SSreq:%x",SSreq));
2219             dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
2220             dbug(1,dprintf("rplci->appl:%x",rplci->appl));
2221             dbug(1,dprintf("rplci->Id:%x",rplci->Id));
2222 */
2223             /* send PTY/ECT req, cannot check all states because of US stuff */
2224             if( !rplci->internal_command && rplci->appl )
2225             {
2226               plci->command = 0;
2227               rplci->relatedPTYPLCI = plci;
2228               plci->relatedPTYPLCI = rplci;
2229               rplci->ptyState = (byte)SSreq;
2230               if(SSreq==S_ECT)
2231               {
2232                 rplci->internal_command = ECT_REQ_PEND;
2233                 cai[1] = ECT_EXECUTE;
2234
2235                 rplci->vswitchstate=0;
2236                 rplci->vsprot=0;
2237                 rplci->vsprotdialect=0;
2238                 plci->vswitchstate=0;
2239                 plci->vsprot=0;
2240                 plci->vsprotdialect=0;
2241
2242               }
2243               else if(SSreq==S_CONF_ADD)
2244               {
2245                 rplci->internal_command = CONF_ADD_REQ_PEND;
2246                 cai[1] = CONF_ADD;
2247               }
2248               else
2249               {
2250                 rplci->internal_command = PTY_REQ_PEND;
2251                 cai[1] = (byte)(SSreq-3);
2252               }
2253               rplci->number = Number;
2254               if(plci!=rplci) /* explicit invocation */
2255               {
2256                 cai[0] = 2;
2257                 cai[2] = plci->Sig.Id;
2258                 dbug(1,dprintf("explicit invocation"));
2259               }
2260               else
2261               {
2262                 dbug(1,dprintf("implicit invocation"));
2263                 cai[0] = 1;
2264               }
2265               add_p(rplci,CAI,cai);
2266               sig_req(rplci,S_SERVICE,0);
2267               send_req(rplci);
2268               return false;
2269             }
2270             else
2271             {
2272               dbug(0,dprintf("Wrong line"));
2273               Info = 0x3010;                    /* wrong state           */
2274               break;
2275             }
2276             break;
2277
2278           case S_CALL_DEFLECTION:
2279             if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
2280             {
2281               dbug(1,dprintf("format wrong"));
2282               Info = _WRONG_MESSAGE_FORMAT;
2283               break;
2284             }
2285             if (!plci)
2286             {
2287               Info = _WRONG_IDENTIFIER;
2288               break;
2289             }
2290             /* reuse unused screening indicator */
2291             ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
2292             plci->command = 0;
2293             plci->internal_command = CD_REQ_PEND;
2294             appl->CDEnable = true;
2295             cai[0] = 1;
2296             cai[1] = CALL_DEFLECTION;
2297             add_p(plci,CAI,cai);
2298             add_p(plci,CPN,ss_parms[3].info);
2299             sig_req(plci,S_SERVICE,0);
2300             send_req(plci);
2301             return false;
2302             break;
2303
2304           case S_CALL_FORWARDING_START:
2305             if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
2306             {
2307               dbug(1,dprintf("format wrong"));
2308               Info = _WRONG_MESSAGE_FORMAT;
2309               break;
2310             }
2311
2312             if((i=get_plci(a)))
2313             {
2314               rplci = &a->plci[i-1];
2315               rplci->appl = appl;
2316               add_p(rplci,CAI,"\x01\x80");
2317               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2318               sig_req(rplci,ASSIGN,DSIG_ID);
2319               send_req(rplci);
2320             }
2321             else
2322             {
2323               Info = _OUT_OF_PLCI;
2324               break;
2325             }
2326
2327             /* reuse unused screening indicator */
2328             rplci->internal_command = CF_START_PEND;
2329             rplci->appl = appl;
2330             rplci->number = Number;
2331             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2332             cai[0] = 2;
2333             cai[1] = 0x70|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2334             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2335             add_p(rplci,CAI,cai);
2336             add_p(rplci,OAD,ss_parms[5].info);
2337             add_p(rplci,CPN,ss_parms[6].info);
2338             sig_req(rplci,S_SERVICE,0);
2339             send_req(rplci);
2340             return false;
2341             break;
2342
2343           case S_INTERROGATE_DIVERSION:
2344           case S_INTERROGATE_NUMBERS:
2345           case S_CALL_FORWARDING_STOP:
2346           case S_CCBS_REQUEST:
2347           case S_CCBS_DEACTIVATE:
2348           case S_CCBS_INTERROGATE:
2349             switch(SSreq)
2350             {
2351             case S_INTERROGATE_NUMBERS:
2352                 if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
2353                 {
2354                   dbug(0,dprintf("format wrong"));
2355                   Info = _WRONG_MESSAGE_FORMAT;
2356                 }
2357                 break;
2358             case S_CCBS_REQUEST:
2359             case S_CCBS_DEACTIVATE:
2360                 if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
2361                 {
2362                   dbug(0,dprintf("format wrong"));
2363                   Info = _WRONG_MESSAGE_FORMAT;
2364                 }
2365                 break;
2366             case S_CCBS_INTERROGATE:
2367                 if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
2368                 {
2369                   dbug(0,dprintf("format wrong"));
2370                   Info = _WRONG_MESSAGE_FORMAT;
2371                 }
2372                 break;
2373             default:
2374             if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
2375             {
2376               dbug(0,dprintf("format wrong"));
2377               Info = _WRONG_MESSAGE_FORMAT;
2378               break;
2379             }
2380                 break;
2381             }
2382
2383             if(Info) break;
2384             if((i=get_plci(a)))
2385             {
2386               rplci = &a->plci[i-1];
2387               switch(SSreq)
2388               {
2389                 case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
2390                   cai[1] = 0x60|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2391                   rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
2392                   break;
2393                 case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
2394                   cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
2395                   rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
2396                   break;
2397                 case S_CALL_FORWARDING_STOP:
2398                   rplci->internal_command = CF_STOP_PEND;
2399                   cai[1] = 0x80|(byte)GET_WORD(&(ss_parms[3].info[0])); /* Function */
2400                   break;
2401                 case S_CCBS_REQUEST:
2402                   cai[1] = CCBS_REQUEST;
2403                   rplci->internal_command = CCBS_REQUEST_REQ_PEND;
2404                   break;
2405                 case S_CCBS_DEACTIVATE:
2406                   cai[1] = CCBS_DEACTIVATE;
2407                   rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
2408                   break;
2409                 case S_CCBS_INTERROGATE:
2410                   cai[1] = CCBS_INTERROGATE;
2411                   rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
2412                   break;
2413                 default:
2414                   cai[1] = 0;
2415                 break;
2416               }
2417               rplci->appl = appl;
2418               rplci->number = Number;
2419               add_p(rplci,CAI,"\x01\x80");
2420               add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2421               sig_req(rplci,ASSIGN,DSIG_ID);
2422               send_req(rplci);
2423             }
2424             else
2425             {
2426               Info = _OUT_OF_PLCI;
2427               break;
2428             }
2429
2430             appl->S_Handle = GET_DWORD(&(ss_parms[2].info[0]));
2431             switch(SSreq)
2432             {
2433             case S_INTERROGATE_NUMBERS:
2434                 cai[0] = 1;
2435                 add_p(rplci,CAI,cai);
2436                 break;
2437             case S_CCBS_REQUEST:
2438             case S_CCBS_DEACTIVATE:
2439                 cai[0] = 3;
2440                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2441                 add_p(rplci,CAI,cai);
2442                 break;
2443             case S_CCBS_INTERROGATE:
2444                 cai[0] = 3;
2445                 PUT_WORD(&cai[2],GET_WORD(&(ss_parms[3].info[0])));
2446                 add_p(rplci,CAI,cai);
2447                 add_p(rplci,OAD,ss_parms[4].info);
2448                 break;
2449             default:
2450             cai[0] = 2;
2451             cai[2] = (byte)GET_WORD(&(ss_parms[4].info[0])); /* Basic Service */
2452             add_p(rplci,CAI,cai);
2453             add_p(rplci,OAD,ss_parms[5].info);
2454                 break;
2455             }
2456                         
2457             sig_req(rplci,S_SERVICE,0);
2458             send_req(rplci);
2459             return false;
2460             break;
2461
2462           case S_MWI_ACTIVATE:
2463             if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
2464             {
2465               dbug(1,dprintf("format wrong"));
2466               Info = _WRONG_MESSAGE_FORMAT;
2467               break;
2468             }
2469             if(!plci)
2470             {                               
2471               if((i=get_plci(a)))
2472               {
2473                 rplci = &a->plci[i-1];
2474                 rplci->appl = appl;
2475                 rplci->cr_enquiry=true;
2476                 add_p(rplci,CAI,"\x01\x80");
2477                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2478                 sig_req(rplci,ASSIGN,DSIG_ID);
2479                 send_req(rplci);
2480               }
2481               else
2482               {
2483                 Info = _OUT_OF_PLCI;
2484                 break;
2485               }
2486             }
2487             else
2488             {
2489               rplci = plci;
2490               rplci->cr_enquiry=false;
2491             }
2492
2493             rplci->command = 0;
2494             rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
2495             rplci->appl = appl;
2496             rplci->number = Number;
2497
2498             cai[0] = 13;
2499             cai[1] = ACTIVATION_MWI; /* Function */
2500             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2501             PUT_DWORD(&cai[4],GET_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
2502             PUT_WORD(&cai[8],GET_WORD(&(ss_parms[4].info[0]))); /* Message Status */
2503             PUT_WORD(&cai[10],GET_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
2504             PUT_WORD(&cai[12],GET_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
2505             add_p(rplci,CAI,cai);
2506             add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
2507             add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
2508             add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
2509             add_p(rplci,UID,ss_parms[10].info); /* Time */
2510             sig_req(rplci,S_SERVICE,0);
2511             send_req(rplci);
2512             return false;
2513
2514           case S_MWI_DEACTIVATE:
2515             if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
2516             {
2517               dbug(1,dprintf("format wrong"));
2518               Info = _WRONG_MESSAGE_FORMAT;
2519               break;
2520             }
2521             if(!plci)
2522             {                               
2523               if((i=get_plci(a)))
2524               {
2525                 rplci = &a->plci[i-1];
2526                 rplci->appl = appl;
2527                 rplci->cr_enquiry=true;
2528                 add_p(rplci,CAI,"\x01\x80");
2529                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
2530                 sig_req(rplci,ASSIGN,DSIG_ID);
2531                 send_req(rplci);
2532               }
2533               else
2534               {
2535                 Info = _OUT_OF_PLCI;
2536                 break;
2537               }
2538             }
2539             else
2540             {
2541               rplci = plci;
2542               rplci->cr_enquiry=false;
2543             }
2544
2545             rplci->command = 0;
2546             rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
2547             rplci->appl = appl;
2548             rplci->number = Number;
2549
2550             cai[0] = 5;
2551             cai[1] = DEACTIVATION_MWI; /* Function */
2552             PUT_WORD(&cai[2],GET_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
2553             PUT_WORD(&cai[4],GET_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
2554             add_p(rplci,CAI,cai);
2555             add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
2556             add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
2557             sig_req(rplci,S_SERVICE,0);
2558             send_req(rplci);
2559             return false;
2560
2561           default:
2562             Info = 0x300E;  /* not supported */
2563             break;
2564         }
2565         break; /* case SELECTOR_SU_SERV: end */
2566
2567
2568       case SELECTOR_DTMF:
2569         return (dtmf_request (Id, Number, a, plci, appl, msg));
2570
2571
2572
2573       case SELECTOR_LINE_INTERCONNECT:
2574         return (mixer_request (Id, Number, a, plci, appl, msg));
2575
2576
2577
2578       case PRIV_SELECTOR_ECHO_CANCELLER:
2579         appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
2580         return (ec_request (Id, Number, a, plci, appl, msg));
2581
2582       case SELECTOR_ECHO_CANCELLER:
2583         appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
2584         return (ec_request (Id, Number, a, plci, appl, msg));
2585
2586
2587       case SELECTOR_V42BIS:
2588       default:
2589         Info = _FACILITY_NOT_SUPPORTED;
2590         break;
2591     } /* end of switch(selector) */
2592   }
2593
2594   dbug(1,dprintf("SendFacRc"));
2595   sendf(appl,
2596         _FACILITY_R|CONFIRM,
2597         Id,
2598         Number,
2599         "wws",Info,selector,SSparms);
2600   return false;
2601 }
2602
2603 byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
2604 {
2605   dbug(1,dprintf("facility_res"));
2606   return false;
2607 }
2608
2609 byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2610 {
2611   word Info = 0;
2612   byte req;
2613   byte len;
2614   word w;
2615   word fax_control_bits, fax_feature_bits, fax_info_change;
2616   API_PARSE * ncpi;
2617     byte pvc[2];
2618
2619     API_PARSE fax_parms[9];
2620   word i;
2621
2622
2623   dbug(1,dprintf("connect_b3_req"));
2624   if(plci)
2625   {
2626     if ((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING)
2627      || (plci->State == INC_DIS_PENDING) || (plci->SuppState != IDLE))
2628     {
2629       Info = _WRONG_STATE;
2630     }
2631     else
2632     {
2633       /* local reply if assign unsuccessfull
2634          or B3 protocol allows only one layer 3 connection
2635            and already connected
2636              or B2 protocol not any LAPD
2637                and connect_b3_req contradicts originate/answer direction */
2638       if (!plci->NL.Id
2639        || (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
2640         && ((plci->channels != 0)
2641          || (((plci->B2_prot != B2_SDLC) && (plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL))
2642           && ((plci->call_dir & CALL_DIR_ANSWER) && !(plci->call_dir & CALL_DIR_FORCE_OUTG_NL))))))
2643       {
2644         dbug(1,dprintf("B3 already connected=%d or no NL.Id=0x%x, dir=%d sstate=0x%x",
2645                        plci->channels,plci->NL.Id,plci->call_dir,plci->SuppState));
2646         Info = _WRONG_STATE;
2647         sendf(appl,                                                        
2648               _CONNECT_B3_R|CONFIRM,
2649               Id,
2650               Number,
2651               "w",Info);
2652         return false;
2653       }
2654       plci->requested_options_conn = 0;
2655
2656       req = N_CONNECT;
2657       ncpi = &parms[0];
2658       if(plci->B3_prot==2 || plci->B3_prot==3)
2659       {
2660         if(ncpi->length>2)
2661         {
2662           /* check for PVC */
2663           if(ncpi->info[2] || ncpi->info[3])
2664           {
2665             pvc[0] = ncpi->info[3];
2666             pvc[1] = ncpi->info[2];
2667             add_d(plci,2,pvc);
2668             req = N_RESET;
2669           }
2670           else
2671           {
2672             if(ncpi->info[1] &1) req = N_CONNECT | N_D_BIT;
2673             add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2674           }
2675         }
2676       }
2677       else if(plci->B3_prot==5)
2678       {
2679         if (plci->NL.Id && !plci->nl_remove_id)
2680         {
2681           fax_control_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low);
2682           fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low);
2683           if (!(fax_control_bits & T30_CONTROL_BIT_MORE_DOCUMENTS)
2684            || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
2685           {
2686             len = (byte)(&(((T30_INFO *) 0)->universal_6));
2687             fax_info_change = false;
2688             if (ncpi->length >= 4)
2689             {
2690               w = GET_WORD(&ncpi->info[3]);
2691               if ((w & 0x0001) != ((word)(((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & 0x0001)))
2692               {
2693                 ((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution =
2694                   (byte)((((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
2695                   ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
2696                 fax_info_change = true;
2697               }
2698               fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
2699               if (w & 0x0002)  /* Fax-polling request */
2700                 fax_control_bits |= T30_CONTROL_BIT_REQUEST_POLLING;
2701               if ((w & 0x0004) /* Request to send / poll another document */
2702                && (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS))
2703               {
2704                 fax_control_bits |= T30_CONTROL_BIT_MORE_DOCUMENTS;
2705               }
2706               if (ncpi->length >= 6)
2707               {
2708                 w = GET_WORD(&ncpi->info[5]);
2709                 if (((byte) w) != ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format)
2710                 {
2711                   ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
2712                   fax_info_change = true;
2713                 }
2714
2715                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2716                  && (GET_WORD(&ncpi->info[5]) & 0x8000)) /* Private SEP/SUB/PWD enable */
2717                 {
2718                   plci->requested_options_conn |= (1L << PRIVATE_FAX_SUB_SEP_PWD);
2719                 }
2720                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
2721                  && (GET_WORD(&ncpi->info[5]) & 0x4000)) /* Private non-standard facilities enable */
2722                 {
2723                   plci->requested_options_conn |= (1L << PRIVATE_FAX_NONSTANDARD);
2724                 }
2725                 fax_control_bits &= ~(T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_SEL_POLLING |
2726                   T30_CONTROL_BIT_ACCEPT_PASSWORD);
2727                 if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2728                   & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
2729                 {
2730                   if (api_parse (&ncpi->info[1], ncpi->length, "wwwwsss", fax_parms))
2731                     Info = _WRONG_MESSAGE_FORMAT;
2732                   else
2733                   {
2734                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2735                       & (1L << PRIVATE_FAX_SUB_SEP_PWD))
2736       {
2737                     fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
2738                     if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
2739                       fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
2740       }
2741                     w = fax_parms[4].length;
2742                     if (w > 20)
2743                       w = 20;
2744                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id_len = (byte) w;
2745                     for (i = 0; i < w; i++)
2746                       ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
2747                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2748                     len = (byte)(((T30_INFO *) 0)->station_id + 20);
2749                     w = fax_parms[5].length;
2750                     if (w > 20)
2751                       w = 20;
2752                     plci->fax_connect_info_buffer[len++] = (byte) w;
2753                     for (i = 0; i < w; i++)
2754                       plci->fax_connect_info_buffer[len++] = fax_parms[5].info[1+i];
2755                     w = fax_parms[6].length;
2756                     if (w > 20)
2757                       w = 20;
2758                     plci->fax_connect_info_buffer[len++] = (byte) w;
2759                     for (i = 0; i < w; i++)
2760                       plci->fax_connect_info_buffer[len++] = fax_parms[6].info[1+i];
2761                     if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[appl->Id-1])
2762                       & (1L << PRIVATE_FAX_NONSTANDARD))
2763       {
2764                       if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2765         {
2766                         dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2767                         plci->fax_connect_info_buffer[len++] = 0;
2768         }
2769                       else
2770                       {
2771           if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2772             plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2773    plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2774           for (i = 0; i < fax_parms[7].length; i++)
2775      plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2776                       }
2777                     }
2778                   }
2779                 }
2780                 else
2781                 {
2782                   len = (byte)(&(((T30_INFO *) 0)->universal_6));
2783                 }
2784                 fax_info_change = true;
2785
2786               }
2787               if (fax_control_bits != GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low))
2788               {
2789                 PUT_WORD (&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
2790                 fax_info_change = true;
2791               }
2792             }
2793             if (Info == GOOD)
2794             {
2795               plci->fax_connect_info_length = len;
2796               if (fax_info_change)
2797               {
2798                 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
2799                 {
2800                   start_internal_command (Id, plci, fax_connect_info_command);
2801                   return false;
2802                 }
2803                 else
2804                 {
2805                   start_internal_command (Id, plci, fax_adjust_b23_command);
2806                   return false;
2807                 }
2808               }
2809             }
2810           }
2811           else  Info = _WRONG_STATE;
2812         }
2813         else  Info = _WRONG_STATE;
2814       }
2815
2816       else if (plci->B3_prot == B3_RTP)
2817       {
2818         plci->internal_req_buffer[0] = ncpi->length + 1;
2819         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2820         for (w = 0; w < ncpi->length; w++)
2821           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2822         start_internal_command (Id, plci, rtp_connect_b3_req_command);
2823         return false;
2824       }
2825
2826       if(!Info)
2827       {
2828         nl_req_ncci(plci,req,0);
2829         return 1;
2830       }
2831     }
2832   }
2833   else Info = _WRONG_IDENTIFIER;
2834
2835   sendf(appl,
2836         _CONNECT_B3_R|CONFIRM,
2837         Id,
2838         Number,
2839         "w",Info);
2840   return false;
2841 }
2842
2843 byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2844 {
2845   word ncci;
2846   API_PARSE * ncpi;
2847   byte req;
2848
2849   word w;
2850
2851
2852     API_PARSE fax_parms[9];
2853   word i;
2854   byte len;
2855
2856
2857   dbug(1,dprintf("connect_b3_res"));
2858
2859   ncci = (word)(Id>>16);
2860   if(plci && ncci) {
2861     if(a->ncci_state[ncci]==INC_CON_PENDING) {
2862       if (GET_WORD (&parms[0].info[0]) != 0)
2863       {
2864         a->ncci_state[ncci] = OUTG_REJ_PENDING;
2865         channel_request_xon (plci, a->ncci_ch[ncci]);
2866         channel_xmit_xon (plci);
2867         cleanup_ncci_data (plci, ncci);
2868         nl_req_ncci(plci,N_DISC,(byte)ncci);
2869         return 1;
2870       }
2871       a->ncci_state[ncci] = INC_ACT_PENDING;
2872
2873       req = N_CONNECT_ACK;
2874       ncpi = &parms[1];
2875       if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
2876       {
2877
2878         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
2879           & (1L << PRIVATE_FAX_NONSTANDARD))
2880  {
2881    if (((plci->B3_prot == 4) || (plci->B3_prot == 5))
2882     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
2883     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
2884    {
2885             len = ((byte)(((T30_INFO *) 0)->station_id + 20));
2886             if (plci->fax_connect_info_length < len)
2887             {
2888               ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
2889               ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
2890             }
2891             if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
2892             {
2893               dbug(1,dprintf("non-standard facilities info missing or wrong format"));
2894             }
2895             else
2896             {
2897               if (plci->fax_connect_info_length <= len)
2898                 plci->fax_connect_info_buffer[len] = 0;
2899               len += 1 + plci->fax_connect_info_buffer[len];
2900               if (plci->fax_connect_info_length <= len)
2901                 plci->fax_connect_info_buffer[len] = 0;
2902               len += 1 + plci->fax_connect_info_buffer[len];
2903               if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
2904                 plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
2905               plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
2906               for (i = 0; i < fax_parms[7].length; i++)
2907                 plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
2908             }
2909             plci->fax_connect_info_length = len;
2910             ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
2911             start_internal_command (Id, plci, fax_connect_ack_command);
2912      return false;
2913           }
2914         }
2915
2916         nl_req_ncci(plci,req,(byte)ncci);
2917         if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
2918          && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
2919         {
2920           if (plci->B3_prot == 4)
2921             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2922           else
2923             sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
2924           plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
2925         }
2926       }
2927
2928       else if (plci->B3_prot == B3_RTP)
2929       {
2930         plci->internal_req_buffer[0] = ncpi->length + 1;
2931         plci->internal_req_buffer[1] = UDATA_REQUEST_RTP_RECONFIGURE;
2932         for (w = 0; w < ncpi->length; w++)
2933           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
2934         start_internal_command (Id, plci, rtp_connect_b3_res_command);
2935         return false;
2936       }
2937
2938       else
2939       {
2940         if(ncpi->length>2) {
2941           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
2942           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
2943         }
2944         nl_req_ncci(plci,req,(byte)ncci);
2945         sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
2946         if (plci->adjust_b_restore)
2947         {
2948           plci->adjust_b_restore = false;
2949           start_internal_command (Id, plci, adjust_b_restore);
2950         }
2951       }
2952       return 1;
2953     }
2954   }
2955   return false;
2956 }
2957
2958 byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2959 {
2960   word ncci;
2961
2962   ncci = (word)(Id>>16);
2963   dbug(1,dprintf("connect_b3_a_res(ncci=0x%x)",ncci));
2964
2965   if (plci && ncci && (plci->State != IDLE) && (plci->State != INC_DIS_PENDING)
2966    && (plci->State != OUTG_DIS_PENDING))
2967   {
2968     if(a->ncci_state[ncci]==INC_ACT_PENDING) {
2969       a->ncci_state[ncci] = CONNECTED;
2970       if(plci->State!=INC_CON_CONNECTED_ALERT) plci->State = CONNECTED;
2971       channel_request_xon (plci, a->ncci_ch[ncci]);
2972       channel_xmit_xon (plci);
2973     }
2974   }
2975   return false;
2976 }
2977
2978 byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
2979 {
2980   word Info;
2981   word ncci;
2982   API_PARSE * ncpi;
2983
2984   dbug(1,dprintf("disconnect_b3_req"));
2985
2986   Info = _WRONG_IDENTIFIER;
2987   ncci = (word)(Id>>16);
2988   if (plci && ncci)
2989   {
2990     Info = _WRONG_STATE;
2991     if ((a->ncci_state[ncci] == CONNECTED)
2992      || (a->ncci_state[ncci] == OUTG_CON_PENDING)
2993      || (a->ncci_state[ncci] == INC_CON_PENDING)
2994      || (a->ncci_state[ncci] == INC_ACT_PENDING))
2995     {
2996       a->ncci_state[ncci] = OUTG_DIS_PENDING;
2997       channel_request_xon (plci, a->ncci_ch[ncci]);
2998       channel_xmit_xon (plci);
2999
3000       if (a->ncci[ncci].data_pending
3001        && ((plci->B3_prot == B3_TRANSPARENT)
3002         || (plci->B3_prot == B3_T30)
3003         || (plci->B3_prot == B3_T30_WITH_EXTENSIONS)))
3004       {
3005         plci->send_disc = (byte)ncci;
3006         plci->command = 0;
3007         return false;
3008       }
3009       else
3010       {
3011         cleanup_ncci_data (plci, ncci);
3012
3013         if(plci->B3_prot==2 || plci->B3_prot==3)
3014         {
3015           ncpi = &parms[0];
3016           if(ncpi->length>3)
3017           {
3018             add_d(plci, (word)(ncpi->length - 3) ,(byte   *)&(ncpi->info[4]));
3019           }
3020         }
3021         nl_req_ncci(plci,N_DISC,(byte)ncci);
3022       }
3023       return 1;
3024     }
3025   }
3026   sendf(appl,
3027         _DISCONNECT_B3_R|CONFIRM,
3028         Id,
3029         Number,
3030         "w",Info);
3031   return false;
3032 }
3033
3034 byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3035 {
3036   word ncci;
3037   word i;
3038
3039   ncci = (word)(Id>>16);
3040   dbug(1,dprintf("disconnect_b3_res(ncci=0x%x",ncci));
3041   if(plci && ncci) {
3042     plci->requested_options_conn = 0;
3043     plci->fax_connect_info_length = 0;
3044     plci->ncpi_state = 0x00;
3045     if (((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE))
3046       && ((plci->B2_prot != B2_LAPD) && (plci->B2_prot != B2_LAPD_FREE_SAPI_SEL)))
3047     {
3048       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
3049     }
3050     for(i=0; i<MAX_CHANNELS_PER_PLCI && plci->inc_dis_ncci_table[i]!=(byte)ncci; i++);
3051     if(i<MAX_CHANNELS_PER_PLCI) {
3052       if(plci->channels)plci->channels--;
3053       for(; i<MAX_CHANNELS_PER_PLCI-1; i++) plci->inc_dis_ncci_table[i] = plci->inc_dis_ncci_table[i+1];
3054       plci->inc_dis_ncci_table[MAX_CHANNELS_PER_PLCI-1] = 0;
3055
3056       ncci_free_receive_buffers (plci, ncci);
3057
3058       if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
3059         if(plci->State == SUSPENDING){
3060           sendf(plci->appl,
3061                 _FACILITY_I,
3062                 Id & 0xffffL,
3063                 0,
3064                 "ws", (word)3, "\x03\x04\x00\x00");
3065           sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
3066         }
3067         plci_remove(plci);
3068         plci->State=IDLE;
3069       }
3070     }
3071     else
3072     {
3073       if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
3074        && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
3075        && (a->ncci_state[ncci] == INC_DIS_PENDING))
3076       {
3077         ncci_free_receive_buffers (plci, ncci);
3078
3079         nl_req_ncci(plci,N_EDATA,(byte)ncci);
3080
3081         plci->adapter->ncci_state[ncci] = IDLE;
3082         start_internal_command (Id, plci, fax_disconnect_command);
3083         return 1;
3084       }
3085     }
3086   }
3087   return false;
3088 }
3089
3090 byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3091 {
3092   NCCI   *ncci_ptr;
3093   DATA_B3_DESC   *data;
3094   word Info;
3095   word ncci;
3096   word i;
3097
3098   dbug(1,dprintf("data_b3_req"));
3099
3100   Info = _WRONG_IDENTIFIER;
3101   ncci = (word)(Id>>16);
3102   dbug(1,dprintf("ncci=0x%x, plci=0x%x",ncci,plci));
3103
3104   if (plci && ncci)
3105   {
3106     Info = _WRONG_STATE;
3107     if ((a->ncci_state[ncci] == CONNECTED)
3108      || (a->ncci_state[ncci] == INC_ACT_PENDING))
3109     {
3110         /* queue data */
3111       ncci_ptr = &(a->ncci[ncci]);
3112       i = ncci_ptr->data_out + ncci_ptr->data_pending;
3113       if (i >= MAX_DATA_B3)
3114         i -= MAX_DATA_B3;
3115       data = &(ncci_ptr->DBuffer[i]);
3116       data->Number = Number;
3117       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3118        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3119       {
3120
3121         data->P = (byte   *)(*((dword   *)(parms[0].info)));
3122
3123       }
3124       else
3125         data->P = TransmitBufferSet(appl,*(dword *)parms[0].info);
3126       data->Length = GET_WORD(parms[1].info);
3127       data->Handle = GET_WORD(parms[2].info);
3128       data->Flags = GET_WORD(parms[3].info);
3129       (ncci_ptr->data_pending)++;
3130
3131         /* check for delivery confirmation */
3132       if (data->Flags & 0x0004)
3133       {
3134         i = ncci_ptr->data_ack_out + ncci_ptr->data_ack_pending;
3135         if (i >= MAX_DATA_ACK)
3136           i -= MAX_DATA_ACK;
3137         ncci_ptr->DataAck[i].Number = data->Number;
3138         ncci_ptr->DataAck[i].Handle = data->Handle;
3139         (ncci_ptr->data_ack_pending)++;
3140       }
3141
3142       send_data(plci);
3143       return false;
3144     }
3145   }
3146   if (appl)
3147   {
3148     if (plci)
3149     {
3150       if ((((byte   *)(parms[0].info)) >= ((byte   *)(plci->msg_in_queue)))
3151        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
3152       {
3153
3154         TransmitBufferFree (appl, (byte   *)(*((dword   *)(parms[0].info))));
3155
3156       }
3157     }
3158     sendf(appl,
3159           _DATA_B3_R|CONFIRM,
3160           Id,
3161           Number,
3162           "ww",GET_WORD(parms[2].info),Info);
3163   }
3164   return false;
3165 }
3166
3167 byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3168 {
3169   word n;
3170   word ncci;
3171   word NCCIcode;
3172
3173   dbug(1,dprintf("data_b3_res"));
3174
3175   ncci = (word)(Id>>16);
3176   if(plci && ncci) {
3177     n = GET_WORD(parms[0].info);
3178     dbug(1,dprintf("free(%d)",n));
3179     NCCIcode = ncci | (((word) a->Id) << 8);
3180     if(n<appl->MaxBuffer &&
3181        appl->DataNCCI[n]==NCCIcode &&
3182        (byte)(appl->DataFlags[n]>>8)==plci->Id) {
3183       dbug(1,dprintf("found"));
3184       appl->DataNCCI[n] = 0;
3185
3186       if (channel_can_xon (plci, a->ncci_ch[ncci])) {
3187         channel_request_xon (plci, a->ncci_ch[ncci]);
3188       }
3189       channel_xmit_xon (plci);
3190
3191       if(appl->DataFlags[n] &4) {
3192         nl_req_ncci(plci,N_DATA_ACK,(byte)ncci);
3193         return 1;
3194       }
3195     }
3196   }
3197   return false;
3198 }
3199
3200 byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3201 {
3202   word Info;
3203   word ncci;
3204
3205   dbug(1,dprintf("reset_b3_req"));
3206
3207   Info = _WRONG_IDENTIFIER;
3208   ncci = (word)(Id>>16);
3209   if(plci && ncci)
3210   {
3211     Info = _WRONG_STATE;
3212     switch (plci->B3_prot)
3213     {
3214     case B3_ISO8208:
3215     case B3_X25_DCE:
3216       if(a->ncci_state[ncci]==CONNECTED)
3217       {
3218         nl_req_ncci(plci,N_RESET,(byte)ncci);
3219         send_req(plci);
3220         Info = GOOD;
3221       }
3222       break;
3223     case B3_TRANSPARENT:
3224       if(a->ncci_state[ncci]==CONNECTED)
3225       {
3226         start_internal_command (Id, plci, reset_b3_command);
3227         Info = GOOD;
3228       }
3229       break;
3230     }
3231   }
3232   /* reset_b3 must result in a reset_b3_con & reset_b3_Ind */
3233   sendf(appl,
3234         _RESET_B3_R|CONFIRM,
3235         Id,
3236         Number,
3237         "w",Info);
3238   return false;
3239 }
3240
3241 byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3242 {
3243   word ncci;
3244
3245   dbug(1,dprintf("reset_b3_res"));
3246
3247   ncci = (word)(Id>>16);
3248   if(plci && ncci) {
3249     switch (plci->B3_prot)
3250     {
3251     case B3_ISO8208:
3252     case B3_X25_DCE:
3253       if(a->ncci_state[ncci]==INC_RES_PENDING)
3254       {
3255         a->ncci_state[ncci] = CONNECTED;
3256         nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
3257         return true;
3258       }
3259     break;
3260     }
3261   }
3262   return false;
3263 }
3264
3265 byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3266 {
3267   word ncci;
3268   API_PARSE * ncpi;
3269   byte req;
3270
3271   dbug(1,dprintf("connect_b3_t90_a_res"));
3272
3273   ncci = (word)(Id>>16);
3274   if(plci && ncci) {
3275     if(a->ncci_state[ncci]==INC_ACT_PENDING) {
3276       a->ncci_state[ncci] = CONNECTED;
3277     }
3278     else if(a->ncci_state[ncci]==INC_CON_PENDING) {
3279       a->ncci_state[ncci] = CONNECTED;
3280
3281       req = N_CONNECT_ACK;
3282
3283         /* parms[0]==0 for CAPI original message definition! */
3284       if(parms[0].info) {
3285         ncpi = &parms[1];
3286         if(ncpi->length>2) {
3287           if(ncpi->info[1] &1) req = N_CONNECT_ACK | N_D_BIT;
3288           add_d(plci,(word)(ncpi->length-3),&ncpi->info[4]);
3289         }
3290       }
3291       nl_req_ncci(plci,req,(byte)ncci);
3292       return 1;
3293     }
3294   }
3295   return false;
3296 }
3297
3298
3299 byte select_b_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
3300 {
3301   word Info=0;
3302   word i;
3303   byte tel;
3304     API_PARSE bp_parms[7];
3305
3306   if(!plci || !msg)
3307   {
3308     Info = _WRONG_IDENTIFIER;
3309   }
3310   else
3311   {
3312     dbug(1,dprintf("select_b_req[%d],PLCI=0x%x,Tel=0x%x,NL=0x%x,appl=0x%x,sstate=0x%x",
3313                    msg->length,plci->Id,plci->tel,plci->NL.Id,plci->appl,plci->SuppState));
3314     dbug(1,dprintf("PlciState=0x%x",plci->State));
3315     for(i=0;i<7;i++) bp_parms[i].length = 0;
3316
3317     /* check if no channel is open, no B3 connected only */
3318     if((plci->State == IDLE) || (plci->State == OUTG_DIS_PENDING) || (plci->State == INC_DIS_PENDING)
3319      || (plci->SuppState != IDLE) || plci->channels || plci->nl_remove_id)
3320     {
3321       Info = _WRONG_STATE;
3322     }
3323     /* check message format and fill bp_parms pointer */
3324     else if(msg->length && api_parse(&msg->info[1], (word)msg->length, "wwwsss", bp_parms))
3325     {
3326       Info = _WRONG_MESSAGE_FORMAT;
3327     }
3328     else
3329     {
3330       if((plci->State==INC_CON_PENDING) || (plci->State==INC_CON_ALERT)) /* send alert tone inband to the network, */
3331       {                                                                  /* e.g. Qsig or RBS or Cornet-N or xess PRI */
3332         if(Id & EXT_CONTROLLER)
3333         {
3334           sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", 0x2002); /* wrong controller */
3335           return 0;
3336         }
3337         plci->State=INC_CON_CONNECTED_ALERT;
3338         plci->appl = appl;
3339         clear_c_ind_mask_bit (plci, (word)(appl->Id-1));
3340         dump_c_ind_mask (plci);
3341         for(i=0; i<max_appl; i++) /* disconnect the other appls */
3342         {                         /* its quasi a connect        */
3343           if(test_c_ind_mask_bit (plci, i))
3344             sendf(&application[i], _DISCONNECT_I, Id, 0, "w", _OTHER_APPL_CONNECTED);
3345         }
3346       }
3347
3348       api_save_msg(msg, "s", &plci->saved_msg);
3349       tel = plci->tel;
3350       if(Id & EXT_CONTROLLER)
3351       {
3352         if(tel) /* external controller in use by this PLCI */
3353         {
3354           if(a->AdvSignalAppl && a->AdvSignalAppl!=appl)
3355           {
3356             dbug(1,dprintf("Ext_Ctrl in use 1"));
3357             Info = _WRONG_STATE;
3358           }
3359         }
3360         else  /* external controller NOT in use by this PLCI ? */
3361         {
3362           if(a->AdvSignalPLCI)
3363           {
3364             dbug(1,dprintf("Ext_Ctrl in use 2"));
3365             Info = _WRONG_STATE;
3366           }
3367           else /* activate the codec */
3368           {
3369             dbug(1,dprintf("Ext_Ctrl start"));
3370             if(AdvCodecSupport(a, plci, appl, 0) )
3371             {
3372               dbug(1,dprintf("Error in codec procedures"));
3373               Info = _WRONG_STATE;
3374             }
3375             else if(plci->spoofed_msg==SPOOFING_REQUIRED) /* wait until codec is active */
3376             {
3377               plci->spoofed_msg = AWAITING_SELECT_B;
3378               plci->internal_command = BLOCK_PLCI; /* lock other commands */
3379               plci->command = 0;
3380               dbug(1,dprintf("continue if codec loaded"));
3381               return false;
3382             }
3383           }
3384         }
3385       }
3386       else /* external controller bit is OFF */
3387       {
3388         if(tel) /* external controller in use, need to switch off */
3389         {
3390           if(a->AdvSignalAppl==appl)
3391           {
3392             CodecIdCheck(a, plci);
3393             plci->tel = 0;
3394             plci->adv_nl = 0;
3395             dbug(1,dprintf("Ext_Ctrl disable"));
3396           }
3397           else
3398           {
3399             dbug(1,dprintf("Ext_Ctrl not requested"));
3400           }
3401         }
3402       }
3403       if (!Info)
3404       {
3405         if (plci->call_dir & CALL_DIR_OUT)
3406           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3407         else if (plci->call_dir & CALL_DIR_IN)
3408           plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
3409         start_internal_command (Id, plci, select_b_command);
3410         return false;
3411       }
3412     }
3413   }
3414   sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
3415   return false;
3416 }
3417
3418 byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
3419 {
3420   word command;
3421   word i;
3422   word ncci;
3423   API_PARSE * m;
3424     API_PARSE m_parms[5];
3425   word codec;
3426   byte req;
3427   byte ch;
3428   byte dir;
3429   static byte chi[2] = {0x01,0x00};
3430   static byte lli[2] = {0x01,0x00};
3431   static byte codec_cai[2] = {0x01,0x01};
3432   static byte null_msg = {0};
3433   static API_PARSE null_parms = { 0, &null_msg };
3434   PLCI   * v_plci;
3435   word Info=0;
3436
3437   dbug(1,dprintf("manufacturer_req"));
3438   for(i=0;i<5;i++) m_parms[i].length = 0;
3439
3440   if(GET_DWORD(parms[0].info)!=_DI_MANU_ID) {
3441     Info = _WRONG_MESSAGE_FORMAT;
3442   }
3443   command = GET_WORD(parms[1].info);
3444   m = &parms[2];
3445   if (!Info)
3446   {
3447     switch(command) {
3448     case _DI_ASSIGN_PLCI:
3449       if(api_parse(&m->info[1],(word)m->length,"wbbs",m_parms)) {
3450         Info = _WRONG_MESSAGE_FORMAT;
3451         break;
3452       }
3453       codec = GET_WORD(m_parms[0].info);
3454       ch = m_parms[1].info[0];
3455       dir = m_parms[2].info[0];
3456       if((i=get_plci(a))) {
3457         plci = &a->plci[i-1];
3458         plci->appl = appl;
3459         plci->command = _MANUFACTURER_R;
3460         plci->m_command = command;
3461         plci->number = Number;
3462         plci->State = LOCAL_CONNECT;
3463         Id = ( ((word)plci->Id<<8)|plci->adapter->Id|0x80);
3464         dbug(1,dprintf("ManCMD,plci=0x%x",Id));
3465
3466         if((ch==1 || ch==2) && (dir<=2)) {
3467           chi[1] = (byte)(0x80|ch);
3468           lli[1] = 0;
3469           plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
3470           switch(codec)
3471           {
3472           case 0:
3473             Info = add_b1(plci,&m_parms[3],0,0);
3474             break;
3475           case 1:
3476             add_p(plci,CAI,codec_cai);
3477             break;
3478           /* manual 'swich on' to the codec support without signalling */
3479           /* first 'assign plci' with this function, then use */
3480           case 2:
3481             if(AdvCodecSupport(a, plci, appl, 0) ) {
3482               Info = _RESOURCE_ERROR;
3483             }
3484             else {
3485               Info = add_b1(plci,&null_parms,0,B1_FACILITY_LOCAL);
3486               lli[1] = 0x10; /* local call codec stream */
3487             }
3488             break;
3489           }
3490
3491           plci->State = LOCAL_CONNECT;
3492           plci->manufacturer = true;
3493           plci->command = _MANUFACTURER_R;
3494           plci->m_command = command;
3495           plci->number = Number;
3496
3497           if(!Info)
3498           {
3499             add_p(plci,LLI,lli);
3500             add_p(plci,CHI,chi);
3501             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
3502             sig_req(plci,ASSIGN,DSIG_ID);
3503
3504             if(!codec)
3505             {
3506               Info = add_b23(plci,&m_parms[3]);
3507               if(!Info)
3508               {
3509                 nl_req_ncci(plci,ASSIGN,0);
3510                 send_req(plci);
3511               }
3512             }
3513             if(!Info)
3514             {
3515               dbug(1,dprintf("dir=0x%x,spoof=0x%x",dir,plci->spoofed_msg));
3516               if (plci->spoofed_msg==SPOOFING_REQUIRED)
3517               {
3518                 api_save_msg (m_parms, "wbbs", &plci->saved_msg);
3519                 plci->spoofed_msg = AWAITING_MANUF_CON;
3520                 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3521                 plci->command = 0;
3522                 send_req(plci);
3523                 return false;
3524               }
3525               if(dir==1) {
3526                 sig_req(plci,CALL_REQ,0);
3527               }
3528               else if(!dir){
3529                 sig_req(plci,LISTEN_REQ,0);
3530               }
3531               send_req(plci);
3532             }
3533             else
3534             {
3535               sendf(appl,
3536                     _MANUFACTURER_R|CONFIRM,
3537                     Id,
3538                     Number,
3539                     "dww",_DI_MANU_ID,command,Info);
3540               return 2;
3541             }
3542           }
3543         }
3544       }
3545       else  Info = _OUT_OF_PLCI;
3546       break;
3547
3548     case _DI_IDI_CTRL:
3549       if(!plci)
3550       {
3551         Info = _WRONG_IDENTIFIER;
3552         break;
3553       }
3554       if(api_parse(&m->info[1],(word)m->length,"bs",m_parms)) {
3555         Info = _WRONG_MESSAGE_FORMAT;
3556         break;
3557       }
3558       req = m_parms[0].info[0];
3559       plci->command = _MANUFACTURER_R;
3560       plci->m_command = command;
3561       plci->number = Number;
3562       if(req==CALL_REQ)
3563       {
3564         plci->b_channel = getChannel(&m_parms[1]);
3565         mixer_set_bchannel_id_esc (plci, plci->b_channel);
3566         if(plci->spoofed_msg==SPOOFING_REQUIRED)
3567         {
3568           plci->spoofed_msg = CALL_REQ | AWAITING_MANUF_CON;
3569           plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
3570           plci->command = 0;
3571           break;
3572         }
3573       }
3574       else if(req==LAW_REQ)
3575       {
3576         plci->cr_enquiry = true;
3577       }
3578       add_ss(plci,FTY,&m_parms[1]);
3579       sig_req(plci,req,0);
3580       send_req(plci);
3581       if(req==HANGUP)
3582       {      
3583         if (plci->NL.Id && !plci->nl_remove_id)
3584         {
3585           if (plci->channels)
3586           {
3587             for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
3588             {
3589               if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED))
3590               {
3591                 a->ncci_state[ncci] = OUTG_DIS_PENDING;
3592                 cleanup_ncci_data (plci, ncci);
3593                 nl_req_ncci(plci,N_DISC,(byte)ncci);
3594               }
3595             }
3596           }
3597           mixer_remove (plci);
3598           nl_req_ncci(plci,REMOVE,0);
3599           send_req(plci);
3600         }  
3601       }
3602       break;
3603
3604     case _DI_SIG_CTRL:
3605     /* signalling control for loop activation B-channel */
3606       if(!plci)
3607       {
3608         Info = _WRONG_IDENTIFIER;
3609         break;
3610       }
3611       if(m->length){
3612         plci->command = _MANUFACTURER_R;
3613         plci->number = Number;
3614         add_ss(plci,FTY,m);
3615         sig_req(plci,SIG_CTRL,0);
3616         send_req(plci);
3617       }
3618       else Info = _WRONG_MESSAGE_FORMAT;
3619       break;
3620
3621     case _DI_RXT_CTRL:
3622     /* activation control for receiver/transmitter B-channel */
3623       if(!plci)
3624       {
3625         Info = _WRONG_IDENTIFIER;
3626         break;
3627       }
3628       if(m->length){
3629         plci->command = _MANUFACTURER_R;
3630         plci->number = Number;
3631         add_ss(plci,FTY,m);
3632         sig_req(plci,DSP_CTRL,0);
3633         send_req(plci);
3634       }
3635       else Info = _WRONG_MESSAGE_FORMAT;
3636       break;
3637
3638     case _DI_ADV_CODEC:
3639     case _DI_DSP_CTRL:
3640       /* TEL_CTRL commands to support non standard adjustments: */
3641       /* Ring on/off, Handset micro volume, external micro vol. */
3642       /* handset+external speaker volume, receiver+transm. gain,*/
3643       /* handsfree on (hookinfo off), set mixer command         */
3644
3645       if(command == _DI_ADV_CODEC)
3646       {
3647         if(!a->AdvCodecPLCI) {
3648           Info = _WRONG_STATE;
3649           break;
3650         }
3651         v_plci = a->AdvCodecPLCI;
3652       }
3653       else
3654       {
3655         if (plci
3656          && (m->length >= 3)
3657          && (m->info[1] == 0x1c)
3658          && (m->info[2] >= 1))
3659         {
3660           if (m->info[3] == DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS)
3661           {
3662             if ((plci->tel != ADV_VOICE) || (plci != a->AdvSignalPLCI))
3663             {
3664               Info = _WRONG_STATE;
3665               break;
3666             }
3667             a->adv_voice_coef_length = m->info[2] - 1;
3668             if (a->adv_voice_coef_length > m->length - 3)
3669               a->adv_voice_coef_length = (byte)(m->length - 3);
3670             if (a->adv_voice_coef_length > ADV_VOICE_COEF_BUFFER_SIZE)
3671               a->adv_voice_coef_length = ADV_VOICE_COEF_BUFFER_SIZE;
3672             for (i = 0; i < a->adv_voice_coef_length; i++)
3673               a->adv_voice_coef_buffer[i] = m->info[4 + i];
3674             if (plci->B1_facilities & B1_FACILITY_VOICE)
3675               adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
3676             break;
3677           }
3678           else if (m->info[3] == DSP_CTRL_SET_DTMF_PARAMETERS)
3679           {
3680             if (!(a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_PARAMETERS))
3681             {
3682               Info = _FACILITY_NOT_SUPPORTED;
3683               break;
3684             }
3685
3686             plci->dtmf_parameter_length = m->info[2] - 1;
3687             if (plci->dtmf_parameter_length > m->length - 3)
3688               plci->dtmf_parameter_length = (byte)(m->length - 3);
3689             if (plci->dtmf_parameter_length > DTMF_PARAMETER_BUFFER_SIZE)
3690               plci->dtmf_parameter_length = DTMF_PARAMETER_BUFFER_SIZE;
3691             for (i = 0; i < plci->dtmf_parameter_length; i++)
3692               plci->dtmf_parameter_buffer[i] = m->info[4+i];
3693             if (plci->B1_facilities & B1_FACILITY_DTMFR)
3694               dtmf_parameter_write (plci);
3695             break;
3696
3697           }
3698         }
3699         v_plci = plci;
3700       }
3701
3702       if(!v_plci)
3703       {
3704         Info = _WRONG_IDENTIFIER;
3705         break;
3706       }
3707       if(m->length){
3708         add_ss(v_plci,FTY,m);
3709         sig_req(v_plci,TEL_CTRL,0);
3710         send_req(v_plci);
3711       }
3712       else Info = _WRONG_MESSAGE_FORMAT;
3713
3714       break;
3715
3716     case _DI_OPTIONS_REQUEST:
3717       if(api_parse(&m->info[1],(word)m->length,"d",m_parms)) {
3718         Info = _WRONG_MESSAGE_FORMAT;
3719         break;
3720       }
3721       if (GET_DWORD (m_parms[0].info) & ~a->man_profile.private_options)
3722       {
3723         Info = _FACILITY_NOT_SUPPORTED;
3724         break;
3725       }
3726       a->requested_options_table[appl->Id-1] = GET_DWORD (m_parms[0].info);
3727       break;
3728
3729
3730
3731     default:
3732       Info = _WRONG_MESSAGE_FORMAT;
3733       break;
3734     }
3735   }
3736
3737   sendf(appl,
3738         _MANUFACTURER_R|CONFIRM,
3739         Id,
3740         Number,
3741         "dww",_DI_MANU_ID,command,Info);
3742   return false;
3743 }
3744
3745
3746 byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
3747 {
3748   word indication;
3749
3750     API_PARSE m_parms[3];
3751   API_PARSE *ncpi;
3752     API_PARSE fax_parms[9];
3753   word i;
3754   byte len;
3755
3756
3757   dbug(1,dprintf("manufacturer_res"));
3758
3759   if ((msg[0].length == 0)
3760    || (msg[1].length == 0)
3761    || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
3762   {
3763     return false;
3764   }
3765   indication = GET_WORD(msg[1].info);
3766   switch (indication)
3767   {
3768
3769   case _DI_NEGOTIATE_B3:
3770     if(!plci)
3771       break;
3772     if (((plci->B3_prot != 4) && (plci->B3_prot != 5))
3773      || !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
3774     {
3775       dbug(1,dprintf("wrong state for NEGOTIATE_B3 parameters"));
3776       break;
3777     }
3778     if (api_parse (&msg[2].info[1], msg[2].length, "ws", m_parms))
3779     {
3780       dbug(1,dprintf("wrong format in NEGOTIATE_B3 parameters"));
3781       break;
3782     }
3783     ncpi = &m_parms[1];
3784     len = ((byte)(((T30_INFO *) 0)->station_id + 20));
3785     if (plci->fax_connect_info_length < len)
3786     {
3787       ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
3788       ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0;
3789     }
3790     if (api_parse (&ncpi->info[1], ncpi->length, "wwwwssss", fax_parms))
3791     {
3792       dbug(1,dprintf("non-standard facilities info missing or wrong format"));
3793     }
3794     else
3795     {
3796       if (plci->fax_connect_info_length <= len)
3797         plci->fax_connect_info_buffer[len] = 0;
3798       len += 1 + plci->fax_connect_info_buffer[len];
3799       if (plci->fax_connect_info_length <= len)
3800         plci->fax_connect_info_buffer[len] = 0;
3801       len += 1 + plci->fax_connect_info_buffer[len];
3802       if ((fax_parms[7].length >= 3) && (fax_parms[7].info[1] >= 2))
3803         plci->nsf_control_bits = GET_WORD(&fax_parms[7].info[2]);
3804       plci->fax_connect_info_buffer[len++] = (byte)(fax_parms[7].length);
3805       for (i = 0; i < fax_parms[7].length; i++)
3806         plci->fax_connect_info_buffer[len++] = fax_parms[7].info[1+i];
3807     }
3808     plci->fax_connect_info_length = len;
3809     plci->fax_edata_ack_length = plci->fax_connect_info_length;
3810     start_internal_command (Id, plci, fax_edata_ack_command);
3811     break;
3812
3813   }
3814   return false;
3815 }
3816
3817 /*------------------------------------------------------------------*/
3818 /* IDI callback function                                            */
3819 /*------------------------------------------------------------------*/
3820
3821 void   callback(ENTITY   * e)
3822 {
3823   DIVA_CAPI_ADAPTER   * a;
3824   APPL   * appl;
3825   PLCI   * plci;
3826   CAPI_MSG   *m;
3827   word i, j;
3828   byte rc;
3829   byte ch;
3830   byte req;
3831   byte global_req;
3832   int no_cancel_rc;
3833
3834   dbug(1,dprintf("%x:CB(%x:Req=%x,Rc=%x,Ind=%x)",
3835                  (e->user[0]+1)&0x7fff,e->Id,e->Req,e->Rc,e->Ind));
3836
3837   a = &(adapter[(byte)e->user[0]]);
3838   plci = &(a->plci[e->user[1]]);
3839   no_cancel_rc = DIVA_CAPI_SUPPORTS_NO_CANCEL(a);
3840
3841   /*
3842      If new protocol code and new XDI is used then CAPI should work
3843      fully in accordance with IDI cpec an look on callback field instead
3844      of Rc field for return codes.
3845    */
3846   if (((e->complete == 0xff) && no_cancel_rc) ||
3847       (e->Rc && !no_cancel_rc)) {
3848     rc = e->Rc;
3849     ch = e->RcCh;
3850     req = e->Req;
3851     e->Rc = 0;
3852
3853     if (e->user[0] & 0x8000)
3854     {
3855       /*
3856          If REMOVE request was sent then we have to wait until
3857          return code with Id set to zero arrives.
3858          All other return codes should be ignored.
3859          */
3860       if (req == REMOVE)
3861       {
3862         if (e->Id)
3863         {
3864           dbug(1,dprintf("cancel RC in REMOVE state"));
3865           return;
3866         }
3867         channel_flow_control_remove (plci);
3868         for (i = 0; i < 256; i++)
3869         {
3870           if (a->FlowControlIdTable[i] == plci->nl_remove_id)
3871             a->FlowControlIdTable[i] = 0;
3872         }
3873         plci->nl_remove_id = 0;
3874         if (plci->rx_dma_descriptor > 0) {
3875           diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3876           plci->rx_dma_descriptor = 0;
3877         }
3878       }
3879       if (rc == OK_FC)
3880       {
3881         a->FlowControlIdTable[ch] = e->Id;
3882         a->FlowControlSkipTable[ch] = 0;
3883
3884         a->ch_flow_control[ch] |= N_OK_FC_PENDING;
3885         a->ch_flow_plci[ch] = plci->Id;
3886         plci->nl_req = 0;
3887       }
3888       else
3889       {
3890         /*
3891           Cancel return codes self, if feature was requested
3892           */
3893         if (no_cancel_rc && (a->FlowControlIdTable[ch] == e->Id) && e->Id) {
3894           a->FlowControlIdTable[ch] = 0;
3895           if ((rc == OK) && a->FlowControlSkipTable[ch]) {
3896             dbug(3,dprintf ("XDI CAPI: RC cancelled Id:0x02, Ch:%02x",                              e->Id, ch));
3897             return;
3898           }
3899         }
3900
3901         if (a->ch_flow_control[ch] & N_OK_FC_PENDING)
3902         {
3903           a->ch_flow_control[ch] &= ~N_OK_FC_PENDING;
3904           if (ch == e->ReqCh)
3905             plci->nl_req = 0;
3906         }
3907         else
3908           plci->nl_req = 0;
3909       }
3910       if (plci->nl_req)
3911         control_rc (plci, 0, rc, ch, 0, true);
3912       else
3913       {
3914         if (req == N_XON)
3915         {
3916           channel_x_on (plci, ch);
3917           if (plci->internal_command)
3918             control_rc (plci, req, rc, ch, 0, true);
3919         }
3920         else
3921         {
3922           if (plci->nl_global_req)
3923           {
3924             global_req = plci->nl_global_req;
3925             plci->nl_global_req = 0;
3926             if (rc != ASSIGN_OK) {
3927               e->Id = 0;
3928               if (plci->rx_dma_descriptor > 0) {
3929                 diva_free_dma_descriptor (plci, plci->rx_dma_descriptor - 1);
3930                 plci->rx_dma_descriptor = 0;
3931               }
3932             }
3933             channel_xmit_xon (plci);
3934             control_rc (plci, 0, rc, ch, global_req, true);
3935           }
3936           else if (plci->data_sent)
3937           {
3938             channel_xmit_xon (plci);
3939             plci->data_sent = false;
3940             plci->NL.XNum = 1;
3941             data_rc (plci, ch);
3942             if (plci->internal_command)
3943               control_rc (plci, req, rc, ch, 0, true);
3944           }
3945           else
3946           {
3947             channel_xmit_xon (plci);
3948             control_rc (plci, req, rc, ch, 0, true);
3949           }
3950         }
3951       }
3952     }
3953     else
3954     {
3955       /*
3956          If REMOVE request was sent then we have to wait until
3957          return code with Id set to zero arrives.
3958          All other return codes should be ignored.
3959          */
3960       if (req == REMOVE)
3961       {
3962         if (e->Id)
3963         {
3964           dbug(1,dprintf("cancel RC in REMOVE state"));
3965           return;
3966         }
3967         plci->sig_remove_id = 0;
3968       }
3969       plci->sig_req = 0;
3970       if (plci->sig_global_req)
3971       {
3972         global_req = plci->sig_global_req;
3973         plci->sig_global_req = 0;
3974         if (rc != ASSIGN_OK)
3975           e->Id = 0;
3976         channel_xmit_xon (plci);
3977         control_rc (plci, 0, rc, ch, global_req, false);
3978       }
3979       else
3980       {
3981         channel_xmit_xon (plci);
3982         control_rc (plci, req, rc, ch, 0, false);
3983       }
3984     }
3985     /*
3986       Again: in accordance with IDI spec Rc and Ind can't be delivered in the
3987       same callback. Also if new XDI and protocol code used then jump
3988       direct to finish.
3989       */
3990     if (no_cancel_rc) {
3991       channel_xmit_xon(plci);
3992       goto capi_callback_suffix;
3993     }
3994   }
3995
3996   channel_xmit_xon(plci);
3997
3998   if (e->Ind) {
3999     if (e->user[0] &0x8000) {
4000       byte Ind = e->Ind & 0x0f;
4001       byte Ch = e->IndCh;
4002       if (((Ind==N_DISC) || (Ind==N_DISC_ACK)) &&
4003           (a->ch_flow_plci[Ch] == plci->Id)) {
4004         if (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK) {
4005           dbug(3,dprintf ("XDI CAPI: I: pending N-XON Ch:%02x", Ch));
4006         }
4007         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4008       }
4009       nl_ind(plci);
4010       if ((e->RNR != 1) &&
4011           (a->ch_flow_plci[Ch] == plci->Id) &&
4012           (a->ch_flow_control[Ch] & N_RX_FLOW_CONTROL_MASK)) {
4013         a->ch_flow_control[Ch] &= ~N_RX_FLOW_CONTROL_MASK;
4014         dbug(3,dprintf ("XDI CAPI: I: remove faked N-XON Ch:%02x", Ch));
4015       }
4016     } else {
4017       sig_ind(plci);
4018     }
4019     e->Ind = 0;
4020   }
4021
4022 capi_callback_suffix:
4023
4024   while (!plci->req_in
4025    && !plci->internal_command
4026    && (plci->msg_in_write_pos != plci->msg_in_read_pos))
4027   {
4028     j = (plci->msg_in_read_pos == plci->msg_in_wrap_pos) ? 0 : plci->msg_in_read_pos;
4029
4030     i = (((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]))->header.length + 3) & 0xfffc;
4031
4032     m = (CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[j]);
4033     appl = *((APPL   *   *)(&((byte   *)(plci->msg_in_queue))[j+i]));
4034     dbug(1,dprintf("dequeue msg(0x%04x) - write=%d read=%d wrap=%d",
4035       m->header.command, plci->msg_in_write_pos, plci->msg_in_read_pos, plci->msg_in_wrap_pos));
4036     if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4037     {
4038       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4039       plci->msg_in_read_pos = i + MSG_IN_OVERHEAD;
4040     }
4041     else
4042     {
4043       plci->msg_in_read_pos = j + i + MSG_IN_OVERHEAD;
4044     }
4045     if (plci->msg_in_read_pos == plci->msg_in_write_pos)
4046     {
4047       plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
4048       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4049     }
4050     else if (plci->msg_in_read_pos == plci->msg_in_wrap_pos)
4051     {
4052       plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
4053       plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
4054     }
4055     i = api_put (appl, m);
4056     if (i != 0)
4057     {
4058       if (m->header.command == _DATA_B3_R)
4059
4060         TransmitBufferFree (appl, (byte   *)(m->info.data_b3_req.Data));
4061
4062       dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
4063       break;
4064     }
4065
4066     if (plci->li_notify_update)
4067     {
4068       plci->li_notify_update = false;
4069       mixer_notify_update (plci, false);
4070     }
4071
4072   }
4073   send_data(plci);
4074   send_req(plci);
4075 }
4076
4077
4078 void control_rc(PLCI   * plci, byte req, byte rc, byte ch, byte global_req, byte nl_rc)
4079 {
4080   dword Id;
4081   dword rId;
4082   word Number;
4083   word Info=0;
4084   word i;
4085   word ncci;
4086   DIVA_CAPI_ADAPTER   * a;
4087   APPL   * appl;
4088   PLCI   * rplci;
4089     byte SSparms[]  = "\x05\x00\x00\x02\x00\x00";
4090     byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
4091
4092   if (!plci) {
4093     dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
4094     return;
4095   }
4096   dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
4097   if(plci->req_in!=plci->req_out)
4098   {
4099     if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
4100     {
4101       dbug(1,dprintf("req_1return"));
4102       return;
4103     }
4104     /* cancel outstanding request on the PLCI after SIG ASSIGN failure */
4105   }
4106   plci->req_in = plci->req_in_start = plci->req_out = 0;
4107   dbug(1,dprintf("control_rc"));
4108
4109   appl = plci->appl;
4110   a = plci->adapter;
4111   ncci = a->ch_ncci[ch];
4112   if(appl)
4113   {
4114     Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
4115     if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4116     Number = plci->number;
4117     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));
4118     dbug(1,dprintf("channels=0x%x",plci->channels));
4119     if (plci_remove_check(plci))
4120       return;
4121     if(req==REMOVE && rc==ASSIGN_OK)
4122     {
4123       sig_req(plci,HANGUP,0);
4124       sig_req(plci,REMOVE,0);
4125       send_req(plci);
4126     }
4127     if(plci->command)
4128     {
4129       switch(plci->command)
4130       {
4131       case C_HOLD_REQ:
4132         dbug(1,dprintf("HoldRC=0x%x",rc));
4133         SSparms[1] = (byte)S_HOLD;
4134         if(rc!=OK)
4135         {
4136           plci->SuppState = IDLE;
4137           Info = 0x2001;
4138         }
4139         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4140         break;
4141
4142       case C_RETRIEVE_REQ:
4143         dbug(1,dprintf("RetrieveRC=0x%x",rc));
4144         SSparms[1] = (byte)S_RETRIEVE;
4145         if(rc!=OK)
4146         {
4147           plci->SuppState = CALL_HELD;
4148           Info = 0x2001;
4149         }
4150         sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
4151         break;
4152
4153       case _INFO_R:
4154         dbug(1,dprintf("InfoRC=0x%x",rc));
4155         if(rc!=OK) Info=_WRONG_STATE;
4156         sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
4157         break;
4158
4159       case _CONNECT_R:
4160         dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
4161         if (plci->State == INC_DIS_PENDING)
4162           break;
4163         if(plci->Sig.Id!=0xff)
4164         {
4165           if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
4166            || (!nl_rc && (req == CALL_REQ) && (rc != OK)))
4167           {
4168             dbug(1,dprintf("No more IDs/Call_Req failed"));
4169             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4170             plci_remove(plci);
4171             plci->State = IDLE;
4172             break;
4173           }
4174           if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
4175           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4176         }
4177         else /* D-ch activation */
4178         {
4179           if (rc != ASSIGN_OK)
4180           {
4181             dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
4182             sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4183             plci_remove(plci);
4184             plci->State = IDLE;
4185             break;
4186           }
4187           sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
4188           sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
4189           plci->State = INC_ACT_PENDING;
4190         }
4191         break;
4192
4193       case _CONNECT_I|RESPONSE:
4194         if (plci->State != INC_DIS_PENDING)
4195           plci->State = INC_CON_ACCEPT;
4196         break;
4197
4198       case _DISCONNECT_R:
4199         if (plci->State == INC_DIS_PENDING)
4200           break;
4201         if(plci->Sig.Id!=0xff)
4202         {
4203           plci->State = OUTG_DIS_PENDING;
4204           sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
4205         }
4206         break;
4207
4208       case SUSPEND_REQ:
4209         break;
4210
4211       case RESUME_REQ:
4212         break;
4213
4214       case _CONNECT_B3_R:
4215         if(rc!=OK)
4216         {
4217           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
4218           break;
4219         }
4220         ncci = get_ncci (plci, ch, 0);
4221         Id = (Id & 0xffff) | (((dword) ncci) << 16);
4222         plci->channels++;
4223         if(req==N_RESET)
4224         {
4225           a->ncci_state[ncci] = INC_ACT_PENDING;
4226           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4227           sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
4228         }
4229         else
4230         {
4231           a->ncci_state[ncci] = OUTG_CON_PENDING;
4232           sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4233         }
4234         break;
4235
4236       case _CONNECT_B3_I|RESPONSE:
4237         break;
4238
4239       case _RESET_B3_R:
4240 /*        sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
4241         break;
4242
4243       case _DISCONNECT_B3_R:
4244         sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
4245         break;
4246
4247       case _MANUFACTURER_R:
4248         break;
4249
4250       case PERM_LIST_REQ:
4251         if(rc!=OK)
4252         {
4253           Info = _WRONG_IDENTIFIER;
4254           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4255           plci_remove(plci);
4256         }
4257         else
4258           sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
4259         break;
4260
4261       default:
4262         break;
4263       }
4264       plci->command = 0;
4265     }
4266     else if (plci->internal_command)
4267     {
4268       switch(plci->internal_command)
4269       {
4270       case BLOCK_PLCI:
4271         return;
4272
4273       case GET_MWI_STATE:
4274         if(rc==OK) /* command supported, wait for indication */
4275         {
4276           return;
4277         }
4278         plci_remove(plci);
4279         break;
4280
4281         /* Get Supported Services */
4282       case GETSERV_REQ_PEND:
4283         if(rc==OK) /* command supported, wait for indication */
4284         {
4285           break;
4286         }
4287         PUT_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
4288         sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
4289         plci_remove(plci);
4290         break;
4291
4292       case INTERR_DIVERSION_REQ_PEND:      /* Interrogate Parameters        */
4293       case INTERR_NUMBERS_REQ_PEND:
4294       case CF_START_PEND:                  /* Call Forwarding Start pending */
4295       case CF_STOP_PEND:                   /* Call Forwarding Stop pending  */
4296       case CCBS_REQUEST_REQ_PEND:
4297       case CCBS_DEACTIVATE_REQ_PEND:
4298       case CCBS_INTERROGATE_REQ_PEND:
4299         switch(plci->internal_command)
4300         {
4301           case INTERR_DIVERSION_REQ_PEND:
4302             SSparms[1] = S_INTERROGATE_DIVERSION;
4303             break;
4304           case INTERR_NUMBERS_REQ_PEND:
4305             SSparms[1] = S_INTERROGATE_NUMBERS;
4306             break;
4307           case CF_START_PEND:
4308             SSparms[1] = S_CALL_FORWARDING_START;
4309             break;
4310           case CF_STOP_PEND:
4311             SSparms[1] = S_CALL_FORWARDING_STOP;
4312             break;
4313           case CCBS_REQUEST_REQ_PEND:
4314             SSparms[1] = S_CCBS_REQUEST;
4315             break;
4316           case CCBS_DEACTIVATE_REQ_PEND:
4317             SSparms[1] = S_CCBS_DEACTIVATE;
4318             break;
4319           case CCBS_INTERROGATE_REQ_PEND:
4320             SSparms[1] = S_CCBS_INTERROGATE;
4321             break;
4322         }
4323         if(global_req==ASSIGN)
4324         {
4325           dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
4326           return;
4327         }
4328         if(!plci->appl) break;
4329         if(rc==ISDN_GUARD_REJ)
4330         {
4331           Info = _CAPI_GUARD_ERROR;
4332         }
4333         else if(rc!=OK)
4334         {
4335           Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
4336         }
4337         sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
4338               plci->number,"wws",Info,(word)3,SSparms);
4339         if(Info) plci_remove(plci);
4340         break;
4341
4342         /* 3pty conference pending */
4343       case PTY_REQ_PEND:
4344         if(!plci->relatedPTYPLCI) break;
4345         rplci = plci->relatedPTYPLCI;
4346         SSparms[1] = plci->ptyState;
4347         rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4348         if(rplci->tel) rId|=EXT_CONTROLLER;
4349         if(rc!=OK)
4350         {
4351           Info = 0x300E; /* not supported */
4352           plci->relatedPTYPLCI = NULL;
4353           plci->ptyState = 0;
4354         }
4355         sendf(rplci->appl,
4356               _FACILITY_R|CONFIRM,
4357               rId,
4358               plci->number,
4359               "wws",Info,(word)3,SSparms);
4360         break;
4361
4362         /* Explicit Call Transfer pending */
4363       case ECT_REQ_PEND:
4364         dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
4365         if(!plci->relatedPTYPLCI) break;
4366         rplci = plci->relatedPTYPLCI;
4367         SSparms[1] = S_ECT;
4368         rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4369         if(rplci->tel) rId|=EXT_CONTROLLER;
4370         if(rc!=OK)
4371         {
4372           Info = 0x300E; /* not supported */
4373           plci->relatedPTYPLCI = NULL;
4374           plci->ptyState = 0;
4375         }
4376         sendf(rplci->appl,
4377               _FACILITY_R|CONFIRM,
4378               rId,
4379               plci->number,
4380               "wws",Info,(word)3,SSparms);
4381         break;
4382
4383       case _MANUFACTURER_R:
4384         dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
4385         if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4386         {
4387           dbug(1,dprintf("No more IDs"));
4388           sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
4389           plci_remove(plci);  /* after codec init, internal codec commands pending */
4390         }
4391         break;
4392
4393       case _CONNECT_R:
4394         dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
4395         if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
4396         {
4397           dbug(1,dprintf("No more IDs"));
4398           sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
4399           plci_remove(plci);  /* after codec init, internal codec commands pending */
4400         }
4401         break;
4402
4403       case PERM_COD_HOOK:                     /* finished with Hook_Ind */
4404         return;
4405
4406       case PERM_COD_CALL:
4407         dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
4408         plci->internal_command = PERM_COD_CONN_PEND;
4409         return;
4410
4411       case PERM_COD_ASSIGN:
4412         dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
4413         if(rc!=ASSIGN_OK) break;
4414         sig_req(plci,CALL_REQ,0);
4415         send_req(plci);
4416         plci->internal_command = PERM_COD_CALL;
4417         return;
4418
4419         /* Null Call Reference Request pending */
4420       case C_NCR_FAC_REQ:
4421         dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
4422         if(global_req==ASSIGN)
4423         {
4424           if(rc==ASSIGN_OK)
4425           {
4426             return;
4427           }
4428           else
4429           {
4430             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4431             appl->NullCREnable = false;
4432             plci_remove(plci);
4433           }
4434         }
4435         else if(req==NCR_FACILITY)
4436         {
4437           if(rc==OK)
4438           {
4439             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
4440           }
4441           else
4442           {
4443             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
4444             appl->NullCREnable = false;
4445           }
4446           plci_remove(plci);
4447         }
4448         break;
4449
4450       case HOOK_ON_REQ:
4451         if(plci->channels)
4452         {
4453           if(a->ncci_state[ncci]==CONNECTED)
4454           {
4455             a->ncci_state[ncci] = OUTG_DIS_PENDING;
4456             cleanup_ncci_data (plci, ncci);
4457             nl_req_ncci(plci,N_DISC,(byte)ncci);
4458           }
4459           break;
4460         }
4461         break;
4462
4463       case HOOK_OFF_REQ:
4464         if (plci->State == INC_DIS_PENDING)
4465           break;
4466         sig_req(plci,CALL_REQ,0);
4467         send_req(plci);
4468         plci->State=OUTG_CON_PENDING;
4469         break;
4470
4471
4472       case MWI_ACTIVATE_REQ_PEND:
4473       case MWI_DEACTIVATE_REQ_PEND:
4474         if(global_req == ASSIGN && rc==ASSIGN_OK)
4475         {
4476           dbug(1,dprintf("MWI_REQ assigned"));
4477           return;
4478         }
4479         else if(rc!=OK)
4480         {                 
4481           if(rc==WRONG_IE)
4482           {
4483             Info = 0x2007; /* Illegal message parameter coding */
4484             dbug(1,dprintf("MWI_REQ invalid parameter"));
4485           }
4486           else
4487           {
4488             Info = 0x300B; /* not supported */                      
4489             dbug(1,dprintf("MWI_REQ not supported"));
4490           }
4491           /* 0x3010: Request not allowed in this state */
4492           PUT_WORD(&SSparms[4],0x300E); /* SS not supported */
4493                     
4494         }
4495         if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
4496         {
4497           PUT_WORD(&SSparms[1],S_MWI_ACTIVATE);
4498         }
4499         else PUT_WORD(&SSparms[1],S_MWI_DEACTIVATE);
4500
4501         if(plci->cr_enquiry)
4502         {
4503           sendf(plci->appl,
4504                 _FACILITY_R|CONFIRM,
4505                 Id&0xf,
4506                 plci->number,
4507                 "wws",Info,(word)3,SSparms);
4508           if(rc!=OK) plci_remove(plci);
4509         }
4510         else
4511         {
4512           sendf(plci->appl,
4513                 _FACILITY_R|CONFIRM,
4514                 Id,
4515                 plci->number,
4516                 "wws",Info,(word)3,SSparms);
4517         }
4518         break;
4519
4520       case CONF_BEGIN_REQ_PEND:
4521       case CONF_ADD_REQ_PEND:
4522       case CONF_SPLIT_REQ_PEND:
4523       case CONF_DROP_REQ_PEND:
4524       case CONF_ISOLATE_REQ_PEND:
4525       case CONF_REATTACH_REQ_PEND:
4526         dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
4527         if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
4528         rplci = plci;
4529         rId = Id;
4530         switch(plci->internal_command)
4531         {
4532           case CONF_BEGIN_REQ_PEND:
4533             SSparms[1] = S_CONF_BEGIN;
4534             break;
4535           case CONF_ADD_REQ_PEND:
4536             SSparms[1] = S_CONF_ADD;
4537             rplci = plci->relatedPTYPLCI;
4538             rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
4539             break;
4540           case CONF_SPLIT_REQ_PEND:
4541             SSparms[1] = S_CONF_SPLIT;
4542             break;
4543           case CONF_DROP_REQ_PEND:
4544             SSparms[1] = S_CONF_DROP;
4545             break;
4546           case CONF_ISOLATE_REQ_PEND:
4547             SSparms[1] = S_CONF_ISOLATE;
4548             break;
4549           case CONF_REATTACH_REQ_PEND:
4550             SSparms[1] = S_CONF_REATTACH;
4551             break;
4552         }
4553         
4554         if(rc!=OK)
4555         {
4556           Info = 0x300E; /* not supported */
4557           plci->relatedPTYPLCI = NULL;
4558           plci->ptyState = 0;
4559         }
4560         sendf(rplci->appl,
4561               _FACILITY_R|CONFIRM,
4562               rId,
4563               plci->number,
4564               "wws",Info,(word)3,SSparms);
4565         break;
4566
4567       case VSWITCH_REQ_PEND:
4568         if(rc!=OK)
4569         {
4570           if(plci->relatedPTYPLCI)
4571           {
4572             plci->relatedPTYPLCI->vswitchstate=0;
4573             plci->relatedPTYPLCI->vsprot=0;
4574             plci->relatedPTYPLCI->vsprotdialect=0;    
4575           }
4576           plci->vswitchstate=0;
4577           plci->vsprot=0;
4578           plci->vsprotdialect=0;
4579         }
4580         else
4581         {
4582           if(plci->relatedPTYPLCI &&
4583              plci->vswitchstate==1 &&
4584              plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
4585             plci->vswitchstate=3;
4586         }
4587         break;
4588
4589   /* Call Deflection Request pending (SSCT) */
4590       case CD_REQ_PEND:
4591         SSparms[1] = S_CALL_DEFLECTION;
4592         if(rc!=OK)
4593         {
4594           Info = 0x300E; /* not supported */
4595           plci->appl->CDEnable = 0;
4596         }  
4597         sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
4598           plci->number,"wws",Info,(word)3,SSparms);
4599         break;
4600
4601       case RTP_CONNECT_B3_REQ_COMMAND_2:
4602         if (rc == OK)
4603         {
4604           ncci = get_ncci (plci, ch, 0);
4605           Id = (Id & 0xffff) | (((dword) ncci) << 16);
4606           plci->channels++;
4607           a->ncci_state[ncci] = OUTG_CON_PENDING;
4608         }
4609
4610       default:
4611         if (plci->internal_command_queue[0])
4612         {
4613           (*(plci->internal_command_queue[0]))(Id, plci, rc);
4614           if (plci->internal_command)
4615             return;
4616         }
4617         break;
4618       }
4619       next_internal_command (Id, plci);
4620     }
4621   }
4622   else /* appl==0 */
4623   {
4624     Id = ((word)plci->Id<<8)|plci->adapter->Id;
4625     if(plci->tel) Id|=EXT_CONTROLLER;
4626
4627     switch(plci->internal_command)
4628     {
4629     case BLOCK_PLCI:
4630       return;
4631
4632     case START_L1_SIG_ASSIGN_PEND:
4633     case REM_L1_SIG_ASSIGN_PEND:
4634       if(global_req == ASSIGN)
4635       {
4636         break;
4637       }
4638       else
4639       {
4640         dbug(1,dprintf("***L1 Req rem PLCI"));
4641         plci->internal_command = 0;
4642         sig_req(plci,REMOVE,0);
4643         send_req(plci);
4644       }
4645       break;
4646
4647       /* Call Deflection Request pending, just no appl ptr assigned */
4648     case CD_REQ_PEND:
4649       SSparms[1] = S_CALL_DEFLECTION;
4650       if(rc!=OK)
4651       {
4652         Info = 0x300E; /* not supported */
4653       }
4654       for(i=0; i<max_appl; i++)
4655       {
4656         if(application[i].CDEnable)
4657         {
4658           if(!application[i].Id) application[i].CDEnable = 0;
4659           else
4660           {
4661             sendf(&application[i],_FACILITY_R|CONFIRM,Id,
4662                   plci->number,"wws",Info,(word)3,SSparms);
4663             if(Info) application[i].CDEnable = 0;
4664           }
4665         }
4666       }
4667       plci->internal_command = 0;
4668       break;
4669
4670     case PERM_COD_HOOK:                   /* finished with Hook_Ind */
4671       return;
4672
4673     case PERM_COD_CALL:
4674       plci->internal_command = PERM_COD_CONN_PEND;
4675       dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
4676       return;
4677
4678     case PERM_COD_ASSIGN:
4679       dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
4680       plci->internal_command = 0;
4681       if(rc!=ASSIGN_OK) break;
4682       plci->internal_command = PERM_COD_CALL;
4683       sig_req(plci,CALL_REQ,0);
4684       send_req(plci);
4685       return;
4686
4687     case LISTEN_SIG_ASSIGN_PEND:
4688       if(rc == ASSIGN_OK)
4689       {
4690         plci->internal_command = 0;
4691         dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
4692         add_p(plci,ESC,"\x02\x18\x00");             /* support call waiting */
4693         sig_req(plci,INDICATE_REQ,0);
4694         send_req(plci);
4695       }
4696       else
4697       {
4698         dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
4699         a->listen_active--;
4700         plci_remove(plci);
4701         plci->State = IDLE;
4702       }
4703       break;
4704
4705     case USELAW_REQ:
4706       if(global_req == ASSIGN)
4707       {
4708         if (rc==ASSIGN_OK)
4709       {
4710         sig_req(plci,LAW_REQ,0);
4711         send_req(plci);
4712         dbug(1,dprintf("Auto-Law assigned"));
4713         }
4714         else
4715         {
4716           dbug(1,dprintf("Auto-Law assign failed"));
4717           a->automatic_law = 3;
4718           plci->internal_command = 0;
4719           a->automatic_lawPLCI = NULL;
4720         }
4721         break;
4722       }
4723       else if(req == LAW_REQ && rc==OK)
4724       {
4725         dbug(1,dprintf("Auto-Law initiated"));
4726         a->automatic_law = 2;
4727         plci->internal_command = 0;
4728       }
4729       else
4730       {
4731         dbug(1,dprintf("Auto-Law not supported"));
4732         a->automatic_law = 3;
4733         plci->internal_command = 0;
4734         sig_req(plci,REMOVE,0);
4735         send_req(plci);
4736         a->automatic_lawPLCI = NULL;
4737       }
4738       break;
4739     }
4740     plci_remove_check(plci);
4741   }
4742 }
4743
4744 void data_rc(PLCI   * plci, byte ch)
4745 {
4746   dword Id;
4747   DIVA_CAPI_ADAPTER   * a;
4748   NCCI   *ncci_ptr;
4749   DATA_B3_DESC   *data;
4750   word ncci;
4751
4752   if (plci->appl)
4753   {
4754     TransmitBufferFree (plci->appl, plci->data_sent_ptr);
4755     a = plci->adapter;
4756     ncci = a->ch_ncci[ch];
4757     if (ncci && (a->ncci_plci[ncci] == plci->Id))
4758     {
4759       ncci_ptr = &(a->ncci[ncci]);
4760       dbug(1,dprintf("data_out=%d, data_pending=%d",ncci_ptr->data_out,ncci_ptr->data_pending));
4761       if (ncci_ptr->data_pending)
4762       {
4763         data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
4764         if (!(data->Flags &4) && a->ncci_state[ncci])
4765         {
4766           Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4767           if(plci->tel) Id|=EXT_CONTROLLER;
4768           sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,data->Number,
4769                 "ww",data->Handle,0);
4770         }
4771         (ncci_ptr->data_out)++;
4772         if (ncci_ptr->data_out == MAX_DATA_B3)
4773           ncci_ptr->data_out = 0;
4774         (ncci_ptr->data_pending)--;
4775       }
4776     }
4777   }
4778 }
4779
4780 void data_ack(PLCI   * plci, byte ch)
4781 {
4782   dword Id;
4783   DIVA_CAPI_ADAPTER   * a;
4784   NCCI   *ncci_ptr;
4785   word ncci;
4786
4787   a = plci->adapter;
4788   ncci = a->ch_ncci[ch];
4789   ncci_ptr = &(a->ncci[ncci]);
4790   if (ncci_ptr->data_ack_pending)
4791   {
4792     if (a->ncci_state[ncci] && (a->ncci_plci[ncci] == plci->Id))
4793     {
4794       Id = (((dword)ncci)<<16)|((word)plci->Id<<8)|a->Id;
4795       if(plci->tel) Id|=EXT_CONTROLLER;
4796       sendf(plci->appl,_DATA_B3_R|CONFIRM,Id,ncci_ptr->DataAck[ncci_ptr->data_ack_out].Number,
4797             "ww",ncci_ptr->DataAck[ncci_ptr->data_ack_out].Handle,0);
4798     }
4799     (ncci_ptr->data_ack_out)++;
4800     if (ncci_ptr->data_ack_out == MAX_DATA_ACK)
4801       ncci_ptr->data_ack_out = 0;
4802     (ncci_ptr->data_ack_pending)--;
4803   }
4804 }
4805
4806 void sig_ind(PLCI   * plci)
4807 {
4808   dword x_Id;
4809   dword Id;
4810   dword rId;
4811   word Number = 0;
4812   word i;
4813   word cip;
4814   dword cip_mask;
4815   byte   *ie;
4816   DIVA_CAPI_ADAPTER   * a;
4817     API_PARSE saved_parms[MAX_MSG_PARMS+1];
4818 #define MAXPARMSIDS 31
4819     byte   * parms[MAXPARMSIDS];
4820     byte   * add_i[4];
4821     byte   * multi_fac_parms[MAX_MULTI_IE];
4822     byte   * multi_pi_parms [MAX_MULTI_IE];
4823     byte   * multi_ssext_parms [MAX_MULTI_IE];
4824     byte   * multi_CiPN_parms [MAX_MULTI_IE];
4825
4826     byte   * multi_vswitch_parms [MAX_MULTI_IE];
4827
4828   byte ai_len;
4829     byte   *esc_chi = "";
4830     byte   *esc_law = "";
4831     byte   *pty_cai = "";
4832     byte   *esc_cr  = "";
4833     byte   *esc_profile = "";
4834
4835     byte facility[256];
4836   PLCI   * tplci = NULL;
4837   byte chi[] = "\x02\x18\x01";
4838   byte voice_cai[]  = "\x06\x14\x00\x00\x00\x00\x08";
4839     byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
4840   /* ESC_MSGTYPE must be the last but one message, a new IE has to be */
4841   /* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
4842   /* SMSG is situated at the end because its 0 (for compatibility reasons */
4843   /* (see Info_Mask Bit 4, first IE. then the message type)           */
4844     word parms_id[] =
4845          {MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
4846           UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
4847           RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
4848           CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
4849           /* 14 FTY repl by ESC_CHI */
4850           /* 18 PI  repl by ESC_LAW */
4851          /* removed OAD changed to 0xff for future use, OAD is multiIE now */
4852      word multi_fac_id[] = {1, FTY};
4853      word multi_pi_id[]  = {1, PI};
4854      word multi_CiPN_id[]  = {1, OAD};
4855      word multi_ssext_id[]  = {1, ESC_SSEXT};
4856
4857      word multi_vswitch_id[]  = {1, ESC_VSWITCH};
4858
4859   byte   * cau;
4860   word ncci;
4861     byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
4862     byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
4863     byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
4864     byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
4865   byte force_mt_info = false;
4866   byte dir;
4867   dword d;
4868   word w;
4869
4870   a = plci->adapter;
4871   Id = ((word)plci->Id<<8)|a->Id;
4872   PUT_WORD(&SS_Ind[4],0x0000);
4873
4874   if (plci->sig_remove_id)
4875   {
4876     plci->Sig.RNR = 2; /* discard */
4877     dbug(1,dprintf("SIG discard while remove pending"));
4878     return;
4879   }
4880   if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
4881   dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
4882     Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
4883   if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
4884   {
4885     plci->Sig.RNR = 1;
4886     return;
4887   }
4888   if(plci->Sig.Ind==HANGUP && plci->channels)
4889   {
4890     plci->Sig.RNR = 1;
4891     plci->hangup_flow_ctrl_timer++;
4892     /* recover the network layer after timeout */
4893     if(plci->hangup_flow_ctrl_timer==100)
4894     {
4895       dbug(1,dprintf("Exceptional disc"));
4896       plci->Sig.RNR = 0;
4897       plci->hangup_flow_ctrl_timer = 0;
4898       for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
4899       {
4900         if (a->ncci_plci[ncci] == plci->Id)
4901         {
4902           cleanup_ncci_data (plci, ncci);
4903           if(plci->channels)plci->channels--;
4904           if (plci->appl)
4905             sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
4906         }
4907       }
4908       if (plci->appl)
4909         sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
4910       plci_remove(plci);
4911       plci->State=IDLE;
4912     }
4913     return;
4914   }
4915
4916   /* do first parse the info with no OAD in, because OAD will be converted */
4917   /* first the multiple facility IE, then mult. progress ind.              */
4918   /* then the parameters for the info_ind + conn_ind                       */
4919   IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
4920   IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
4921   IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
4922
4923   IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
4924
4925   IndParse(plci,parms_id,parms,0);
4926   IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
4927   esc_chi  = parms[14];
4928   esc_law  = parms[18];
4929   pty_cai  = parms[24];
4930   esc_cr   = parms[25];
4931   esc_profile = parms[27];
4932   if(esc_cr[0] && plci)
4933   {
4934     if(plci->cr_enquiry && plci->appl)
4935     {
4936       plci->cr_enquiry = false;
4937       /* d = MANU_ID            */
4938       /* w = m_command          */
4939       /* b = total length       */
4940       /* b = indication type    */
4941       /* b = length of all IEs  */
4942       /* b = IE1                */
4943       /* S = IE1 length + cont. */
4944       /* b = IE2                */
4945       /* S = IE2 lenght + cont. */
4946       sendf(plci->appl,
4947         _MANUFACTURER_I,
4948         Id,
4949         0,
4950         "dwbbbbSbS",_DI_MANU_ID,plci->m_command,
4951         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);
4952     }
4953   }
4954   /* create the additional info structure                                  */
4955   add_i[1] = parms[15]; /* KEY of additional info */
4956   add_i[2] = parms[11]; /* UUI of additional info */
4957   ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
4958
4959   /* the ESC_LAW indicates if u-Law or a-Law is actually used by the card  */
4960   /* indication returns by the card if requested by the function           */
4961   /* AutomaticLaw() after driver init                                      */
4962   if (a->automatic_law<4)
4963   {
4964     if(esc_law[0]){
4965       if(esc_law[2]){
4966         dbug(0,dprintf("u-Law selected"));
4967         a->u_law = 1;
4968       }
4969       else {
4970         dbug(0,dprintf("a-Law selected"));
4971         a->u_law = 0;
4972       }
4973       a->automatic_law = 4;
4974       if(plci==a->automatic_lawPLCI) {
4975         plci->internal_command = 0;
4976         sig_req(plci,REMOVE,0);
4977         send_req(plci);
4978         a->automatic_lawPLCI = NULL;
4979       }
4980     }
4981     if (esc_profile[0])
4982     {
4983       dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
4984         UnMapController (a->Id), GET_DWORD (&esc_profile[6]),
4985         GET_DWORD (&esc_profile[10]), GET_DWORD (&esc_profile[14]),
4986         GET_DWORD (&esc_profile[18]), GET_DWORD (&esc_profile[46])));
4987
4988       a->profile.Global_Options &= 0x000000ffL;
4989       a->profile.B1_Protocols &= 0x000003ffL;
4990       a->profile.B2_Protocols &= 0x00001fdfL;
4991       a->profile.B3_Protocols &= 0x000000b7L;
4992
4993       a->profile.Global_Options &= GET_DWORD (&esc_profile[6]) |
4994         GL_BCHANNEL_OPERATION_SUPPORTED;
4995       a->profile.B1_Protocols &= GET_DWORD (&esc_profile[10]);
4996       a->profile.B2_Protocols &= GET_DWORD (&esc_profile[14]);
4997       a->profile.B3_Protocols &= GET_DWORD (&esc_profile[18]);
4998       a->manufacturer_features = GET_DWORD (&esc_profile[46]);
4999       a->man_profile.private_options = 0;
5000
5001       if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
5002       {
5003         a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
5004         a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
5005       }
5006
5007
5008       if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
5009         a->man_profile.private_options |= 1L << PRIVATE_RTP;
5010       a->man_profile.rtp_primary_payloads = GET_DWORD (&esc_profile[50]);
5011       a->man_profile.rtp_additional_payloads = GET_DWORD (&esc_profile[54]);
5012
5013
5014       if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
5015         a->man_profile.private_options |= 1L << PRIVATE_T38;
5016
5017
5018       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
5019         a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
5020
5021
5022       if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
5023         a->man_profile.private_options |= 1L << PRIVATE_V18;
5024
5025
5026       if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
5027         a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
5028
5029
5030       if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
5031         a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
5032
5033
5034       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
5035         a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
5036
5037
5038       if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
5039         a->man_profile.private_options |= 1L << PRIVATE_VOWN;
5040
5041
5042       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
5043         a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
5044
5045     }
5046     else
5047     {
5048       a->profile.Global_Options &= 0x0000007fL;
5049       a->profile.B1_Protocols &= 0x000003dfL;
5050       a->profile.B2_Protocols &= 0x00001adfL;
5051       a->profile.B3_Protocols &= 0x000000b7L;
5052       a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
5053     }
5054     if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
5055       MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
5056     {
5057       a->profile.Global_Options |= GL_DTMF_SUPPORTED;
5058     }
5059     a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
5060     dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
5061       UnMapController (a->Id), a->profile.Global_Options,
5062       a->profile.B1_Protocols, a->profile.B2_Protocols,
5063       a->profile.B3_Protocols, a->manufacturer_features));
5064   }
5065   /* codec plci for the handset/hook state support is just an internal id  */
5066   if(plci!=a->AdvCodecPLCI)
5067   {
5068     force_mt_info =  SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
5069     force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
5070     SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
5071     SendInfo(plci,Id, parms, force_mt_info);
5072
5073     VSwitchReqInd(plci,Id,multi_vswitch_parms);
5074
5075   }
5076
5077   /* switch the codec to the b-channel                                     */
5078   if(esc_chi[0] && plci && !plci->SuppState){
5079     plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5080     mixer_set_bchannel_id_esc (plci, plci->b_channel);
5081     dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
5082     if(plci->tel==ADV_VOICE && plci->appl) {
5083       SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5084     }
5085   }
5086
5087   if(plci->appl) Number = plci->appl->Number++;
5088
5089   switch(plci->Sig.Ind) {
5090   /* Response to Get_Supported_Services request */
5091   case S_SUPPORTED:
5092     dbug(1,dprintf("S_Supported"));
5093     if(!plci->appl) break;
5094     if(pty_cai[0]==4)
5095     {
5096       PUT_DWORD(&CF_Ind[6],GET_DWORD(&pty_cai[1]) );
5097     }
5098     else
5099     {
5100       PUT_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
5101     }
5102     PUT_WORD (&CF_Ind[1], 0);
5103     PUT_WORD (&CF_Ind[4], 0);
5104     sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
5105     plci_remove(plci);
5106     break;
5107                     
5108   /* Supplementary Service rejected */
5109   case S_SERVICE_REJ:
5110     dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
5111     if(!pty_cai[0]) break;
5112     switch (pty_cai[5])
5113     {
5114     case ECT_EXECUTE:
5115     case THREE_PTY_END:
5116     case THREE_PTY_BEGIN:
5117       if(!plci->relatedPTYPLCI) break;
5118       tplci = plci->relatedPTYPLCI;
5119       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5120       if(tplci->tel) rId|=EXT_CONTROLLER;
5121       if(pty_cai[5]==ECT_EXECUTE)
5122       {
5123         PUT_WORD(&SS_Ind[1],S_ECT);
5124
5125         plci->vswitchstate=0;
5126         plci->relatedPTYPLCI->vswitchstate=0;
5127
5128       }
5129       else
5130       {
5131         PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5132       }
5133       if(pty_cai[2]!=0xff)
5134       {
5135         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5136       }
5137       else
5138       {
5139         PUT_WORD(&SS_Ind[4],0x300E);
5140       }
5141       plci->relatedPTYPLCI = NULL;
5142       plci->ptyState = 0;
5143       sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5144       break;
5145
5146     case CALL_DEFLECTION:
5147       if(pty_cai[2]!=0xff)
5148       {
5149         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5150       }
5151       else
5152       {
5153         PUT_WORD(&SS_Ind[4],0x300E);
5154       }
5155       PUT_WORD(&SS_Ind[1],pty_cai[5]);
5156       for(i=0; i<max_appl; i++)
5157       {
5158         if(application[i].CDEnable)
5159         {
5160           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5161           application[i].CDEnable = false;
5162         }
5163       }
5164       break;
5165
5166     case DEACTIVATION_DIVERSION:
5167     case ACTIVATION_DIVERSION:
5168     case DIVERSION_INTERROGATE_CFU:
5169     case DIVERSION_INTERROGATE_CFB:
5170     case DIVERSION_INTERROGATE_CFNR:
5171     case DIVERSION_INTERROGATE_NUM:
5172     case CCBS_REQUEST:
5173     case CCBS_DEACTIVATE:
5174     case CCBS_INTERROGATE:
5175       if(!plci->appl) break;
5176       if(pty_cai[2]!=0xff)
5177       {
5178         PUT_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
5179       }
5180       else
5181       {
5182         PUT_WORD(&Interr_Err_Ind[4],0x300E);
5183       }
5184       switch (pty_cai[5])
5185       {
5186         case DEACTIVATION_DIVERSION:
5187           dbug(1,dprintf("Deact_Div"));
5188           Interr_Err_Ind[0]=0x9;
5189           Interr_Err_Ind[3]=0x6;
5190           PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
5191           break;
5192         case ACTIVATION_DIVERSION:
5193           dbug(1,dprintf("Act_Div"));
5194           Interr_Err_Ind[0]=0x9;
5195           Interr_Err_Ind[3]=0x6;
5196           PUT_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
5197           break;
5198         case DIVERSION_INTERROGATE_CFU:
5199         case DIVERSION_INTERROGATE_CFB:
5200         case DIVERSION_INTERROGATE_CFNR:
5201           dbug(1,dprintf("Interr_Div"));
5202           Interr_Err_Ind[0]=0xa;
5203           Interr_Err_Ind[3]=0x7;
5204           PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
5205           break;
5206         case DIVERSION_INTERROGATE_NUM:
5207           dbug(1,dprintf("Interr_Num"));
5208           Interr_Err_Ind[0]=0xa;
5209           Interr_Err_Ind[3]=0x7;
5210           PUT_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
5211           break;
5212         case CCBS_REQUEST:
5213           dbug(1,dprintf("CCBS Request"));
5214           Interr_Err_Ind[0]=0xd;
5215           Interr_Err_Ind[3]=0xa;
5216           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
5217           break;
5218         case CCBS_DEACTIVATE:
5219           dbug(1,dprintf("CCBS Deactivate"));
5220           Interr_Err_Ind[0]=0x9;
5221           Interr_Err_Ind[3]=0x6;
5222           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
5223           break;
5224         case CCBS_INTERROGATE:
5225           dbug(1,dprintf("CCBS Interrogate"));
5226           Interr_Err_Ind[0]=0xb;
5227           Interr_Err_Ind[3]=0x8;
5228           PUT_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
5229           break;
5230       }
5231       PUT_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
5232       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
5233       plci_remove(plci);
5234       break;
5235     case ACTIVATION_MWI:      
5236     case DEACTIVATION_MWI:
5237       if(pty_cai[5]==ACTIVATION_MWI)
5238       {
5239         PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5240       }
5241       else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5242       
5243       if(pty_cai[2]!=0xff)
5244       {
5245         PUT_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
5246       }
5247       else
5248       {
5249         PUT_WORD(&SS_Ind[4],0x300E);
5250       }
5251
5252       if(plci->cr_enquiry)
5253       {
5254         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5255         plci_remove(plci);
5256       }
5257       else
5258       {
5259         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5260       }
5261       break;
5262     case CONF_ADD: /* ERROR */
5263     case CONF_BEGIN:
5264     case CONF_DROP:
5265     case CONF_ISOLATE:
5266     case CONF_REATTACH:
5267       CONF_Ind[0]=9;
5268       CONF_Ind[3]=6;   
5269       switch(pty_cai[5])
5270       {
5271       case CONF_BEGIN:
5272           PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5273           plci->ptyState = 0;
5274           break;
5275       case CONF_DROP:
5276           CONF_Ind[0]=5;
5277           CONF_Ind[3]=2;
5278           PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5279           plci->ptyState = CONNECTED;
5280           break;
5281       case CONF_ISOLATE:
5282           CONF_Ind[0]=5;
5283           CONF_Ind[3]=2;
5284           PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5285           plci->ptyState = CONNECTED;
5286           break;
5287       case CONF_REATTACH:
5288           CONF_Ind[0]=5;
5289           CONF_Ind[3]=2;
5290           PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5291           plci->ptyState = CONNECTED;
5292           break;
5293       case CONF_ADD:
5294           PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5295           plci->relatedPTYPLCI = NULL;
5296           tplci=plci->relatedPTYPLCI;
5297           if(tplci) tplci->ptyState = CONNECTED;
5298           plci->ptyState = CONNECTED;
5299           break;
5300       }
5301           
5302       if(pty_cai[2]!=0xff)
5303       {
5304         PUT_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
5305       }
5306       else
5307       {
5308         PUT_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
5309                                             within the required time */
5310       }
5311
5312       PUT_DWORD(&CONF_Ind[6],0x0);
5313       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5314       break;
5315     }
5316     break;
5317
5318   /* Supplementary Service indicates success */
5319   case S_SERVICE:
5320     dbug(1,dprintf("Service_Ind"));
5321     PUT_WORD (&CF_Ind[4], 0);
5322     switch (pty_cai[5])
5323     {
5324     case THREE_PTY_END:
5325     case THREE_PTY_BEGIN:
5326     case ECT_EXECUTE:
5327       if(!plci->relatedPTYPLCI) break;
5328       tplci = plci->relatedPTYPLCI;
5329       rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
5330       if(tplci->tel) rId|=EXT_CONTROLLER;
5331       if(pty_cai[5]==ECT_EXECUTE)
5332       {
5333         PUT_WORD(&SS_Ind[1],S_ECT);
5334
5335         if(plci->vswitchstate!=3)
5336         {
5337
5338         plci->ptyState = IDLE;
5339         plci->relatedPTYPLCI = NULL;
5340         plci->ptyState = 0;
5341
5342         }
5343
5344         dbug(1,dprintf("ECT OK"));
5345         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5346
5347
5348
5349       }
5350       else
5351       {
5352         switch (plci->ptyState)
5353         {
5354         case S_3PTY_BEGIN:
5355           plci->ptyState = CONNECTED;
5356           dbug(1,dprintf("3PTY ON"));
5357           break;
5358
5359         case S_3PTY_END:
5360           plci->ptyState = IDLE;
5361           plci->relatedPTYPLCI = NULL;
5362           plci->ptyState = 0;
5363           dbug(1,dprintf("3PTY OFF"));
5364           break;
5365         }
5366         PUT_WORD(&SS_Ind[1],pty_cai[5]+3);
5367         sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
5368       }
5369       break;
5370
5371     case CALL_DEFLECTION:
5372       PUT_WORD(&SS_Ind[1],pty_cai[5]);
5373       for(i=0; i<max_appl; i++)
5374       {
5375         if(application[i].CDEnable)
5376         {
5377           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
5378           application[i].CDEnable = false;
5379         }
5380       }
5381       break;
5382
5383     case DEACTIVATION_DIVERSION:
5384     case ACTIVATION_DIVERSION:
5385       if(!plci->appl) break;
5386       PUT_WORD(&CF_Ind[1],pty_cai[5]+2);
5387       PUT_DWORD(&CF_Ind[6],plci->appl->S_Handle);
5388       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
5389       plci_remove(plci);
5390       break;
5391
5392     case DIVERSION_INTERROGATE_CFU:
5393     case DIVERSION_INTERROGATE_CFB:
5394     case DIVERSION_INTERROGATE_CFNR:
5395     case DIVERSION_INTERROGATE_NUM:
5396     case CCBS_REQUEST:
5397     case CCBS_DEACTIVATE:
5398     case CCBS_INTERROGATE:
5399       if(!plci->appl) break;
5400       switch (pty_cai[5])
5401       {
5402         case DIVERSION_INTERROGATE_CFU:
5403         case DIVERSION_INTERROGATE_CFB:
5404         case DIVERSION_INTERROGATE_CFNR:
5405           dbug(1,dprintf("Interr_Div"));
5406           PUT_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
5407           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5408           break;
5409         case DIVERSION_INTERROGATE_NUM:
5410           dbug(1,dprintf("Interr_Num"));
5411           PUT_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
5412           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5413           break;
5414         case CCBS_REQUEST:
5415           dbug(1,dprintf("CCBS Request"));
5416           PUT_WORD(&pty_cai[1],S_CCBS_REQUEST);
5417           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5418           break;
5419         case CCBS_DEACTIVATE:
5420           dbug(1,dprintf("CCBS Deactivate"));
5421           PUT_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
5422           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5423           break;
5424         case CCBS_INTERROGATE:
5425           dbug(1,dprintf("CCBS Interrogate"));
5426           PUT_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
5427           pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
5428           break;
5429       }
5430       PUT_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
5431       PUT_DWORD(&pty_cai[6],plci->appl->S_Handle);
5432       sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
5433       plci_remove(plci);
5434       break;
5435
5436     case ACTIVATION_MWI:
5437     case DEACTIVATION_MWI:
5438       if(pty_cai[5]==ACTIVATION_MWI)
5439       {
5440         PUT_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
5441       }
5442       else PUT_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
5443       if(plci->cr_enquiry)
5444       {
5445         sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
5446         plci_remove(plci);
5447       }
5448       else
5449       {
5450         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5451       }
5452       break;
5453     case MWI_INDICATION:
5454       if(pty_cai[0]>=0x12)
5455       {
5456         PUT_WORD(&pty_cai[3],S_MWI_INDICATE);
5457         pty_cai[2]=pty_cai[0]-2; /* len Parameter */
5458         pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
5459         if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
5460         {
5461           if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
5462           {
5463             sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
5464             plci_remove(plci);
5465             return;
5466           }
5467           else  sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
5468           pty_cai[0]=0;
5469         }
5470         else
5471         {
5472           for(i=0; i<max_appl; i++)
5473           {                     
5474             if(a->Notification_Mask[i]&SMASK_MWI)
5475             {
5476               sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
5477               pty_cai[0]=0;
5478             }
5479           }
5480         }
5481
5482         if(!pty_cai[0])
5483         { /* acknowledge */
5484           facility[2]= 0; /* returncode */
5485         }
5486         else facility[2]= 0xff;
5487       }
5488       else
5489       {
5490         /* reject */
5491         facility[2]= 0xff; /* returncode */
5492       }
5493       facility[0]= 2;
5494       facility[1]= MWI_RESPONSE; /* Function */
5495       add_p(plci,CAI,facility);
5496       add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
5497       sig_req(plci,S_SERVICE,0);
5498       send_req(plci);
5499       plci->command = 0;
5500       next_internal_command (Id, plci);
5501       break;
5502     case CONF_ADD: /* OK */
5503     case CONF_BEGIN:
5504     case CONF_DROP:
5505     case CONF_ISOLATE:
5506     case CONF_REATTACH:
5507     case CONF_PARTYDISC:
5508       CONF_Ind[0]=9;
5509       CONF_Ind[3]=6;
5510       switch(pty_cai[5])
5511       {
5512       case CONF_BEGIN:
5513           PUT_WORD(&CONF_Ind[1],S_CONF_BEGIN);
5514           if(pty_cai[0]==6)
5515           {
5516               d=pty_cai[6];
5517               PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5518           }
5519           else
5520           {
5521               PUT_DWORD(&CONF_Ind[6],0x0);
5522           }
5523           break;
5524       case CONF_ISOLATE:
5525           PUT_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
5526           CONF_Ind[0]=5;
5527           CONF_Ind[3]=2;
5528           break;
5529       case CONF_REATTACH:
5530           PUT_WORD(&CONF_Ind[1],S_CONF_REATTACH);
5531           CONF_Ind[0]=5;
5532           CONF_Ind[3]=2;
5533           break;
5534       case CONF_DROP:
5535           PUT_WORD(&CONF_Ind[1],S_CONF_DROP);
5536           CONF_Ind[0]=5;
5537           CONF_Ind[3]=2;
5538           break;
5539       case CONF_ADD:
5540           PUT_WORD(&CONF_Ind[1],S_CONF_ADD);
5541           d=pty_cai[6];
5542           PUT_DWORD(&CONF_Ind[6],d); /* PartyID */
5543           tplci=plci->relatedPTYPLCI;
5544           if(tplci) tplci->ptyState = CONNECTED;
5545           break;
5546       case CONF_PARTYDISC:
5547           CONF_Ind[0]=7;
5548           CONF_Ind[3]=4;          
5549           PUT_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
5550           d=pty_cai[6];
5551           PUT_DWORD(&CONF_Ind[4],d); /* PartyID */
5552           break;
5553       }
5554       plci->ptyState = CONNECTED;
5555       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5556       break;
5557     case CCBS_INFO_RETAIN:
5558     case CCBS_ERASECALLLINKAGEID:
5559     case CCBS_STOP_ALERTING:
5560       CONF_Ind[0]=5;
5561       CONF_Ind[3]=2;
5562       switch(pty_cai[5])
5563       {
5564       case CCBS_INFO_RETAIN:
5565         PUT_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
5566         break;
5567       case CCBS_STOP_ALERTING:
5568         PUT_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
5569     break;
5570       case CCBS_ERASECALLLINKAGEID:
5571         PUT_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
5572         CONF_Ind[0]=7;
5573         CONF_Ind[3]=4;
5574         CONF_Ind[6]=0;
5575         CONF_Ind[7]=0;
5576         break;
5577       }      
5578       w=pty_cai[6];
5579       PUT_WORD(&CONF_Ind[4],w); /* PartyID */
5580
5581       if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
5582       {
5583         sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
5584       }
5585       else
5586       {
5587         for(i=0; i<max_appl; i++)
5588             if(a->Notification_Mask[i]&SMASK_CCBS)
5589                 sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
5590       }
5591       break;
5592     }
5593     break;
5594   case CALL_HOLD_REJ:
5595     cau = parms[7];
5596     if(cau)
5597     {
5598       i = _L3_CAUSE | cau[2];
5599       if(cau[2]==0) i = 0x3603;
5600     }
5601     else
5602     {
5603       i = 0x3603;
5604     }
5605     PUT_WORD(&SS_Ind[1],S_HOLD);
5606     PUT_WORD(&SS_Ind[4],i);
5607     if(plci->SuppState == HOLD_REQUEST)
5608     {
5609       plci->SuppState = IDLE;
5610       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5611     }
5612     break;
5613
5614   case CALL_HOLD_ACK:
5615     if(plci->SuppState == HOLD_REQUEST)
5616     {
5617       plci->SuppState = CALL_HELD;
5618       CodecIdCheck(a, plci);
5619       start_internal_command (Id, plci, hold_save_command);
5620     }
5621     break;
5622
5623   case CALL_RETRIEVE_REJ:
5624     cau = parms[7];
5625     if(cau)
5626     {
5627       i = _L3_CAUSE | cau[2];
5628       if(cau[2]==0) i = 0x3603;
5629     }
5630     else
5631     {
5632       i = 0x3603;
5633     }
5634     PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5635     PUT_WORD(&SS_Ind[4],i);
5636     if(plci->SuppState == RETRIEVE_REQUEST)
5637     {
5638       plci->SuppState = CALL_HELD;
5639       CodecIdCheck(a, plci);
5640       sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5641     }
5642     break;
5643
5644   case CALL_RETRIEVE_ACK:
5645     PUT_WORD(&SS_Ind[1],S_RETRIEVE);
5646     if(plci->SuppState == RETRIEVE_REQUEST)
5647     {
5648       plci->SuppState = IDLE;
5649       plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
5650       plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5651       if(plci->tel)
5652       {
5653         mixer_set_bchannel_id_esc (plci, plci->b_channel);
5654         dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
5655         SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
5656         if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
5657         {
5658           dbug(1,dprintf("Get B-ch"));
5659           start_internal_command (Id, plci, retrieve_restore_command);
5660         }
5661         else
5662           sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
5663       }
5664       else
5665         start_internal_command (Id, plci, retrieve_restore_command);
5666     }
5667     break;
5668
5669   case INDICATE_IND:
5670     if(plci->State != LISTENING) {
5671       sig_req(plci,HANGUP,0);
5672       send_req(plci);
5673       break;
5674     }
5675     cip = find_cip(a,parms[4],parms[6]);
5676     cip_mask = 1L<<cip;
5677     dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
5678     clear_c_ind_mask (plci);
5679     if (!remove_started && !a->adapter_disabled)
5680     {
5681       set_c_ind_mask_bit (plci, MAX_APPL);
5682       group_optimization(a, plci);
5683       for(i=0; i<max_appl; i++) {
5684         if(application[i].Id
5685         && (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
5686         && CPN_filter_ok(parms[0],a,i)
5687         && test_group_ind_mask_bit (plci, i) ) {
5688           dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
5689           set_c_ind_mask_bit (plci, i);
5690           dump_c_ind_mask (plci);
5691           plci->State = INC_CON_PENDING;
5692           plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
5693             CALL_DIR_IN | CALL_DIR_ANSWER;
5694           if(esc_chi[0]) {
5695             plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
5696             mixer_set_bchannel_id_esc (plci, plci->b_channel);
5697           }
5698           /* if a listen on the ext controller is done, check if hook states */
5699           /* are supported or if just a on board codec must be activated     */
5700           if(a->codec_listen[i] && !a->AdvSignalPLCI) {
5701             if(a->profile.Global_Options & HANDSET)
5702               plci->tel = ADV_VOICE;
5703             else if(a->profile.Global_Options & ON_BOARD_CODEC)
5704               plci->tel = CODEC;
5705             if(plci->tel) Id|=EXT_CONTROLLER;
5706             a->codec_listen[i] = plci;
5707           }
5708
5709           sendf(&application[i],_CONNECT_I,Id,0,
5710                 "wSSSSSSSbSSSSS", cip,    /* CIP                 */
5711                              parms[0],    /* CalledPartyNumber   */
5712                              multi_CiPN_parms[0],    /* CallingPartyNumber  */
5713                              parms[2],    /* CalledPartySubad    */
5714                              parms[3],    /* CallingPartySubad   */
5715                              parms[4],    /* BearerCapability    */
5716                              parms[5],    /* LowLC               */
5717                              parms[6],    /* HighLC              */
5718                              ai_len,      /* nested struct add_i */
5719                              add_i[0],    /* B channel info    */
5720                              add_i[1],    /* keypad facility   */
5721                              add_i[2],    /* user user data    */
5722                              add_i[3],    /* nested facility   */
5723                              multi_CiPN_parms[1]    /* second CiPN(SCR)   */
5724                              );
5725           SendSSExtInd(&application[i],
5726                         plci,
5727                         Id,
5728                         multi_ssext_parms);
5729           SendSetupInfo(&application[i],
5730                         plci,
5731                         Id,
5732                         parms,
5733                         SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
5734         }
5735       }
5736       clear_c_ind_mask_bit (plci, MAX_APPL);
5737       dump_c_ind_mask (plci);
5738     }
5739     if(c_ind_mask_empty (plci)) {
5740       sig_req(plci,HANGUP,0);
5741       send_req(plci);
5742       plci->State = IDLE;
5743     }
5744     plci->notifiedcall = 0;
5745     a->listen_active--;
5746     listen_check(a);
5747     break;
5748
5749   case CALL_PEND_NOTIFY:
5750     plci->notifiedcall = 1;
5751     listen_check(a);
5752     break;
5753
5754   case CALL_IND:
5755   case CALL_CON:
5756     if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
5757     {
5758       if(plci->internal_command==PERM_COD_CONN_PEND)
5759       {
5760         if(plci->State==ADVANCED_VOICE_NOSIG)
5761         {
5762           dbug(1,dprintf("***Codec OK"));
5763           if(a->AdvSignalPLCI)
5764           {
5765             tplci = a->AdvSignalPLCI;
5766             if(tplci->spoofed_msg)
5767             {
5768               dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
5769               tplci->command = 0;
5770               tplci->internal_command = 0;
5771               x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
5772               switch (tplci->spoofed_msg)
5773               {
5774               case CALL_RES:
5775                 tplci->command = _CONNECT_I|RESPONSE;
5776                 api_load_msg (&tplci->saved_msg, saved_parms);
5777                 add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
5778                 if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
5779                 {
5780                   /* early B3 connect (CIP mask bit 9) no release after a disc */
5781                   add_p(tplci,LLI,"\x01\x01");
5782                 }
5783                 add_s(tplci, CONN_NR, &saved_parms[2]);
5784                 add_s(tplci, LLC, &saved_parms[4]);
5785                 add_ai(tplci, &saved_parms[5]);
5786                 tplci->State = INC_CON_ACCEPT;
5787                 sig_req(tplci, CALL_RES,0);
5788                 send_req(tplci);
5789                 break;
5790
5791               case AWAITING_SELECT_B:
5792                 dbug(1,dprintf("Select_B continue"));
5793                 start_internal_command (x_Id, tplci, select_b_command);
5794                 break;
5795
5796               case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
5797                 if(!tplci->Sig.Id)
5798                 {
5799                   dbug(1,dprintf("No SigID!"));
5800                   sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
5801                   plci_remove(tplci);
5802                   break;
5803                 }
5804                 tplci->command = _MANUFACTURER_R;
5805                 api_load_msg (&tplci->saved_msg, saved_parms);
5806                 dir = saved_parms[2].info[0];
5807                 if(dir==1) {
5808                   sig_req(tplci,CALL_REQ,0);
5809                 }
5810                 else if(!dir){
5811                   sig_req(tplci,LISTEN_REQ,0);
5812                 }
5813                 send_req(tplci);
5814                 sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
5815                 break;
5816
5817               case (CALL_REQ|AWAITING_MANUF_CON):
5818                 sig_req(tplci,CALL_REQ,0);
5819                 send_req(tplci);
5820                 break;
5821
5822               case CALL_REQ:
5823                 if(!tplci->Sig.Id)
5824                 {
5825                   dbug(1,dprintf("No SigID!"));
5826                   sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
5827                   plci_remove(tplci);
5828                   break;
5829                 }
5830                 tplci->command = _CONNECT_R;
5831                 api_load_msg (&tplci->saved_msg, saved_parms);
5832                 add_s(tplci,CPN,&saved_parms[1]);
5833                 add_s(tplci,DSA,&saved_parms[3]);
5834                 add_ai(tplci,&saved_parms[9]);
5835                 sig_req(tplci,CALL_REQ,0);
5836                 send_req(tplci);
5837                 break;
5838
5839               case CALL_RETRIEVE:
5840                 tplci->command = C_RETRIEVE_REQ;
5841                 sig_req(tplci,CALL_RETRIEVE,0);
5842                 send_req(tplci);
5843                 break;
5844               }
5845               tplci->spoofed_msg = 0;
5846               if (tplci->internal_command == 0)
5847                 next_internal_command (x_Id, tplci);
5848             }
5849           }
5850           next_internal_command (Id, plci);
5851           break;
5852         }
5853         dbug(1,dprintf("***Codec Hook Init Req"));
5854         plci->internal_command = PERM_COD_HOOK;
5855         add_p(plci,FTY,"\x01\x09");             /* Get Hook State*/
5856         sig_req(plci,TEL_CTRL,0);
5857         send_req(plci);
5858       }
5859     }
5860     else if(plci->command != _MANUFACTURER_R  /* old style permanent connect */
5861     && plci->State!=INC_ACT_PENDING)
5862     {
5863       mixer_set_bchannel_id_esc (plci, plci->b_channel);
5864       if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
5865       {
5866         chi[2] = plci->b_channel;
5867         SetVoiceChannel(a->AdvCodecPLCI, chi, a);
5868       }
5869       sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
5870       plci->State = INC_ACT_PENDING;
5871     }
5872     break;
5873
5874   case TEL_CTRL:
5875     Number = 0;
5876     ie = multi_fac_parms[0]; /* inspect the facility hook indications */
5877     if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
5878       switch (ie[1]&0x91) {
5879         case 0x80:   /* hook off */
5880         case 0x81:
5881           if(plci->internal_command==PERM_COD_HOOK)
5882           {
5883             dbug(1,dprintf("init:hook_off"));
5884             plci->hook_state = ie[1];
5885             next_internal_command (Id, plci);
5886             break;
5887           }
5888           else /* ignore doubled hook indications */
5889           {
5890             if( ((plci->hook_state)&0xf0)==0x80)
5891             {
5892               dbug(1,dprintf("ignore hook"));
5893               break;
5894             }
5895             plci->hook_state = ie[1]&0x91;
5896           }
5897           /* check for incoming call pending */
5898           /* and signal '+'.Appl must decide */
5899           /* with connect_res if call must   */
5900           /* accepted or not                 */
5901           for(i=0, tplci=NULL;i<max_appl;i++){
5902             if(a->codec_listen[i]
5903             && (a->codec_listen[i]->State==INC_CON_PENDING
5904               ||a->codec_listen[i]->State==INC_CON_ALERT) ){
5905               tplci = a->codec_listen[i];
5906               tplci->appl = &application[i];
5907             }
5908           }
5909           /* no incoming call, do outgoing call */
5910           /* and signal '+' if outg. setup   */
5911           if(!a->AdvSignalPLCI && !tplci){
5912             if((i=get_plci(a))) {
5913               a->AdvSignalPLCI = &a->plci[i-1];
5914               tplci = a->AdvSignalPLCI;
5915               tplci->tel  = ADV_VOICE;
5916               PUT_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
5917               if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
5918                 /* early B3 connect (CIP mask bit 9) no release after a disc */
5919                 add_p(tplci,LLI,"\x01\x01");
5920               }
5921               add_p(tplci, CAI, voice_cai);
5922               add_p(tplci, OAD, a->TelOAD);
5923               add_p(tplci, OSA, a->TelOSA);
5924               add_p(tplci,SHIFT|6,NULL);
5925               add_p(tplci,SIN,"\x02\x01\x00");
5926               add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
5927               sig_req(tplci,ASSIGN,DSIG_ID);
5928               a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
5929               a->AdvSignalPLCI->command = 0;
5930               tplci->appl = a->AdvSignalAppl;
5931               tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
5932               send_req(tplci);
5933             }
5934
5935           }
5936
5937           if(!tplci) break;
5938           Id = ((word)tplci->Id<<8)|a->Id;
5939           Id|=EXT_CONTROLLER;
5940           sendf(tplci->appl,
5941                 _FACILITY_I,
5942                 Id,
5943                 0,
5944                 "ws", (word)0, "\x01+");
5945           break;
5946
5947         case 0x90:   /* hook on  */
5948         case 0x91:
5949           if(plci->internal_command==PERM_COD_HOOK)
5950           {
5951             dbug(1,dprintf("init:hook_on"));
5952             plci->hook_state = ie[1]&0x91;
5953             next_internal_command (Id, plci);
5954             break;
5955           }
5956           else /* ignore doubled hook indications */
5957           {
5958             if( ((plci->hook_state)&0xf0)==0x90) break;
5959             plci->hook_state = ie[1]&0x91;
5960           }
5961           /* hangup the adv. voice call and signal '-' to the appl */
5962           if(a->AdvSignalPLCI) {
5963             Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
5964             if(plci->tel) Id|=EXT_CONTROLLER;
5965             sendf(a->AdvSignalAppl,
5966                   _FACILITY_I,
5967                   Id,
5968                   0,
5969                   "ws", (word)0, "\x01-");
5970             a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
5971             a->AdvSignalPLCI->command = 0;
5972             sig_req(a->AdvSignalPLCI,HANGUP,0);
5973             send_req(a->AdvSignalPLCI);
5974           }
5975           break;
5976       }
5977     }
5978     break;
5979
5980   case RESUME:
5981     clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
5982     PUT_WORD(&resume_cau[4],GOOD);
5983     sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
5984     break;
5985
5986   case SUSPEND:
5987     clear_c_ind_mask (plci);
5988
5989     if (plci->NL.Id && !plci->nl_remove_id) {
5990       mixer_remove (plci);
5991       nl_req_ncci(plci,REMOVE,0);
5992     }
5993     if (!plci->sig_remove_id) {
5994       plci->internal_command = 0;
5995       sig_req(plci,REMOVE,0);
5996     }
5997     send_req(plci);
5998     if(!plci->channels) {
5999       sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
6000       sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
6001     }
6002     break;
6003
6004   case SUSPEND_REJ:
6005     break;
6006
6007   case HANGUP:
6008     plci->hangup_flow_ctrl_timer=0;
6009     if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
6010     cau = parms[7];
6011     if(cau) {
6012       i = _L3_CAUSE | cau[2];
6013       if(cau[2]==0) i = 0;
6014       else if(cau[2]==8) i = _L1_ERROR;
6015       else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
6016       else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
6017     }
6018     else {
6019       i = _L3_ERROR;
6020     }
6021
6022     if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
6023     {
6024       for(i=0; i<max_appl; i++)
6025       {
6026         if(test_c_ind_mask_bit (plci, i))
6027           sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
6028       }
6029     }
6030     else
6031     {
6032       clear_c_ind_mask (plci);
6033     }
6034     if(!plci->appl)
6035     {
6036       if (plci->State == LISTENING)
6037       {
6038         plci->notifiedcall=0;
6039         a->listen_active--;
6040       }
6041       plci->State = INC_DIS_PENDING;
6042       if(c_ind_mask_empty (plci))
6043       {
6044         plci->State = IDLE;
6045         if (plci->NL.Id && !plci->nl_remove_id)
6046         {
6047           mixer_remove (plci);
6048           nl_req_ncci(plci,REMOVE,0);
6049         }
6050         if (!plci->sig_remove_id)
6051         {
6052           plci->internal_command = 0;
6053           sig_req(plci,REMOVE,0);
6054         }
6055         send_req(plci);
6056       }
6057     }
6058     else
6059     {
6060         /* collision of DISCONNECT or CONNECT_RES with HANGUP can   */
6061         /* result in a second HANGUP! Don't generate another        */
6062         /* DISCONNECT                                               */
6063       if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
6064       {
6065         if(plci->State==RESUMING)
6066         {
6067           PUT_WORD(&resume_cau[4],i);
6068           sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
6069         }
6070         plci->State = INC_DIS_PENDING;
6071         sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
6072       }
6073     }
6074     break;
6075
6076   case SSEXT_IND:
6077     SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
6078     break;
6079
6080   case VSWITCH_REQ:
6081     VSwitchReqInd(plci,Id,multi_vswitch_parms);
6082     break;
6083   case VSWITCH_IND:
6084  if(plci->relatedPTYPLCI &&
6085   plci->vswitchstate==3 &&
6086   plci->relatedPTYPLCI->vswitchstate==3 &&
6087   parms[MAXPARMSIDS-1][0])
6088  {
6089   add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
6090   sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
6091   send_req(plci->relatedPTYPLCI);
6092  }
6093     else VSwitchReqInd(plci,Id,multi_vswitch_parms);
6094     break;
6095
6096   }
6097 }
6098
6099
6100 static void SendSetupInfo(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms, byte Info_Sent_Flag)
6101 {
6102   word i;
6103   byte   * ie;
6104   word Info_Number;
6105   byte   * Info_Element;
6106   word Info_Mask = 0;
6107
6108   dbug(1,dprintf("SetupInfo"));
6109
6110   for(i=0; i<MAXPARMSIDS; i++) {
6111     ie = parms[i];
6112     Info_Number = 0;
6113     Info_Element = ie;
6114     if(ie[0]) {
6115       switch(i) {
6116       case 0:
6117         dbug(1,dprintf("CPN "));
6118         Info_Number = 0x0070;
6119         Info_Mask   = 0x80;
6120         Info_Sent_Flag = true;
6121         break;
6122       case 8:  /* display      */
6123         dbug(1,dprintf("display(%d)",i));
6124         Info_Number = 0x0028;
6125         Info_Mask = 0x04;
6126         Info_Sent_Flag = true;
6127         break;
6128       case 16: /* Channel Id */
6129         dbug(1,dprintf("CHI"));
6130         Info_Number = 0x0018;
6131         Info_Mask = 0x100;
6132         Info_Sent_Flag = true;
6133         mixer_set_bchannel_id (plci, Info_Element);
6134         break;
6135       case 19: /* Redirected Number */
6136         dbug(1,dprintf("RDN"));
6137         Info_Number = 0x0074;
6138         Info_Mask = 0x400;
6139         Info_Sent_Flag = true;
6140         break;
6141       case 20: /* Redirected Number extended */
6142         dbug(1,dprintf("RDX"));
6143         Info_Number = 0x0073;
6144         Info_Mask = 0x400;
6145         Info_Sent_Flag = true;
6146         break;
6147       case 22: /* Redirecing Number  */
6148         dbug(1,dprintf("RIN"));
6149         Info_Number = 0x0076;
6150         Info_Mask = 0x400;
6151         Info_Sent_Flag = true;
6152         break;
6153       default:
6154         Info_Number = 0;
6155         break;
6156       }
6157     }
6158
6159     if(i==MAXPARMSIDS-2){ /* to indicate the message type "Setup" */
6160       Info_Number = 0x8000 |5;
6161       Info_Mask = 0x10;
6162       Info_Element = "";
6163     }
6164
6165     if(Info_Sent_Flag && Info_Number){
6166       if(plci->adapter->Info_Mask[appl->Id-1] & Info_Mask) {
6167         sendf(appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6168       }
6169     }
6170   }
6171 }
6172
6173
6174 void SendInfo(PLCI   * plci, dword Id, byte   * * parms, byte iesent)
6175 {
6176   word i;
6177   word j;
6178   word k;
6179   byte   * ie;
6180   word Info_Number;
6181   byte   * Info_Element;
6182   word Info_Mask = 0;
6183   static byte charges[5] = {4,0,0,0,0};
6184   static byte cause[] = {0x02,0x80,0x00};
6185   APPL   *appl;
6186
6187   dbug(1,dprintf("InfoParse "));
6188
6189   if(
6190         !plci->appl
6191         && !plci->State
6192         && plci->Sig.Ind!=NCR_FACILITY
6193       )
6194   {
6195     dbug(1,dprintf("NoParse "));
6196     return;
6197   }
6198   cause[2] = 0;
6199   for(i=0; i<MAXPARMSIDS; i++) {
6200     ie = parms[i];
6201     Info_Number = 0;
6202     Info_Element = ie;
6203     if(ie[0]) {
6204       switch(i) {
6205       case 0:
6206         dbug(1,dprintf("CPN "));
6207         Info_Number = 0x0070;
6208         Info_Mask   = 0x80;
6209         break;
6210       case 7: /* ESC_CAU */
6211         dbug(1,dprintf("cau(0x%x)",ie[2]));
6212         Info_Number = 0x0008;
6213         Info_Mask = 0x00;
6214         cause[2] = ie[2];
6215         Info_Element = NULL;
6216         break;
6217       case 8:  /* display      */
6218         dbug(1,dprintf("display(%d)",i));
6219         Info_Number = 0x0028;
6220         Info_Mask = 0x04;
6221         break;
6222       case 9:  /* Date display */
6223         dbug(1,dprintf("date(%d)",i));
6224         Info_Number = 0x0029;
6225         Info_Mask = 0x02;
6226         break;
6227       case 10: /* charges */
6228         for(j=0;j<4;j++) charges[1+j] = 0;
6229         for(j=0; j<ie[0] && !(ie[1+j]&0x80); j++);
6230         for(k=1,j++; j<ie[0] && k<=4; j++,k++) charges[k] = ie[1+j];
6231         Info_Number = 0x4000;
6232         Info_Mask = 0x40;
6233         Info_Element = charges;
6234         break;
6235       case 11: /* user user info */
6236         dbug(1,dprintf("uui"));
6237         Info_Number = 0x007E;
6238         Info_Mask = 0x08;
6239         break;
6240       case 12: /* congestion receiver ready */
6241         dbug(1,dprintf("clRDY"));
6242         Info_Number = 0x00B0;
6243         Info_Mask = 0x08;
6244         Info_Element = "";
6245         break;
6246       case 13: /* congestion receiver not ready */
6247         dbug(1,dprintf("clNRDY"));
6248         Info_Number = 0x00BF;
6249         Info_Mask = 0x08;
6250         Info_Element = "";
6251         break;
6252       case 15: /* Keypad Facility */
6253         dbug(1,dprintf("KEY"));
6254         Info_Number = 0x002C;
6255         Info_Mask = 0x20;
6256         break;
6257       case 16: /* Channel Id */
6258         dbug(1,dprintf("CHI"));
6259         Info_Number = 0x0018;
6260         Info_Mask = 0x100;
6261         mixer_set_bchannel_id (plci, Info_Element);
6262         break;
6263       case 17: /* if no 1tr6 cause, send full cause, else esc_cause */
6264         dbug(1,dprintf("q9cau(0x%x)",ie[2]));
6265         if(!cause[2] || cause[2]<0x80) break;  /* eg. layer 1 error */
6266         Info_Number = 0x0008;
6267         Info_Mask = 0x01;
6268         if(cause[2] != ie[2]) Info_Element = cause;
6269         break;
6270       case 19: /* Redirected Number */
6271         dbug(1,dprintf("RDN"));
6272         Info_Number = 0x0074;
6273         Info_Mask = 0x400;
6274         break;
6275       case 22: /* Redirecing Number  */
6276         dbug(1,dprintf("RIN"));
6277         Info_Number = 0x0076;
6278         Info_Mask = 0x400;
6279         break;
6280       case 23: /* Notification Indicator  */
6281         dbug(1,dprintf("NI"));
6282         Info_Number = (word)NI;
6283         Info_Mask = 0x210;
6284         break;
6285       case 26: /* Call State  */
6286         dbug(1,dprintf("CST"));
6287         Info_Number = (word)CST;
6288         Info_Mask = 0x01; /* do with cause i.e. for now */
6289         break;
6290       case MAXPARMSIDS-2:  /* Escape Message Type, must be the last indication */
6291         dbug(1,dprintf("ESC/MT[0x%x]",ie[3]));
6292         Info_Number = 0x8000 |ie[3];
6293         if(iesent) Info_Mask = 0xffff;
6294         else  Info_Mask = 0x10;
6295         Info_Element = "";
6296         break;
6297       default:
6298         Info_Number  = 0;
6299         Info_Mask    = 0;
6300         Info_Element = "";
6301         break;
6302       }
6303     }
6304
6305     if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
6306     {
6307       for(j=0; j<max_appl; j++)
6308       {
6309         appl = &application[j];
6310         if(Info_Number
6311         && appl->Id
6312         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6313         {
6314           dbug(1,dprintf("NCR_Ind"));
6315           iesent=true;
6316           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6317         }
6318       }
6319     }
6320     else if(!plci->appl)
6321     { /* overlap receiving broadcast */
6322       if(Info_Number==CPN
6323       || Info_Number==KEY
6324       || Info_Number==NI
6325       || Info_Number==DSP
6326       || Info_Number==UUI )
6327       {
6328         for(j=0; j<max_appl; j++)
6329         {
6330           if(test_c_ind_mask_bit (plci, j))
6331           {
6332             dbug(1,dprintf("Ovl_Ind"));
6333             iesent=true;
6334             sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6335           }
6336         }
6337       }
6338     }               /* all other signalling states */
6339     else if(Info_Number
6340     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6341     {
6342       dbug(1,dprintf("Std_Ind"));
6343       iesent=true;
6344       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6345     }
6346   }
6347 }
6348
6349
6350 byte SendMultiIE(PLCI   * plci, dword Id, byte   * * parms, byte ie_type, dword info_mask, byte setupParse)
6351 {
6352   word i;
6353   word j;
6354   byte   * ie;
6355   word Info_Number;
6356   byte   * Info_Element;
6357   APPL   *appl;
6358   word Info_Mask = 0;
6359   byte iesent=0;
6360
6361   if(
6362       !plci->appl
6363       && !plci->State
6364       && plci->Sig.Ind!=NCR_FACILITY
6365       && !setupParse
6366       )
6367   {
6368     dbug(1,dprintf("NoM-IEParse "));
6369     return 0;
6370   }
6371   dbug(1,dprintf("M-IEParse "));
6372
6373   for(i=0; i<MAX_MULTI_IE; i++)
6374   {
6375     ie = parms[i];
6376     Info_Number = 0;
6377     Info_Element = ie;
6378     if(ie[0])
6379     {
6380       dbug(1,dprintf("[Ind0x%x]:IE=0x%x",plci->Sig.Ind,ie_type));
6381       Info_Number = (word)ie_type;
6382       Info_Mask = (word)info_mask;
6383     }
6384
6385     if(plci->Sig.Ind==NCR_FACILITY)           /* check controller broadcast */
6386     {
6387       for(j=0; j<max_appl; j++)
6388       {
6389         appl = &application[j];
6390         if(Info_Number
6391         && appl->Id
6392         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
6393         {
6394           iesent = true;
6395           dbug(1,dprintf("Mlt_NCR_Ind"));
6396           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
6397         }
6398       }
6399     }
6400     else if(!plci->appl && Info_Number)
6401     {                                        /* overlap receiving broadcast */
6402       for(j=0; j<max_appl; j++)
6403       {
6404         if(test_c_ind_mask_bit (plci, j))
6405         {
6406           iesent = true;
6407           dbug(1,dprintf("Mlt_Ovl_Ind"));
6408           sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6409         }
6410       }
6411     }                                        /* all other signalling states */
6412     else if(Info_Number
6413     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
6414     {
6415       iesent = true;
6416       dbug(1,dprintf("Mlt_Std_Ind"));
6417       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
6418     }
6419   }
6420   return iesent;
6421 }
6422
6423 static void SendSSExtInd(APPL   * appl, PLCI   * plci, dword Id, byte   * * parms)
6424 {
6425   word i;
6426    /* Format of multi_ssext_parms[i][]:
6427    0 byte length
6428    1 byte SSEXTIE
6429    2 byte SSEXT_REQ/SSEXT_IND
6430    3 byte length
6431    4 word SSExtCommand
6432    6... Params
6433    */
6434   if(
6435    plci
6436    && plci->State
6437    && plci->Sig.Ind!=NCR_FACILITY
6438     )
6439  for(i=0;i<MAX_MULTI_IE;i++)
6440     {
6441       if(parms[i][0]<6) continue;
6442    if(parms[i][2]==SSEXT_REQ) continue;
6443
6444    if(appl)
6445    {
6446     parms[i][0]=0; /* kill it */
6447     sendf(appl,_MANUFACTURER_I,
6448     Id,
6449     0,
6450     "dwS",
6451     _DI_MANU_ID,
6452     _DI_SSEXT_CTRL,
6453     &parms[i][3]);
6454    }
6455    else if(plci->appl)
6456    {
6457     parms[i][0]=0; /* kill it */
6458     sendf(plci->appl,_MANUFACTURER_I,
6459     Id,
6460     0,
6461     "dwS",
6462     _DI_MANU_ID,
6463     _DI_SSEXT_CTRL,
6464     &parms[i][3]);
6465    }
6466     }
6467 };
6468
6469 void nl_ind(PLCI   * plci)
6470 {
6471   byte ch;
6472   word ncci;
6473   dword Id;
6474   DIVA_CAPI_ADAPTER   * a;
6475   word NCCIcode;
6476   APPL   * APPLptr;
6477   word count;
6478   word Num;
6479   word i, ncpi_state;
6480   byte len, ncci_state;
6481   word msg;
6482   word info = 0;
6483   word fax_feature_bits;
6484   byte fax_send_edata_ack;
6485   static byte v120_header_buffer[2 + 3];
6486   static word fax_info[] = {
6487     0,                     /* T30_SUCCESS                        */
6488     _FAX_NO_CONNECTION,    /* T30_ERR_NO_DIS_RECEIVED            */
6489     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_RESPONSE        */
6490     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_RESPONSE          */
6491     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TOO_MANY_REPEATS           */
6492     _FAX_PROTOCOL_ERROR,   /* T30_ERR_UNEXPECTED_MESSAGE         */
6493     _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DCN             */
6494     _FAX_LOCAL_ABORT,      /* T30_ERR_DTC_UNSUPPORTED            */
6495     _FAX_TRAINING_ERROR,   /* T30_ERR_ALL_RATES_FAILED           */
6496     _FAX_TRAINING_ERROR,   /* T30_ERR_TOO_MANY_TRAINS            */
6497     _FAX_PARAMETER_ERROR,  /* T30_ERR_RECEIVE_CORRUPTED          */
6498     _FAX_REMOTE_ABORT,     /* T30_ERR_UNEXPECTED_DISC            */
6499     _FAX_LOCAL_ABORT,      /* T30_ERR_APPLICATION_DISC           */
6500     _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_DIS           */
6501     _FAX_LOCAL_ABORT,      /* T30_ERR_INCOMPATIBLE_DCS           */
6502     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_NO_COMMAND         */
6503     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_COMMAND           */
6504     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_COMMAND_TOO_LONG   */
6505     _FAX_PROTOCOL_ERROR,   /* T30_ERR_TIMEOUT_RESPONSE_TOO_LONG  */
6506     _FAX_NO_CONNECTION,    /* T30_ERR_NOT_IDENTIFIED             */
6507     _FAX_PROTOCOL_ERROR,   /* T30_ERR_SUPERVISORY_TIMEOUT        */
6508     _FAX_PARAMETER_ERROR,  /* T30_ERR_TOO_LONG_SCAN_LINE         */
6509     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_MPS    */
6510     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_PAGE_AFTER_CFR    */
6511     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_FTT     */
6512     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_EOM     */
6513     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCS_AFTER_MPS     */
6514     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_MCF     */
6515     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_DCN_AFTER_RTN     */
6516     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_CFR               */
6517     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOP     */
6518     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_EOM     */
6519     _FAX_PROTOCOL_ERROR,   /* T30_ERR_RETRY_NO_MCF_AFTER_MPS     */
6520     0x331d,                /* T30_ERR_SUB_SEP_UNSUPPORTED        */
6521     0x331e,                /* T30_ERR_PWD_UNSUPPORTED            */
6522     0x331f,                /* T30_ERR_SUB_SEP_PWD_UNSUPPORTED    */
6523     _FAX_PROTOCOL_ERROR,   /* T30_ERR_INVALID_COMMAND_FRAME      */
6524     _FAX_PARAMETER_ERROR,  /* T30_ERR_UNSUPPORTED_PAGE_CODING    */
6525     _FAX_PARAMETER_ERROR,  /* T30_ERR_INVALID_PAGE_CODING        */
6526     _FAX_REMOTE_REJECT,    /* T30_ERR_INCOMPATIBLE_PAGE_CONFIG   */
6527     _FAX_LOCAL_ABORT,      /* T30_ERR_TIMEOUT_FROM_APPLICATION   */
6528     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_NO_REACTION_ON_MARK */
6529     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_TRAINING_TIMEOUT    */
6530     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_UNEXPECTED_V21      */
6531     _FAX_PROTOCOL_ERROR,   /* T30_ERR_V34FAX_PRIMARY_CTS_ON      */
6532     _FAX_LOCAL_ABORT,      /* T30_ERR_V34FAX_TURNAROUND_POLLING  */
6533     _FAX_LOCAL_ABORT       /* T30_ERR_V34FAX_V8_INCOMPATIBILITY  */
6534   };
6535
6536     byte dtmf_code_buffer[CAPIDTMF_RECV_DIGIT_BUFFER_SIZE + 1];
6537
6538
6539   static word rtp_info[] = {
6540     GOOD,                  /* RTP_SUCCESS                       */
6541     0x3600                 /* RTP_ERR_SSRC_OR_PAYLOAD_CHANGE    */
6542   };
6543
6544   static dword udata_forwarding_table[0x100 / sizeof(dword)] =
6545   {
6546     0x0020301e, 0x00000000, 0x00000000, 0x00000000,
6547     0x00000000, 0x00000000, 0x00000000, 0x00000000
6548   };
6549
6550   ch = plci->NL.IndCh;
6551   a = plci->adapter;
6552   ncci = a->ch_ncci[ch];
6553   Id = (((dword)(ncci ? ncci : ch)) << 16) | (((word) plci->Id) << 8) | a->Id;
6554   if(plci->tel) Id|=EXT_CONTROLLER;
6555   APPLptr = plci->appl;
6556   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",
6557     plci->NL.Id,Id,plci->Id,plci->tel,plci->State,ch,plci->channels,plci->NL.Ind &0x0f));
6558
6559   /* in the case if no connect_active_Ind was sent to the appl we wait for */
6560
6561   if (plci->nl_remove_id)
6562   {
6563     plci->NL.RNR = 2; /* discard */
6564     dbug(1,dprintf("NL discard while remove pending"));
6565     return;
6566   }
6567   if((plci->NL.Ind &0x0f)==N_CONNECT)
6568   {
6569     if(plci->State==INC_DIS_PENDING
6570     || plci->State==OUTG_DIS_PENDING
6571     || plci->State==IDLE)
6572     {
6573       plci->NL.RNR = 2; /* discard */
6574       dbug(1,dprintf("discard n_connect"));
6575       return;
6576     }
6577     if(plci->State < INC_ACT_PENDING)
6578     {
6579       plci->NL.RNR = 1; /* flow control */
6580       channel_x_off (plci, ch, N_XON_CONNECT_IND);
6581       return;
6582     }
6583   }
6584
6585   if(!APPLptr)                         /* no application or invalid data */
6586   {                                    /* while reloading the DSP        */
6587     dbug(1,dprintf("discard1"));
6588     plci->NL.RNR = 2;
6589     return;
6590   }
6591
6592   if (((plci->NL.Ind &0x0f) == N_UDATA)
6593      && (((plci->B2_prot != B2_SDLC) && ((plci->B1_resource == 17) || (plci->B1_resource == 18)))
6594         || (plci->B2_prot == 7)
6595         || (plci->B3_prot == 7)) )
6596   {
6597     plci->ncpi_buffer[0] = 0;
6598
6599     ncpi_state = plci->ncpi_state;
6600     if (plci->NL.complete == 1)
6601     {
6602       byte  * data = &plci->NL.RBuffer->P[0];
6603
6604       if ((plci->NL.RBuffer->length >= 12)
6605         &&( (*data == DSP_UDATA_INDICATION_DCD_ON)
6606           ||(*data == DSP_UDATA_INDICATION_CTS_ON)) )
6607       {
6608         word conn_opt, ncpi_opt = 0x00;
6609 /*      HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */
6610
6611         if (*data == DSP_UDATA_INDICATION_DCD_ON)
6612           plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED;
6613         if (*data == DSP_UDATA_INDICATION_CTS_ON)
6614           plci->ncpi_state |= NCPI_MDM_CTS_ON_RECEIVED;
6615
6616         data++;    /* indication code */
6617         data += 2; /* timestamp */
6618         if ((*data == DSP_CONNECTED_NORM_V18) || (*data == DSP_CONNECTED_NORM_VOWN))
6619           ncpi_state &= ~(NCPI_MDM_DCD_ON_RECEIVED | NCPI_MDM_CTS_ON_RECEIVED);
6620         data++;    /* connected norm */
6621         conn_opt = GET_WORD(data);
6622         data += 2; /* connected options */
6623
6624         PUT_WORD (&(plci->ncpi_buffer[1]), (word)(GET_DWORD(data) & 0x0000FFFF));
6625
6626         if (conn_opt & DSP_CONNECTED_OPTION_MASK_V42)
6627         {
6628           ncpi_opt |= MDM_NCPI_ECM_V42;
6629         }
6630         else if (conn_opt & DSP_CONNECTED_OPTION_MASK_MNP)
6631         {
6632           ncpi_opt |= MDM_NCPI_ECM_MNP;
6633         }
6634         else
6635         {
6636           ncpi_opt |= MDM_NCPI_TRANSPARENT;
6637         }
6638         if (conn_opt & DSP_CONNECTED_OPTION_MASK_COMPRESSION)
6639         {
6640           ncpi_opt |= MDM_NCPI_COMPRESSED;
6641         }
6642         PUT_WORD (&(plci->ncpi_buffer[3]), ncpi_opt);
6643         plci->ncpi_buffer[0] = 4;
6644
6645         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND | NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6646       }
6647     }
6648     if (plci->B3_prot == 7)
6649     {
6650       if (((a->ncci_state[ncci] == INC_ACT_PENDING) || (a->ncci_state[ncci] == OUTG_CON_PENDING))
6651        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6652        && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6653       {
6654         a->ncci_state[ncci] = INC_ACT_PENDING;
6655         sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6656         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6657       }
6658     }
6659
6660     if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
6661         & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
6662      || !(ncpi_state & NCPI_MDM_DCD_ON_RECEIVED)
6663      || !(ncpi_state & NCPI_MDM_CTS_ON_RECEIVED))
6664
6665     {
6666       plci->NL.RNR = 2;
6667       return;
6668     }
6669   }
6670
6671   if(plci->NL.complete == 2)
6672     {
6673     if (((plci->NL.Ind &0x0f) == N_UDATA)
6674      && !(udata_forwarding_table[plci->RData[0].P[0] >> 5] & (1L << (plci->RData[0].P[0] & 0x1f))))
6675     {
6676       switch(plci->RData[0].P[0])
6677       {
6678
6679       case DTMF_UDATA_INDICATION_FAX_CALLING_TONE:
6680         if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6681           sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01X");
6682         break;
6683       case DTMF_UDATA_INDICATION_ANSWER_TONE:
6684         if (plci->dtmf_rec_active & DTMF_LISTEN_ACTIVE_FLAG)
6685           sendf(plci->appl, _FACILITY_I, Id & 0xffffL, 0,"ws", SELECTOR_DTMF, "\x01Y");
6686         break;
6687       case DTMF_UDATA_INDICATION_DIGITS_RECEIVED:
6688         dtmf_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6689         break;
6690       case DTMF_UDATA_INDICATION_DIGITS_SENT:
6691         dtmf_confirmation (Id, plci);
6692         break;
6693
6694
6695       case UDATA_INDICATION_MIXER_TAP_DATA:
6696         capidtmf_recv_process_block (&(plci->capidtmf_state), plci->RData[0].P + 1, (word)(plci->RData[0].PLength - 1));
6697  i = capidtmf_indication (&(plci->capidtmf_state), dtmf_code_buffer + 1);
6698  if (i != 0)
6699  {
6700    dtmf_code_buffer[0] = DTMF_UDATA_INDICATION_DIGITS_RECEIVED;
6701           dtmf_indication (Id, plci, dtmf_code_buffer, (word)(i + 1));
6702  }
6703         break;
6704
6705
6706       case UDATA_INDICATION_MIXER_COEFS_SET:
6707         mixer_indication_coefs_set (Id, plci);
6708         break;
6709       case UDATA_INDICATION_XCONNECT_FROM:
6710         mixer_indication_xconnect_from (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6711         break;
6712       case UDATA_INDICATION_XCONNECT_TO:
6713         mixer_indication_xconnect_to (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6714         break;
6715
6716
6717       case LEC_UDATA_INDICATION_DISABLE_DETECT:
6718         ec_indication (Id, plci, plci->RData[0].P, plci->RData[0].PLength);
6719         break;
6720
6721
6722
6723       default:
6724         break;
6725       }
6726     }
6727     else
6728   {
6729       if ((plci->RData[0].PLength != 0)
6730      && ((plci->B2_prot == B2_V120_ASYNC)
6731       || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
6732       || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
6733     {
6734
6735       sendf(plci->appl,_DATA_B3_I,Id,0,
6736             "dwww",
6737             plci->RData[1].P,
6738               (plci->NL.RNum < 2) ? 0 : plci->RData[1].PLength,
6739             plci->RNum,
6740             plci->RFlags);
6741
6742     }
6743     else
6744     {
6745
6746       sendf(plci->appl,_DATA_B3_I,Id,0,
6747             "dwww",
6748             plci->RData[0].P,
6749             plci->RData[0].PLength,
6750             plci->RNum,
6751             plci->RFlags);
6752
6753     }
6754     }
6755     return;
6756   }
6757
6758   fax_feature_bits = 0;
6759   if((plci->NL.Ind &0x0f)==N_CONNECT ||
6760      (plci->NL.Ind &0x0f)==N_CONNECT_ACK ||
6761      (plci->NL.Ind &0x0f)==N_DISC ||
6762      (plci->NL.Ind &0x0f)==N_EDATA ||
6763      (plci->NL.Ind &0x0f)==N_DISC_ACK)
6764   {
6765     info = 0;
6766     plci->ncpi_buffer[0] = 0;
6767     switch (plci->B3_prot) {
6768     case  0: /*XPARENT*/
6769     case  1: /*T.90 NL*/
6770       break;    /* no network control protocol info - jfr */
6771     case  2: /*ISO8202*/
6772     case  3: /*X25 DCE*/
6773       for(i=0; i<plci->NL.RLength; i++) plci->ncpi_buffer[4+i] = plci->NL.RBuffer->P[i];
6774       plci->ncpi_buffer[0] = (byte)(i+3);
6775       plci->ncpi_buffer[1] = (byte)(plci->NL.Ind &N_D_BIT? 1:0);
6776       plci->ncpi_buffer[2] = 0;
6777       plci->ncpi_buffer[3] = 0;
6778       break;
6779     case  4: /*T.30 - FAX*/
6780     case  5: /*T.30 - FAX*/
6781       if(plci->NL.RLength>=sizeof(T30_INFO))
6782       {
6783         dbug(1,dprintf("FaxStatus %04x", ((T30_INFO   *)plci->NL.RBuffer->P)->code));
6784         len = 9;
6785         PUT_WORD(&(plci->ncpi_buffer[1]),((T30_INFO   *)plci->NL.RBuffer->P)->rate_div_2400 * 2400);
6786         fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
6787         i = (((T30_INFO   *)plci->NL.RBuffer->P)->resolution & T30_RESOLUTION_R8_0770_OR_200) ? 0x0001 : 0x0000;
6788         if (plci->B3_prot == 5)
6789         {
6790           if (!(fax_feature_bits & T30_FEATURE_BIT_ECM))
6791             i |= 0x8000; /* This is not an ECM connection */
6792           if (fax_feature_bits & T30_FEATURE_BIT_T6_CODING)
6793             i |= 0x4000; /* This is a connection with MMR compression */
6794           if (fax_feature_bits & T30_FEATURE_BIT_2D_CODING)
6795             i |= 0x2000; /* This is a connection with MR compression */
6796           if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
6797             i |= 0x0004; /* More documents */
6798           if (fax_feature_bits & T30_FEATURE_BIT_POLLING)
6799             i |= 0x0002; /* Fax-polling indication */
6800         }
6801         dbug(1,dprintf("FAX Options %04x %04x",fax_feature_bits,i));
6802         PUT_WORD(&(plci->ncpi_buffer[3]),i);
6803         PUT_WORD(&(plci->ncpi_buffer[5]),((T30_INFO   *)plci->NL.RBuffer->P)->data_format);
6804         plci->ncpi_buffer[7] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_low;
6805         plci->ncpi_buffer[8] = ((T30_INFO   *)plci->NL.RBuffer->P)->pages_high;
6806         plci->ncpi_buffer[len] = 0;
6807         if(((T30_INFO   *)plci->NL.RBuffer->P)->station_id_len)
6808         {
6809           plci->ncpi_buffer[len] = 20;
6810           for (i = 0; i < 20; i++)
6811             plci->ncpi_buffer[++len] = ((T30_INFO   *)plci->NL.RBuffer->P)->station_id[i];
6812         }
6813         if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6814         {
6815           if (((T30_INFO   *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
6816             info = fax_info[((T30_INFO   *)plci->NL.RBuffer->P)->code];
6817           else
6818             info = _FAX_PROTOCOL_ERROR;
6819         }
6820
6821         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
6822           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
6823         {
6824           i = ((word)(((T30_INFO *) 0)->station_id + 20)) + ((T30_INFO   *)plci->NL.RBuffer->P)->head_line_len;
6825           while (i < plci->NL.RBuffer->length)
6826             plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
6827         }
6828
6829         plci->ncpi_buffer[0] = len;
6830         fax_feature_bits = GET_WORD(&((T30_INFO   *)plci->NL.RBuffer->P)->feature_bits_low);
6831         PUT_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->feature_bits_low, fax_feature_bits);
6832
6833         plci->ncpi_state |= NCPI_VALID_CONNECT_B3_IND;
6834  if (((plci->NL.Ind &0x0f) == N_CONNECT_ACK)
6835          || (((plci->NL.Ind &0x0f) == N_CONNECT)
6836           && (fax_feature_bits & T30_FEATURE_BIT_POLLING))
6837          || (((plci->NL.Ind &0x0f) == N_EDATA)
6838           && ((((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_TRAIN_OK)
6839            || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6840            || (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DTC))))
6841  {
6842           plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT;
6843  }
6844  if (((plci->NL.Ind &0x0f) == N_DISC)
6845   || ((plci->NL.Ind &0x0f) == N_DISC_ACK)
6846   || (((plci->NL.Ind &0x0f) == N_EDATA)
6847    && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_EOP_CAPI)))
6848  {
6849           plci->ncpi_state |= NCPI_VALID_CONNECT_B3_ACT | NCPI_VALID_DISC_B3_IND;
6850  }
6851       }
6852       break;
6853
6854     case B3_RTP:
6855       if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
6856       {
6857         if (plci->NL.RLength != 0)
6858         {
6859           info = rtp_info[plci->NL.RBuffer->P[0]];
6860           plci->ncpi_buffer[0] = plci->NL.RLength - 1;
6861           for (i = 1; i < plci->NL.RLength; i++)
6862             plci->ncpi_buffer[i] = plci->NL.RBuffer->P[i];
6863         }
6864       }
6865       break;
6866
6867     }
6868     plci->NL.RNR = 2;
6869   }
6870   switch(plci->NL.Ind &0x0f) {
6871   case N_EDATA:
6872     if ((plci->B3_prot == 4) || (plci->B3_prot == 5))
6873     {
6874       dbug(1,dprintf("EDATA ncci=0x%x state=%d code=%02x", ncci, a->ncci_state[ncci],
6875         ((T30_INFO   *)plci->NL.RBuffer->P)->code));
6876       fax_send_edata_ack = (((T30_INFO   *)(plci->fax_connect_info_buffer))->operating_mode == T30_OPERATING_MODE_CAPI_NEG);
6877
6878       if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
6879        && (plci->nsf_control_bits & (T30_NSF_CONTROL_BIT_NEGOTIATE_IND | T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
6880        && (((T30_INFO   *)plci->NL.RBuffer->P)->code == EDATA_T30_DIS)
6881        && (a->ncci_state[ncci] == OUTG_CON_PENDING)
6882        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6883        && !(plci->ncpi_state & NCPI_NEGOTIATE_B3_SENT))
6884       {
6885         ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code;
6886         sendf(plci->appl,_MANUFACTURER_I,Id,0,"dwbS",_DI_MANU_ID,_DI_NEGOTIATE_B3,
6887           (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
6888         plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
6889  if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
6890    fax_send_edata_ack = false;
6891       }
6892
6893       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
6894       {
6895         switch (((T30_INFO   *)plci->NL.RBuffer->P)->code)
6896         {
6897         case EDATA_T30_DIS:
6898           if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
6899            && !(GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) & T30_CONTROL_BIT_REQUEST_POLLING)
6900            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6901            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6902           {
6903             a->ncci_state[ncci] = INC_ACT_PENDING;
6904             if (plci->B3_prot == 4)
6905               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6906             else
6907               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6908             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6909           }
6910           break;
6911
6912         case EDATA_T30_TRAIN_OK:
6913           if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6914            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6915            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6916           {
6917             if (plci->B3_prot == 4)
6918               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6919             else
6920               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6921             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6922           }
6923           break;
6924
6925         case EDATA_T30_EOP_CAPI:
6926           if (a->ncci_state[ncci] == CONNECTED)
6927           {
6928             sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
6929             a->ncci_state[ncci] = INC_DIS_PENDING;
6930             plci->ncpi_state = 0;
6931      fax_send_edata_ack = false;
6932           }
6933           break;
6934         }
6935       }
6936       else
6937       {
6938         switch (((T30_INFO   *)plci->NL.RBuffer->P)->code)
6939         {
6940         case EDATA_T30_TRAIN_OK:
6941           if ((a->ncci_state[ncci] == INC_ACT_PENDING)
6942            && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
6943            && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
6944           {
6945             if (plci->B3_prot == 4)
6946               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
6947             else
6948               sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
6949             plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
6950           }
6951           break;
6952         }
6953       }
6954       if (fax_send_edata_ack)
6955       {
6956         ((T30_INFO   *)(plci->fax_connect_info_buffer))->code = ((T30_INFO   *)plci->NL.RBuffer->P)->code;
6957  plci->fax_edata_ack_length = 1;
6958         start_internal_command (Id, plci, fax_edata_ack_command);
6959       }
6960     }
6961     else
6962     {
6963       dbug(1,dprintf("EDATA ncci=0x%x state=%d", ncci, a->ncci_state[ncci]));
6964     }
6965     break;
6966   case N_CONNECT:
6967     if (!a->ch_ncci[ch])
6968     {
6969       ncci = get_ncci (plci, ch, 0);
6970       Id = (Id & 0xffff) | (((dword) ncci) << 16);
6971     }
6972     dbug(1,dprintf("N_CONNECT: ch=%d state=%d plci=%lx plci_Id=%lx plci_State=%d",
6973       ch, a->ncci_state[ncci], a->ncci_plci[ncci], plci->Id, plci->State));
6974
6975     msg = _CONNECT_B3_I;
6976     if (a->ncci_state[ncci] == IDLE)
6977       plci->channels++;
6978     else if (plci->B3_prot == 1)
6979       msg = _CONNECT_B3_T90_ACTIVE_I;
6980
6981     a->ncci_state[ncci] = INC_CON_PENDING;
6982     if(plci->B3_prot == 4)
6983       sendf(plci->appl,msg,Id,0,"s","");
6984     else
6985       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
6986     break;
6987   case N_CONNECT_ACK:
6988     dbug(1,dprintf("N_connect_Ack"));
6989     if (plci->internal_command_queue[0]
6990      && ((plci->adjust_b_state == ADJUST_B_CONNECT_2)
6991       || (plci->adjust_b_state == ADJUST_B_CONNECT_3)
6992       || (plci->adjust_b_state == ADJUST_B_CONNECT_4)))
6993     {
6994       (*(plci->internal_command_queue[0]))(Id, plci, 0);
6995       if (!plci->internal_command)
6996         next_internal_command (Id, plci);
6997       break;
6998     }
6999     msg = _CONNECT_B3_ACTIVE_I;
7000     if (plci->B3_prot == 1)
7001     {
7002       if (a->ncci_state[ncci] != OUTG_CON_PENDING)
7003         msg = _CONNECT_B3_T90_ACTIVE_I;
7004       a->ncci_state[ncci] = INC_ACT_PENDING;
7005       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7006     }
7007     else if ((plci->B3_prot == 4) || (plci->B3_prot == 5) || (plci->B3_prot == 7))
7008     {
7009       if ((a->ncci_state[ncci] == OUTG_CON_PENDING)
7010        && (plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
7011        && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
7012       {
7013         a->ncci_state[ncci] = INC_ACT_PENDING;
7014         if (plci->B3_prot == 4)
7015           sendf(plci->appl,msg,Id,0,"s","");
7016         else
7017           sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7018         plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
7019       }
7020     }
7021     else
7022     {
7023       a->ncci_state[ncci] = INC_ACT_PENDING;
7024       sendf(plci->appl,msg,Id,0,"S",plci->ncpi_buffer);
7025     }
7026     if (plci->adjust_b_restore)
7027     {
7028       plci->adjust_b_restore = false;
7029       start_internal_command (Id, plci, adjust_b_restore);
7030     }
7031     break;
7032   case N_DISC:
7033   case N_DISC_ACK:
7034     if (plci->internal_command_queue[0]
7035      && ((plci->internal_command == FAX_DISCONNECT_COMMAND_1)
7036       || (plci->internal_command == FAX_DISCONNECT_COMMAND_2)
7037       || (plci->internal_command == FAX_DISCONNECT_COMMAND_3)))
7038     {
7039       (*(plci->internal_command_queue[0]))(Id, plci, 0);
7040       if (!plci->internal_command)
7041         next_internal_command (Id, plci);
7042     }
7043     ncci_state = a->ncci_state[ncci];
7044     ncci_remove (plci, ncci, false);
7045
7046         /* with N_DISC or N_DISC_ACK the IDI frees the respective   */
7047         /* channel, so we cannot store the state in ncci_state! The */
7048         /* information which channel we received a N_DISC is thus   */
7049         /* stored in the inc_dis_ncci_table buffer.                 */
7050     for(i=0; plci->inc_dis_ncci_table[i]; i++);
7051     plci->inc_dis_ncci_table[i] = (byte) ncci;
7052
7053       /* need a connect_b3_ind before a disconnect_b3_ind with FAX */
7054     if (!plci->channels
7055      && (plci->B1_resource == 16)
7056      && (plci->State <= CONNECTED))
7057     {
7058       len = 9;
7059       i = ((T30_INFO   *)plci->fax_connect_info_buffer)->rate_div_2400 * 2400;
7060       PUT_WORD (&plci->ncpi_buffer[1], i);
7061       PUT_WORD (&plci->ncpi_buffer[3], 0);
7062       i = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format;
7063       PUT_WORD (&plci->ncpi_buffer[5], i);
7064       PUT_WORD (&plci->ncpi_buffer[7], 0);
7065       plci->ncpi_buffer[len] = 0;
7066       plci->ncpi_buffer[0] = len;
7067       if(plci->B3_prot == 4)
7068         sendf(plci->appl,_CONNECT_B3_I,Id,0,"s","");
7069       else
7070       {
7071
7072         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
7073           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
7074         {
7075           plci->ncpi_buffer[++len] = 0;
7076           plci->ncpi_buffer[++len] = 0;
7077           plci->ncpi_buffer[++len] = 0;
7078           plci->ncpi_buffer[0] = len;
7079         }
7080
7081         sendf(plci->appl,_CONNECT_B3_I,Id,0,"S",plci->ncpi_buffer);
7082       }
7083       sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7084       plci->ncpi_state = 0;
7085       sig_req(plci,HANGUP,0);
7086       send_req(plci);
7087       plci->State = OUTG_DIS_PENDING;
7088       /* disc here */
7089     }
7090     else if ((a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
7091      && ((plci->B3_prot == 4) || (plci->B3_prot == 5))
7092      && ((ncci_state == INC_DIS_PENDING) || (ncci_state == IDLE)))
7093     {
7094       if (ncci_state == IDLE)
7095       {
7096         if (plci->channels)
7097           plci->channels--;
7098         if((plci->State==IDLE || plci->State==SUSPENDING) && !plci->channels){
7099           if(plci->State == SUSPENDING){
7100             sendf(plci->appl,
7101                   _FACILITY_I,
7102                   Id & 0xffffL,
7103                   0,
7104                   "ws", (word)3, "\x03\x04\x00\x00");
7105             sendf(plci->appl, _DISCONNECT_I, Id & 0xffffL, 0, "w", 0);
7106           }
7107           plci_remove(plci);
7108           plci->State=IDLE;
7109         }
7110       }
7111     }
7112     else if (plci->channels)
7113     {
7114       sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",info,plci->ncpi_buffer);
7115       plci->ncpi_state = 0;
7116       if ((ncci_state == OUTG_REJ_PENDING)
7117        && ((plci->B3_prot != B3_T90NL) && (plci->B3_prot != B3_ISO8208) && (plci->B3_prot != B3_X25_DCE)))
7118       {
7119         sig_req(plci,HANGUP,0);
7120         send_req(plci);
7121         plci->State = OUTG_DIS_PENDING;
7122       }
7123     }
7124     break;
7125   case N_RESET:
7126     a->ncci_state[ncci] = INC_RES_PENDING;
7127     sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7128     break;
7129   case N_RESET_ACK:
7130     a->ncci_state[ncci] = CONNECTED;
7131     sendf(plci->appl,_RESET_B3_I,Id,0,"S",plci->ncpi_buffer);
7132     break;
7133
7134   case N_UDATA:
7135     if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
7136     {
7137       plci->RData[0].P = plci->internal_ind_buffer + (-((int)(plci->internal_ind_buffer)) & 3);
7138       plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
7139       plci->NL.R = plci->RData;
7140       plci->NL.RNum = 1;
7141       return;
7142     }
7143   case N_BDATA:
7144   case N_DATA:
7145     if (((a->ncci_state[ncci] != CONNECTED) && (plci->B2_prot == 1)) /* transparent */
7146      || (a->ncci_state[ncci] == IDLE)
7147      || (a->ncci_state[ncci] == INC_DIS_PENDING))
7148     {
7149       plci->NL.RNR = 2;
7150       break;
7151     }
7152     if ((a->ncci_state[ncci] != CONNECTED)
7153      && (a->ncci_state[ncci] != OUTG_DIS_PENDING)
7154      && (a->ncci_state[ncci] != OUTG_REJ_PENDING))
7155     {
7156       dbug(1,dprintf("flow control"));
7157       plci->NL.RNR = 1; /* flow control  */
7158       channel_x_off (plci, ch, 0);
7159       break;
7160     }
7161
7162     NCCIcode = ncci | (((word)a->Id) << 8);
7163
7164                 /* count all buffers within the Application pool    */
7165                 /* belonging to the same NCCI. If this is below the */
7166                 /* number of buffers available per NCCI we accept   */
7167                 /* this packet, otherwise we reject it              */
7168     count = 0;
7169     Num = 0xffff;
7170     for(i=0; i<APPLptr->MaxBuffer; i++) {
7171       if(NCCIcode==APPLptr->DataNCCI[i]) count++;
7172       if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
7173     }
7174
7175     if(count>=APPLptr->MaxNCCIData || Num==0xffff)
7176     {
7177       dbug(3,dprintf("Flow-Control"));
7178       plci->NL.RNR = 1;
7179       if( ++(APPLptr->NCCIDataFlowCtrlTimer)>=
7180        (word)((a->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL) ? 40 : 2000))
7181       {
7182         plci->NL.RNR = 2;
7183         dbug(3,dprintf("DiscardData"));
7184       } else {
7185         channel_x_off (plci, ch, 0);
7186       }
7187       break;
7188     }
7189     else
7190     {
7191       APPLptr->NCCIDataFlowCtrlTimer = 0;
7192     }
7193
7194     plci->RData[0].P = ReceiveBufferGet(APPLptr,Num);
7195     if(!plci->RData[0].P) {
7196       plci->NL.RNR = 1;
7197       channel_x_off (plci, ch, 0);
7198       break;
7199     }
7200
7201     APPLptr->DataNCCI[Num] = NCCIcode;
7202     APPLptr->DataFlags[Num] = (plci->Id<<8) | (plci->NL.Ind>>4);
7203     dbug(3,dprintf("Buffer(%d), Max = %d",Num,APPLptr->MaxBuffer));
7204
7205     plci->RNum = Num;
7206     plci->RFlags = plci->NL.Ind>>4;
7207     plci->RData[0].PLength = APPLptr->MaxDataLength;
7208     plci->NL.R = plci->RData;
7209     if ((plci->NL.RLength != 0)
7210      && ((plci->B2_prot == B2_V120_ASYNC)
7211       || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
7212       || (plci->B2_prot == B2_V120_BIT_TRANSPARENT)))
7213     {
7214       plci->RData[1].P = plci->RData[0].P;
7215       plci->RData[1].PLength = plci->RData[0].PLength;
7216       plci->RData[0].P = v120_header_buffer + (-((int) v120_header_buffer) & 3);
7217       if ((plci->NL.RBuffer->P[0] & V120_HEADER_EXTEND_BIT) || (plci->NL.RLength == 1))
7218         plci->RData[0].PLength = 1;
7219       else
7220         plci->RData[0].PLength = 2;
7221       if (plci->NL.RBuffer->P[0] & V120_HEADER_BREAK_BIT)
7222         plci->RFlags |= 0x0010;
7223       if (plci->NL.RBuffer->P[0] & (V120_HEADER_C1_BIT | V120_HEADER_C2_BIT))
7224         plci->RFlags |= 0x8000;
7225       plci->NL.RNum = 2;
7226     }
7227     else
7228     {
7229       if((plci->NL.Ind &0x0f)==N_UDATA)
7230         plci->RFlags |= 0x0010;
7231
7232       else if ((plci->B3_prot == B3_RTP) && ((plci->NL.Ind & 0x0f) == N_BDATA))
7233         plci->RFlags |= 0x0001;
7234
7235       plci->NL.RNum = 1;
7236     }
7237     break;
7238   case N_DATA_ACK:
7239     data_ack (plci, ch);
7240     break;
7241   default:
7242     plci->NL.RNR = 2;
7243     break;
7244   }
7245 }
7246
7247 /*------------------------------------------------------------------*/
7248 /* find a free PLCI                                                 */
7249 /*------------------------------------------------------------------*/
7250
7251 word get_plci(DIVA_CAPI_ADAPTER   * a)
7252 {
7253   word i,j;
7254   PLCI   * plci;
7255
7256   dump_plcis (a);
7257   for(i=0;i<a->max_plci && a->plci[i].Id;i++);
7258   if(i==a->max_plci) {
7259     dbug(1,dprintf("get_plci: out of PLCIs"));
7260     return 0;
7261   }
7262   plci = &a->plci[i];
7263   plci->Id = (byte)(i+1);
7264
7265   plci->Sig.Id = 0;
7266   plci->NL.Id = 0;
7267   plci->sig_req = 0;
7268   plci->nl_req = 0;
7269
7270   plci->appl = NULL;
7271   plci->relatedPTYPLCI = NULL;
7272   plci->State = IDLE;
7273   plci->SuppState = IDLE;
7274   plci->channels = 0;
7275   plci->tel = 0;
7276   plci->B1_resource = 0;
7277   plci->B2_prot = 0;
7278   plci->B3_prot = 0;
7279
7280   plci->command = 0;
7281   plci->m_command = 0;
7282   init_internal_command_queue (plci);
7283   plci->number = 0;
7284   plci->req_in_start = 0;
7285   plci->req_in = 0;
7286   plci->req_out = 0;
7287   plci->msg_in_write_pos = MSG_IN_QUEUE_SIZE;
7288   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
7289   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
7290
7291   plci->data_sent = false;
7292   plci->send_disc = 0;
7293   plci->sig_global_req = 0;
7294   plci->sig_remove_id = 0;
7295   plci->nl_global_req = 0;
7296   plci->nl_remove_id = 0;
7297   plci->adv_nl = 0;
7298   plci->manufacturer = false;
7299   plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
7300   plci->spoofed_msg = 0;
7301   plci->ptyState = 0;
7302   plci->cr_enquiry = false;
7303   plci->hangup_flow_ctrl_timer = 0;
7304
7305   plci->ncci_ring_list = 0;
7306   for(j=0;j<MAX_CHANNELS_PER_PLCI;j++) plci->inc_dis_ncci_table[j] = 0;
7307   clear_c_ind_mask (plci);
7308   set_group_ind_mask (plci);
7309   plci->fax_connect_info_length = 0;
7310   plci->nsf_control_bits = 0;
7311   plci->ncpi_state = 0x00;
7312   plci->ncpi_buffer[0] = 0;
7313
7314   plci->requested_options_conn = 0;
7315   plci->requested_options = 0;
7316   plci->notifiedcall = 0;
7317   plci->vswitchstate = 0;
7318   plci->vsprot = 0;
7319   plci->vsprotdialect = 0;
7320   init_b1_config (plci);
7321   dbug(1,dprintf("get_plci(%x)",plci->Id));
7322   return i+1;
7323 }
7324
7325 /*------------------------------------------------------------------*/
7326 /* put a parameter in the parameter buffer                          */
7327 /*------------------------------------------------------------------*/
7328
7329 static void add_p(PLCI   * plci, byte code, byte   * p)
7330 {
7331   word p_length;
7332
7333   p_length = 0;
7334   if(p) p_length = p[0];
7335   add_ie(plci, code, p, p_length);
7336 }
7337
7338 /*------------------------------------------------------------------*/
7339 /* put a structure in the parameter buffer                          */
7340 /*------------------------------------------------------------------*/
7341 static void add_s(PLCI   * plci, byte code, API_PARSE * p)
7342 {
7343   if(p) add_ie(plci, code, p->info, (word)p->length);
7344 }
7345
7346 /*------------------------------------------------------------------*/
7347 /* put multiple structures in the parameter buffer                  */
7348 /*------------------------------------------------------------------*/
7349 static void add_ss(PLCI   * plci, byte code, API_PARSE * p)
7350 {
7351   byte i;
7352
7353   if(p){
7354     dbug(1,dprintf("add_ss(%x,len=%d)",code,p->length));
7355     for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7356       dbug(1,dprintf("add_ss_ie(%x,len=%d)",p->info[i-1],p->info[i]));
7357       add_ie(plci, p->info[i-1], (byte   *)&(p->info[i]), (word)p->info[i]);
7358     }
7359   }
7360 }
7361
7362 /*------------------------------------------------------------------*/
7363 /* return the channel number sent by the application in a esc_chi   */
7364 /*------------------------------------------------------------------*/
7365 static byte getChannel(API_PARSE * p)
7366 {
7367   byte i;
7368
7369   if(p){
7370     for(i=2;i<(byte)p->length;i+=p->info[i]+2){
7371       if(p->info[i]==2){
7372         if(p->info[i-1]==ESC && p->info[i+1]==CHI) return (p->info[i+2]);
7373       }
7374     }
7375   }
7376   return 0;
7377 }
7378
7379
7380 /*------------------------------------------------------------------*/
7381 /* put an information element in the parameter buffer               */
7382 /*------------------------------------------------------------------*/
7383
7384 static void add_ie(PLCI   * plci, byte code, byte   * p, word p_length)
7385 {
7386   word i;
7387
7388   if(!(code &0x80) && !p_length) return;
7389
7390   if(plci->req_in==plci->req_in_start) {
7391     plci->req_in +=2;
7392   }
7393   else {
7394     plci->req_in--;
7395   }
7396   plci->RBuffer[plci->req_in++] = code;
7397
7398   if(p) {
7399     plci->RBuffer[plci->req_in++] = (byte)p_length;
7400     for(i=0;i<p_length;i++) plci->RBuffer[plci->req_in++] = p[1+i];
7401   }
7402
7403   plci->RBuffer[plci->req_in++] = 0;
7404 }
7405
7406 /*------------------------------------------------------------------*/
7407 /* put a unstructured data into the buffer                          */
7408 /*------------------------------------------------------------------*/
7409
7410 void add_d(PLCI   * plci, word length, byte   * p)
7411 {
7412   word i;
7413
7414   if(plci->req_in==plci->req_in_start) {
7415     plci->req_in +=2;
7416   }
7417   else {
7418     plci->req_in--;
7419   }
7420   for(i=0;i<length;i++) plci->RBuffer[plci->req_in++] = p[i];
7421 }
7422
7423 /*------------------------------------------------------------------*/
7424 /* put parameters from the Additional Info parameter in the         */
7425 /* parameter buffer                                                 */
7426 /*------------------------------------------------------------------*/
7427
7428 void add_ai(PLCI   * plci, API_PARSE * ai)
7429 {
7430   word i;
7431     API_PARSE ai_parms[5];
7432
7433   for(i=0;i<5;i++) ai_parms[i].length = 0;
7434
7435   if(!ai->length)
7436     return;
7437   if(api_parse(&ai->info[1], (word)ai->length, "ssss", ai_parms))
7438     return;
7439
7440   add_s (plci,KEY,&ai_parms[1]);
7441   add_s (plci,UUI,&ai_parms[2]);
7442   add_ss(plci,FTY,&ai_parms[3]);
7443 }
7444
7445 /*------------------------------------------------------------------*/
7446 /* put parameter for b1 protocol in the parameter buffer            */
7447 /*------------------------------------------------------------------*/
7448
7449 word add_b1(PLCI   * plci, API_PARSE * bp, word b_channel_info, word b1_facilities)
7450 {
7451     API_PARSE bp_parms[8];
7452     API_PARSE mdm_cfg[9];
7453     API_PARSE global_config[2];
7454     byte cai[256];
7455   byte resource[] = {5,9,13,12,16,39,9,17,17,18};
7456   byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
7457   word i;
7458
7459     API_PARSE mdm_cfg_v18[4];
7460   word j, n, w;
7461   dword d;
7462
7463
7464   for(i=0;i<8;i++) bp_parms[i].length = 0;
7465   for(i=0;i<2;i++) global_config[i].length = 0;
7466
7467   dbug(1,dprintf("add_b1"));
7468   api_save_msg(bp, "s", &plci->B_protocol);
7469
7470   if(b_channel_info==2){
7471     plci->B1_resource = 0;
7472     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7473     add_p(plci, CAI, "\x01\x00");
7474     dbug(1,dprintf("Cai=1,0 (no resource)"));
7475     return 0;
7476   }
7477
7478   if(plci->tel == CODEC_PERMANENT) return 0;
7479   else if(plci->tel == CODEC){
7480     plci->B1_resource = 1;
7481     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7482     add_p(plci, CAI, "\x01\x01");
7483     dbug(1,dprintf("Cai=1,1 (Codec)"));
7484     return 0;
7485   }
7486   else if(plci->tel == ADV_VOICE){
7487     plci->B1_resource = add_b1_facilities (plci, 9, (word)(b1_facilities | B1_FACILITY_VOICE));
7488     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities | B1_FACILITY_VOICE));
7489     voice_cai[1] = plci->B1_resource;
7490     PUT_WORD (&voice_cai[5], plci->appl->MaxDataLength);
7491     add_p(plci, CAI, voice_cai);
7492     dbug(1,dprintf("Cai=1,0x%x (AdvVoice)",voice_cai[1]));
7493     return 0;
7494   }
7495   plci->call_dir &= ~(CALL_DIR_ORIGINATE | CALL_DIR_ANSWER);
7496   if (plci->call_dir & CALL_DIR_OUT)
7497     plci->call_dir |= CALL_DIR_ORIGINATE;
7498   else if (plci->call_dir & CALL_DIR_IN)
7499     plci->call_dir |= CALL_DIR_ANSWER;
7500
7501   if(!bp->length){
7502     plci->B1_resource = 0x5;
7503     adjust_b1_facilities (plci, plci->B1_resource, b1_facilities);
7504     add_p(plci, CAI, "\x01\x05");
7505     return 0;
7506   }
7507
7508   dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
7509   if(bp->length>256) return _WRONG_MESSAGE_FORMAT;
7510   if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
7511   {
7512     bp_parms[6].length = 0;
7513     if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
7514     {
7515       dbug(1,dprintf("b-form.!"));
7516       return _WRONG_MESSAGE_FORMAT;
7517     }
7518   }
7519   else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
7520   {
7521     dbug(1,dprintf("b-form.!"));
7522     return _WRONG_MESSAGE_FORMAT;
7523   }
7524
7525   if(bp_parms[6].length)
7526   {
7527     if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
7528     {
7529       return _WRONG_MESSAGE_FORMAT;
7530     }
7531     switch(GET_WORD(global_config[0].info))
7532     {
7533     case 1:
7534       plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
7535       break;
7536     case 2:
7537       plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
7538       break;
7539     }
7540   }
7541   dbug(1,dprintf("call_dir=%04x", plci->call_dir));
7542
7543
7544   if ((GET_WORD(bp_parms[0].info) == B1_RTP)
7545    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
7546   {
7547     plci->B1_resource = add_b1_facilities (plci, 31, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7548     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7549     cai[1] = plci->B1_resource;
7550     cai[2] = 0;
7551     cai[3] = 0;
7552     cai[4] = 0;
7553     PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7554     for (i = 0; i < bp_parms[3].length; i++)
7555       cai[7+i] = bp_parms[3].info[1+i];
7556     cai[0] = 6 + bp_parms[3].length;
7557     add_p(plci, CAI, cai);
7558     return 0;
7559   }
7560
7561
7562   if ((GET_WORD(bp_parms[0].info) == B1_PIAFS)
7563    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))
7564   {
7565     plci->B1_resource = add_b1_facilities (plci, 35/* PIAFS HARDWARE FACILITY */, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7566     adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7567     cai[1] = plci->B1_resource;
7568     cai[2] = 0;
7569     cai[3] = 0;
7570     cai[4] = 0;
7571     PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7572     cai[0] = 6;
7573     add_p(plci, CAI, cai);
7574     return 0;
7575   }
7576
7577
7578   if ((GET_WORD(bp_parms[0].info) >= 32)
7579    || (!((1L << GET_WORD(bp_parms[0].info)) & plci->adapter->profile.B1_Protocols)
7580     && ((GET_WORD(bp_parms[0].info) != 3)
7581      || !((1L << B1_HDLC) & plci->adapter->profile.B1_Protocols)
7582      || ((bp_parms[3].length != 0) && (GET_WORD(&bp_parms[3].info[1]) != 0) && (GET_WORD(&bp_parms[3].info[1]) != 56000)))))
7583   {
7584     return _B1_NOT_SUPPORTED;
7585   }
7586   plci->B1_resource = add_b1_facilities (plci, resource[GET_WORD(bp_parms[0].info)],
7587     (word)(b1_facilities & ~B1_FACILITY_VOICE));
7588   adjust_b1_facilities (plci, plci->B1_resource, (word)(b1_facilities & ~B1_FACILITY_VOICE));
7589   cai[0] = 6;
7590   cai[1] = plci->B1_resource;
7591   for (i=2;i<sizeof(cai);i++) cai[i] = 0;
7592
7593   if ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
7594    || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
7595    || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC))
7596   { /* B1 - modem */
7597     for (i=0;i<7;i++) mdm_cfg[i].length = 0;
7598
7599     if (bp_parms[3].length)
7600     {
7601       if(api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwww", mdm_cfg))
7602       {
7603         return (_WRONG_MESSAGE_FORMAT);
7604       }
7605         
7606       cai[2] = 0; /* Bit rate for adaptation */
7607
7608       dbug(1,dprintf("MDM Max Bit Rate:<%d>", GET_WORD(mdm_cfg[0].info)));
7609
7610       PUT_WORD (&cai[13], 0);                          /* Min Tx speed */
7611       PUT_WORD (&cai[15], GET_WORD(mdm_cfg[0].info)); /* Max Tx speed */
7612       PUT_WORD (&cai[17], 0);                          /* Min Rx speed */
7613       PUT_WORD (&cai[19], GET_WORD(mdm_cfg[0].info)); /* Max Rx speed */
7614
7615       cai[3] = 0; /* Async framing parameters */
7616       switch (GET_WORD (mdm_cfg[2].info))
7617       {       /* Parity     */
7618       case 1: /* odd parity */
7619         cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7620         dbug(1,dprintf("MDM: odd parity"));
7621         break;
7622
7623       case 2: /* even parity */
7624         cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7625         dbug(1,dprintf("MDM: even parity"));
7626         break;
7627
7628       default:
7629         dbug(1,dprintf("MDM: no parity"));
7630         break;
7631       }
7632
7633       switch (GET_WORD (mdm_cfg[3].info))
7634       {       /* stop bits   */
7635       case 1: /* 2 stop bits */
7636         cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7637         dbug(1,dprintf("MDM: 2 stop bits"));
7638         break;
7639
7640       default:
7641         dbug(1,dprintf("MDM: 1 stop bit"));
7642         break;
7643       }
7644
7645       switch (GET_WORD (mdm_cfg[1].info))
7646       {     /* char length */
7647       case 5:
7648         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7649         dbug(1,dprintf("MDM: 5 bits"));
7650         break;
7651
7652       case 6:
7653         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7654         dbug(1,dprintf("MDM: 6 bits"));
7655         break;
7656
7657       case 7:
7658         cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7659         dbug(1,dprintf("MDM: 7 bits"));
7660         break;
7661
7662       default:
7663         dbug(1,dprintf("MDM: 8 bits"));
7664         break;
7665       }
7666
7667       cai[7] = 0; /* Line taking options */
7668       cai[8] = 0; /* Modulation negotiation options */
7669       cai[9] = 0; /* Modulation options */
7670
7671       if (((plci->call_dir & CALL_DIR_ORIGINATE) != 0) ^ ((plci->call_dir & CALL_DIR_OUT) != 0))
7672       {
7673         cai[9] |= DSP_CAI_MODEM_REVERSE_DIRECTION;
7674         dbug(1, dprintf("MDM: Reverse direction"));
7675       }
7676
7677       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RETRAIN)
7678       {
7679         cai[9] |= DSP_CAI_MODEM_DISABLE_RETRAIN;
7680         dbug(1, dprintf("MDM: Disable retrain"));
7681       }
7682
7683       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_DISABLE_RING_TONE)
7684       {
7685         cai[7] |= DSP_CAI_MODEM_DISABLE_CALLING_TONE | DSP_CAI_MODEM_DISABLE_ANSWER_TONE;
7686         dbug(1, dprintf("MDM: Disable ring tone"));
7687       }
7688
7689       if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_1800)
7690       {
7691         cai[8] |= DSP_CAI_MODEM_GUARD_TONE_1800HZ;
7692         dbug(1, dprintf("MDM: 1800 guard tone"));
7693       }
7694       else if (GET_WORD (mdm_cfg[4].info) & MDM_CAPI_GUARD_550 )
7695       {
7696         cai[8] |= DSP_CAI_MODEM_GUARD_TONE_550HZ;
7697         dbug(1, dprintf("MDM: 550 guard tone"));
7698       }
7699
7700       if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_V100)
7701       {
7702         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_V100;
7703         dbug(1, dprintf("MDM: V100"));
7704       }
7705       else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_MOD_CLASS)
7706       {
7707         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_IN_CLASS;
7708         dbug(1, dprintf("MDM: IN CLASS"));
7709       }
7710       else if ((GET_WORD (mdm_cfg[5].info) & 0x00ff) == MDM_CAPI_NEG_DISABLED)
7711       {
7712         cai[8] |= DSP_CAI_MODEM_NEGOTIATE_DISABLED;
7713         dbug(1, dprintf("MDM: DISABLED"));
7714       }
7715       cai[0] = 20;
7716
7717       if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_V18))
7718        && (GET_WORD(mdm_cfg[5].info) & 0x8000)) /* Private V.18 enable */
7719       {
7720         plci->requested_options |= 1L << PRIVATE_V18;
7721       }
7722       if (GET_WORD(mdm_cfg[5].info) & 0x4000) /* Private VOWN enable */
7723         plci->requested_options |= 1L << PRIVATE_VOWN;
7724
7725       if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
7726         & ((1L << PRIVATE_V18) | (1L << PRIVATE_VOWN)))
7727       {
7728         if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwws", mdm_cfg))
7729         {
7730           i = 27;
7731           if (mdm_cfg[6].length >= 4)
7732           {
7733             d = GET_DWORD(&mdm_cfg[6].info[1]);
7734             cai[7] |= (byte) d;          /* line taking options */
7735             cai[9] |= (byte)(d >> 8);    /* modulation options */
7736             cai[++i] = (byte)(d >> 16);  /* vown modulation options */
7737             cai[++i] = (byte)(d >> 24);
7738             if (mdm_cfg[6].length >= 8)
7739             {
7740               d = GET_DWORD(&mdm_cfg[6].info[5]);
7741               cai[10] |= (byte) d;        /* disabled modulations mask */
7742               cai[11] |= (byte)(d >> 8);
7743               if (mdm_cfg[6].length >= 12)
7744               {
7745                 d = GET_DWORD(&mdm_cfg[6].info[9]);
7746                 cai[12] = (byte) d;          /* enabled modulations mask */
7747                 cai[++i] = (byte)(d >> 8);   /* vown enabled modulations */
7748                 cai[++i] = (byte)(d >> 16);
7749                 cai[++i] = (byte)(d >> 24);
7750                 cai[++i] = 0;
7751                 if (mdm_cfg[6].length >= 14)
7752                 {
7753                   w = GET_WORD(&mdm_cfg[6].info[13]);
7754                   if (w != 0)
7755                     PUT_WORD(&cai[13], w);  /* min tx speed */
7756                   if (mdm_cfg[6].length >= 16)
7757                   {
7758                     w = GET_WORD(&mdm_cfg[6].info[15]);
7759                     if (w != 0)
7760                       PUT_WORD(&cai[15], w);  /* max tx speed */
7761                     if (mdm_cfg[6].length >= 18)
7762                     {
7763                       w = GET_WORD(&mdm_cfg[6].info[17]);
7764                       if (w != 0)
7765                         PUT_WORD(&cai[17], w);  /* min rx speed */
7766                       if (mdm_cfg[6].length >= 20)
7767                       {
7768                         w = GET_WORD(&mdm_cfg[6].info[19]);
7769                         if (w != 0)
7770                           PUT_WORD(&cai[19], w);  /* max rx speed */
7771                         if (mdm_cfg[6].length >= 22)
7772                         {
7773                           w = GET_WORD(&mdm_cfg[6].info[21]);
7774                           cai[23] = (byte)(-((short) w));  /* transmit level */
7775                           if (mdm_cfg[6].length >= 24)
7776                           {
7777                             w = GET_WORD(&mdm_cfg[6].info[23]);
7778                             cai[22] |= (byte) w;        /* info options mask */
7779                             cai[21] |= (byte)(w >> 8);  /* disabled symbol rates */
7780                           }
7781                         }
7782                       }
7783                     }
7784                   }
7785                 }
7786               }
7787             }
7788           }
7789           cai[27] = i - 27;
7790           i++;
7791           if (!api_parse(&bp_parms[3].info[1],(word)bp_parms[3].length,"wwwwwwss", mdm_cfg))
7792           {
7793             if (!api_parse(&mdm_cfg[7].info[1],(word)mdm_cfg[7].length,"sss", mdm_cfg_v18))
7794             {
7795               for (n = 0; n < 3; n++)
7796               {
7797                 cai[i] = (byte)(mdm_cfg_v18[n].length);
7798                 for (j = 1; j < ((word)(cai[i] + 1)); j++)
7799                   cai[i+j] = mdm_cfg_v18[n].info[j];
7800                 i += cai[i] + 1;
7801               }
7802             }
7803           }
7804           cai[0] = (byte)(i - 1);
7805         }
7806       }
7807
7808     }
7809   }
7810   if(GET_WORD(bp_parms[0].info)==2 ||                         /* V.110 async */
7811      GET_WORD(bp_parms[0].info)==3 )                          /* V.110 sync */
7812   {
7813     if(bp_parms[3].length){
7814       dbug(1,dprintf("V.110,%d",GET_WORD(&bp_parms[3].info[1])));
7815       switch(GET_WORD(&bp_parms[3].info[1])){                 /* Rate */
7816         case 0:
7817         case 56000:
7818           if(GET_WORD(bp_parms[0].info)==3){                  /* V.110 sync 56k */
7819             dbug(1,dprintf("56k sync HSCX"));
7820             cai[1] = 8;
7821             cai[2] = 0;
7822             cai[3] = 0;
7823           }
7824           else if(GET_WORD(bp_parms[0].info)==2){
7825             dbug(1,dprintf("56k async DSP"));
7826             cai[2] = 9;
7827           }
7828           break;
7829         case 50:     cai[2] = 1;  break;
7830         case 75:     cai[2] = 1;  break;
7831         case 110:    cai[2] = 1;  break;
7832         case 150:    cai[2] = 1;  break;
7833         case 200:    cai[2] = 1;  break;
7834         case 300:    cai[2] = 1;  break;
7835         case 600:    cai[2] = 1;  break;
7836         case 1200:   cai[2] = 2;  break;
7837         case 2400:   cai[2] = 3;  break;
7838         case 4800:   cai[2] = 4;  break;
7839         case 7200:   cai[2] = 10; break;
7840         case 9600:   cai[2] = 5;  break;
7841         case 12000:  cai[2] = 13; break;
7842         case 24000:  cai[2] = 0;  break;
7843         case 14400:  cai[2] = 11; break;
7844         case 19200:  cai[2] = 6;  break;
7845         case 28800:  cai[2] = 12; break;
7846         case 38400:  cai[2] = 7;  break;
7847         case 48000:  cai[2] = 8;  break;
7848         case 76:     cai[2] = 15; break;  /* 75/1200     */
7849         case 1201:   cai[2] = 14; break;  /* 1200/75     */
7850         case 56001:  cai[2] = 9;  break;  /* V.110 56000 */
7851
7852         default:
7853           return _B1_PARM_NOT_SUPPORTED;
7854       }
7855       cai[3] = 0;
7856       if (cai[1] == 13)                                        /* v.110 async */
7857       {
7858         if (bp_parms[3].length >= 8)
7859         {
7860           switch (GET_WORD (&bp_parms[3].info[3]))
7861           {       /* char length */
7862           case 5:
7863             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_5;
7864             break;
7865           case 6:
7866             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_6;
7867             break;
7868           case 7:
7869             cai[3] |= DSP_CAI_ASYNC_CHAR_LENGTH_7;
7870             break;
7871           }
7872           switch (GET_WORD (&bp_parms[3].info[5]))
7873           {       /* Parity     */
7874           case 1: /* odd parity */
7875             cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_ODD);
7876             break;
7877           case 2: /* even parity */
7878             cai[3] |= (DSP_CAI_ASYNC_PARITY_ENABLE | DSP_CAI_ASYNC_PARITY_EVEN);
7879             break;
7880           }
7881           switch (GET_WORD (&bp_parms[3].info[7]))
7882           {       /* stop bits   */
7883           case 1: /* 2 stop bits */
7884             cai[3] |= DSP_CAI_ASYNC_TWO_STOP_BITS;
7885             break;
7886           }
7887         }
7888       }
7889     }
7890     else if(cai[1]==8 || GET_WORD(bp_parms[0].info)==3 ){
7891       dbug(1,dprintf("V.110 default 56k sync"));
7892       cai[1] = 8;
7893       cai[2] = 0;
7894       cai[3] = 0;
7895     }
7896     else {
7897       dbug(1,dprintf("V.110 default 9600 async"));
7898       cai[2] = 5;
7899     }
7900   }
7901   PUT_WORD(&cai[5],plci->appl->MaxDataLength);
7902   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]));
7903 /* HexDump ("CAI", sizeof(cai), &cai[0]); */
7904
7905   add_p(plci, CAI, cai);
7906   return 0;
7907 }
7908
7909 /*------------------------------------------------------------------*/
7910 /* put parameter for b2 and B3  protocol in the parameter buffer    */
7911 /*------------------------------------------------------------------*/
7912
7913 word add_b23(PLCI   * plci, API_PARSE * bp)
7914 {
7915   word i, fax_control_bits;
7916   byte pos, len;
7917   byte SAPI = 0x40;  /* default SAPI 16 for x.31 */
7918     API_PARSE bp_parms[8];
7919   API_PARSE * b1_config;
7920   API_PARSE * b2_config;
7921     API_PARSE b2_config_parms[8];
7922   API_PARSE * b3_config;
7923     API_PARSE b3_config_parms[6];
7924     API_PARSE global_config[2];
7925
7926   static byte llc[3] = {2,0,0};
7927   static byte dlc[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
7928   static byte nlc[256];
7929   static byte lli[12] = {1,1};
7930
7931   const byte llc2_out[] = {1,2,4,6,2,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7932   const byte llc2_in[]  = {1,3,4,6,3,0,0,0, X75_V42BIS,V120_L2,V120_V42BIS,V120_L2,6};
7933
7934   const byte llc3[] = {4,3,2,2,6,6,0};
7935   const byte header[] = {0,2,3,3,0,0,0};
7936
7937   for(i=0;i<8;i++) bp_parms[i].length = 0;
7938   for(i=0;i<6;i++) b2_config_parms[i].length = 0;
7939   for(i=0;i<5;i++) b3_config_parms[i].length = 0;
7940
7941   lli[0] = 1;
7942   lli[1] = 1;
7943   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
7944     lli[1] |= 2;
7945   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
7946     lli[1] |= 4;
7947
7948   if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
7949     lli[1] |= 0x10;
7950     if (plci->rx_dma_descriptor <= 0) {
7951       plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
7952       if (plci->rx_dma_descriptor >= 0)
7953         plci->rx_dma_descriptor++;
7954     }
7955     if (plci->rx_dma_descriptor > 0) {
7956       lli[0] = 6;
7957       lli[1] |= 0x40;
7958       lli[2] = (byte)(plci->rx_dma_descriptor - 1);
7959       lli[3] = (byte)plci->rx_dma_magic;
7960       lli[4] = (byte)(plci->rx_dma_magic >>  8);
7961       lli[5] = (byte)(plci->rx_dma_magic >> 16);
7962       lli[6] = (byte)(plci->rx_dma_magic >> 24);
7963     }
7964   }
7965
7966   if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
7967     lli[1] |= 0x20;
7968   }
7969
7970   dbug(1,dprintf("add_b23"));
7971   api_save_msg(bp, "s", &plci->B_protocol);
7972
7973   if(!bp->length && plci->tel)
7974   {
7975     plci->adv_nl = true;
7976     dbug(1,dprintf("Default adv.Nl"));
7977     add_p(plci,LLI,lli);
7978     plci->B2_prot = 1 /*XPARENT*/;
7979     plci->B3_prot = 0 /*XPARENT*/;
7980     llc[1] = 2;
7981     llc[2] = 4;
7982     add_p(plci, LLC, llc);
7983     dlc[0] = 2;
7984     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
7985     add_p(plci, DLC, dlc);
7986     return 0;
7987   }
7988
7989   if(!bp->length) /*default*/
7990   {   
7991     dbug(1,dprintf("ret default"));
7992     add_p(plci,LLI,lli);
7993     plci->B2_prot = 0 /*X.75   */;
7994     plci->B3_prot = 0 /*XPARENT*/;
7995     llc[1] = 1;
7996     llc[2] = 4;
7997     add_p(plci, LLC, llc);
7998     dlc[0] = 2;
7999     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8000     add_p(plci, DLC, dlc);
8001     return 0;
8002   }
8003   dbug(1,dprintf("b_prot_len=%d",(word)bp->length));
8004   if((word)bp->length > 256)    return _WRONG_MESSAGE_FORMAT;
8005
8006   if(api_parse(&bp->info[1], (word)bp->length, "wwwsssb", bp_parms))
8007   {
8008     bp_parms[6].length = 0;
8009     if(api_parse(&bp->info[1], (word)bp->length, "wwwsss", bp_parms))
8010     {
8011       dbug(1,dprintf("b-form.!"));
8012       return _WRONG_MESSAGE_FORMAT;
8013     }
8014   }
8015   else if (api_parse(&bp->info[1], (word)bp->length, "wwwssss", bp_parms))
8016   {
8017     dbug(1,dprintf("b-form.!"));
8018     return _WRONG_MESSAGE_FORMAT;
8019   }
8020
8021   if(plci->tel==ADV_VOICE) /* transparent B on advanced voice */
8022   {  
8023     if(GET_WORD(bp_parms[1].info)!=1
8024     || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
8025     plci->adv_nl = true;
8026   }
8027   else if(plci->tel) return _B2_NOT_SUPPORTED;
8028
8029
8030   if ((GET_WORD(bp_parms[1].info) == B2_RTP)
8031    && (GET_WORD(bp_parms[2].info) == B3_RTP)
8032    && (plci->adapter->man_profile.private_options & (1L << PRIVATE_RTP)))
8033   {
8034     add_p(plci,LLI,lli);
8035     plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8036     plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8037     llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ? 14 : 13;
8038     llc[2] = 4;
8039     add_p(plci, LLC, llc);
8040     dlc[0] = 2;
8041     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8042     dlc[3] = 3; /* Addr A */
8043     dlc[4] = 1; /* Addr B */
8044     dlc[5] = 7; /* modulo mode */
8045     dlc[6] = 7; /* window size */
8046     dlc[7] = 0; /* XID len Lo  */
8047     dlc[8] = 0; /* XID len Hi  */
8048     for (i = 0; i < bp_parms[4].length; i++)
8049       dlc[9+i] = bp_parms[4].info[1+i];
8050     dlc[0] = (byte)(8 + bp_parms[4].length);
8051     add_p(plci, DLC, dlc);
8052     for (i = 0; i < bp_parms[5].length; i++)
8053       nlc[1+i] = bp_parms[5].info[1+i];
8054     nlc[0] = (byte)(bp_parms[5].length);
8055     add_p(plci, NLC, nlc);
8056     return 0;
8057   }
8058
8059
8060
8061   if ((GET_WORD(bp_parms[1].info) >= 32)
8062    || (!((1L << GET_WORD(bp_parms[1].info)) & plci->adapter->profile.B2_Protocols)
8063     && ((GET_WORD(bp_parms[1].info) != B2_PIAFS)
8064      || !(plci->adapter->man_profile.private_options & (1L << PRIVATE_PIAFS)))))
8065
8066   {
8067     return _B2_NOT_SUPPORTED;
8068   }
8069   if ((GET_WORD(bp_parms[2].info) >= 32)
8070    || !((1L << GET_WORD(bp_parms[2].info)) & plci->adapter->profile.B3_Protocols))
8071   {
8072     return _B3_NOT_SUPPORTED;
8073   }
8074   if ((GET_WORD(bp_parms[1].info) != B2_SDLC)
8075    && ((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8076     || (GET_WORD(bp_parms[0].info) == B1_MODEM_ASYNC)
8077     || (GET_WORD(bp_parms[0].info) == B1_MODEM_SYNC_HDLC)))
8078   {
8079     return (add_modem_b23 (plci, bp_parms));
8080   }
8081
8082   add_p(plci,LLI,lli);
8083
8084   plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8085   plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8086   if(plci->B2_prot==12) SAPI = 0; /* default SAPI D-channel */
8087
8088   if(bp_parms[6].length)
8089   {
8090     if(api_parse(&bp_parms[6].info[1], (word)bp_parms[6].length, "w", global_config))
8091     {
8092       return _WRONG_MESSAGE_FORMAT;
8093     }
8094     switch(GET_WORD(global_config[0].info))
8095     {
8096     case 1:
8097       plci->call_dir = (plci->call_dir & ~CALL_DIR_ANSWER) | CALL_DIR_ORIGINATE;
8098       break;
8099     case 2:
8100       plci->call_dir = (plci->call_dir & ~CALL_DIR_ORIGINATE) | CALL_DIR_ANSWER;
8101       break;
8102     }
8103   }
8104   dbug(1,dprintf("call_dir=%04x", plci->call_dir));
8105
8106
8107   if (plci->B2_prot == B2_PIAFS)
8108     llc[1] = PIAFS_CRC;
8109   else
8110 /* IMPLEMENT_PIAFS */
8111   {
8112     llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8113              llc2_out[GET_WORD(bp_parms[1].info)] : llc2_in[GET_WORD(bp_parms[1].info)];
8114   }
8115   llc[2] = llc3[GET_WORD(bp_parms[2].info)];
8116
8117   add_p(plci, LLC, llc);
8118
8119   dlc[0] = 2;
8120   PUT_WORD(&dlc[1], plci->appl->MaxDataLength +
8121                       header[GET_WORD(bp_parms[2].info)]);
8122
8123   b1_config = &bp_parms[3];
8124   nlc[0] = 0;
8125   if(plci->B3_prot == 4
8126   || plci->B3_prot == 5)
8127   {
8128     for (i=0;i<sizeof(T30_INFO);i++) nlc[i] = 0;
8129     nlc[0] = sizeof(T30_INFO);
8130     if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8131       ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI;
8132     ((T30_INFO *)&nlc[1])->rate_div_2400 = 0xff;
8133     if(b1_config->length>=2)
8134     {
8135       ((T30_INFO *)&nlc[1])->rate_div_2400 = (byte)(GET_WORD(&b1_config->info[1])/2400);
8136     }
8137   }
8138   b2_config = &bp_parms[4];
8139
8140
8141   if (llc[1] == PIAFS_CRC)
8142   {
8143     if (plci->B3_prot != B3_TRANSPARENT)
8144     {
8145       return _B_STACK_NOT_SUPPORTED;
8146     }
8147     if(b2_config->length && api_parse(&b2_config->info[1], (word)b2_config->length, "bwww", b2_config_parms)) {
8148       return _WRONG_MESSAGE_FORMAT;
8149     }
8150     PUT_WORD(&dlc[1],plci->appl->MaxDataLength);
8151     dlc[3] = 0; /* Addr A */
8152     dlc[4] = 0; /* Addr B */
8153     dlc[5] = 0; /* modulo mode */
8154     dlc[6] = 0; /* window size */
8155     if (b2_config->length >= 7){
8156       dlc[ 7] = 7; 
8157       dlc[ 8] = 0; 
8158       dlc[ 9] = b2_config_parms[0].info[0]; /* PIAFS protocol Speed configuration */
8159       dlc[10] = b2_config_parms[1].info[0]; /* V.42bis P0 */
8160       dlc[11] = b2_config_parms[1].info[1]; /* V.42bis P0 */
8161       dlc[12] = b2_config_parms[2].info[0]; /* V.42bis P1 */
8162       dlc[13] = b2_config_parms[2].info[1]; /* V.42bis P1 */
8163       dlc[14] = b2_config_parms[3].info[0]; /* V.42bis P2 */
8164       dlc[15] = b2_config_parms[3].info[1]; /* V.42bis P2 */
8165       dlc[ 0] = 15;
8166       if(b2_config->length >= 8) { /* PIAFS control abilities */
8167         dlc[ 7] = 10; 
8168         dlc[16] = 2; /* Length of PIAFS extention */
8169         dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
8170         dlc[18] = b2_config_parms[4].info[0]; /* value */
8171         dlc[ 0] = 18;
8172       }
8173     }
8174     else /* default values, 64K, variable, no compression */
8175     {
8176       dlc[ 7] = 7; 
8177       dlc[ 8] = 0; 
8178       dlc[ 9] = 0x03; /* PIAFS protocol Speed configuration */
8179       dlc[10] = 0x03; /* V.42bis P0 */
8180       dlc[11] = 0;    /* V.42bis P0 */
8181       dlc[12] = 0;    /* V.42bis P1 */
8182       dlc[13] = 0;    /* V.42bis P1 */
8183       dlc[14] = 0;    /* V.42bis P2 */
8184       dlc[15] = 0;    /* V.42bis P2 */
8185     dlc[ 0] = 15;
8186     }
8187     add_p(plci, DLC, dlc);
8188   }
8189   else
8190
8191   if ((llc[1] == V120_L2) || (llc[1] == V120_V42BIS))
8192   {
8193     if (plci->B3_prot != B3_TRANSPARENT)
8194       return _B_STACK_NOT_SUPPORTED;
8195
8196     dlc[0] = 6;
8197     PUT_WORD (&dlc[1], GET_WORD (&dlc[1]) + 2);
8198     dlc[3] = 0x08;
8199     dlc[4] = 0x01;
8200     dlc[5] = 127;
8201     dlc[6] = 7;
8202     if (b2_config->length != 0)
8203     {
8204       if((llc[1]==V120_V42BIS) && api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms)) {
8205         return _WRONG_MESSAGE_FORMAT;
8206       }
8207       dlc[3] = (byte)((b2_config->info[2] << 3) | ((b2_config->info[1] >> 5) & 0x04));
8208       dlc[4] = (byte)((b2_config->info[1] << 1) | 0x01);
8209       if (b2_config->info[3] != 128)
8210       {
8211         dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8212         return _B2_PARM_NOT_SUPPORTED;
8213       }
8214       dlc[5] = (byte)(b2_config->info[3] - 1);
8215       dlc[6] = b2_config->info[4];
8216       if(llc[1]==V120_V42BIS){
8217         if (b2_config->length >= 10){
8218           dlc[ 7] = 6; 
8219           dlc[ 8] = 0; 
8220           dlc[ 9] = b2_config_parms[4].info[0];
8221           dlc[10] = b2_config_parms[4].info[1];
8222           dlc[11] = b2_config_parms[5].info[0];
8223           dlc[12] = b2_config_parms[5].info[1];
8224           dlc[13] = b2_config_parms[6].info[0];
8225           dlc[14] = b2_config_parms[6].info[1];
8226           dlc[ 0] = 14;
8227           dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8228           dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8229           dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8230         }
8231         else {
8232           dlc[ 6] = 14;
8233         }
8234       }
8235     }
8236   }
8237   else
8238   {
8239     if(b2_config->length)
8240     {
8241       dbug(1,dprintf("B2-Config"));
8242       if(llc[1]==X75_V42BIS){
8243         if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbwww", b2_config_parms))
8244         {
8245           return _WRONG_MESSAGE_FORMAT;
8246         }
8247       }
8248       else {
8249         if(api_parse(&b2_config->info[1], (word)b2_config->length, "bbbbs", b2_config_parms))
8250         {
8251           return _WRONG_MESSAGE_FORMAT;
8252         }
8253       }
8254           /* if B2 Protocol is LAPD, b2_config structure is different */
8255       if(llc[1]==6)
8256       {
8257         dlc[0] = 4;
8258         if(b2_config->length>=1) dlc[2] = b2_config->info[1];      /* TEI */
8259         else dlc[2] = 0x01;
8260         if( (b2_config->length>=2) && (plci->B2_prot==12) )
8261         {
8262           SAPI = b2_config->info[2];    /* SAPI */
8263         }
8264         dlc[1] = SAPI;
8265         if( (b2_config->length>=3) && (b2_config->info[3]==128) )
8266         {
8267           dlc[3] = 127;      /* Mode */
8268         }
8269         else
8270         {
8271           dlc[3] = 7;        /* Mode */
8272         }
8273    
8274         if(b2_config->length>=4) dlc[4] = b2_config->info[4];      /* Window */
8275         else dlc[4] = 1;
8276         dbug(1,dprintf("D-dlc[%d]=%x,%x,%x,%x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8277         if(b2_config->length>5) return _B2_PARM_NOT_SUPPORTED;
8278       }
8279       else
8280       {
8281         dlc[0] = (byte)(b2_config_parms[4].length+6);
8282         dlc[3] = b2_config->info[1];
8283         dlc[4] = b2_config->info[2];
8284         if(b2_config->info[3]!=8 && b2_config->info[3]!=128){
8285           dbug(1,dprintf("1D-dlc= %x %x %x %x %x", dlc[0], dlc[1], dlc[2], dlc[3], dlc[4]));
8286           return _B2_PARM_NOT_SUPPORTED;
8287         }
8288
8289         dlc[5] = (byte)(b2_config->info[3]-1);
8290         dlc[6] = b2_config->info[4];
8291         if(dlc[6]>dlc[5]){
8292           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]));
8293           return _B2_PARM_NOT_SUPPORTED;
8294         }
8295  
8296         if(llc[1]==X75_V42BIS) {
8297           if (b2_config->length >= 10){
8298             dlc[ 7] = 6; 
8299             dlc[ 8] = 0; 
8300             dlc[ 9] = b2_config_parms[4].info[0];
8301             dlc[10] = b2_config_parms[4].info[1];
8302             dlc[11] = b2_config_parms[5].info[0];
8303             dlc[12] = b2_config_parms[5].info[1];
8304             dlc[13] = b2_config_parms[6].info[0];
8305             dlc[14] = b2_config_parms[6].info[1];
8306             dlc[ 0] = 14;
8307             dbug(1,dprintf("b2_config_parms[4].info[0] [1]:  %x %x", b2_config_parms[4].info[0], b2_config_parms[4].info[1]));
8308             dbug(1,dprintf("b2_config_parms[5].info[0] [1]:  %x %x", b2_config_parms[5].info[0], b2_config_parms[5].info[1]));
8309             dbug(1,dprintf("b2_config_parms[6].info[0] [1]:  %x %x", b2_config_parms[6].info[0], b2_config_parms[6].info[1]));
8310           }
8311           else {
8312             dlc[ 6] = 14;
8313           }
8314
8315         }
8316         else {
8317           PUT_WORD(&dlc[7], (word)b2_config_parms[4].length);
8318           for(i=0; i<b2_config_parms[4].length; i++)
8319             dlc[11+i] = b2_config_parms[4].info[1+i];
8320         }
8321       }
8322     }
8323   }
8324   add_p(plci, DLC, dlc);
8325
8326   b3_config = &bp_parms[5];
8327   if(b3_config->length)
8328   {
8329     if(plci->B3_prot == 4 
8330     || plci->B3_prot == 5)
8331     {
8332       if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwss", b3_config_parms))
8333       {
8334         return _WRONG_MESSAGE_FORMAT;
8335       }
8336       i = GET_WORD((byte   *)(b3_config_parms[0].info));
8337       ((T30_INFO *)&nlc[1])->resolution = (byte)(((i & 0x0001) ||
8338         ((plci->B3_prot == 4) && (((byte)(GET_WORD((byte   *)b3_config_parms[1].info))) != 5))) ? T30_RESOLUTION_R8_0770_OR_200 : 0);
8339       ((T30_INFO *)&nlc[1])->data_format = (byte)(GET_WORD((byte   *)b3_config_parms[1].info));
8340       fax_control_bits = T30_CONTROL_BIT_ALL_FEATURES;
8341       if ((((T30_INFO *)&nlc[1])->rate_div_2400 != 0) && (((T30_INFO *)&nlc[1])->rate_div_2400 <= 6))
8342         fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_V34FAX;
8343       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
8344       {
8345
8346         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8347           & (1L << PRIVATE_FAX_PAPER_FORMATS))
8348         {
8349           ((T30_INFO *)&nlc[1])->resolution |= T30_RESOLUTION_R8_1540 |
8350             T30_RESOLUTION_R16_1540_OR_400 | T30_RESOLUTION_300_300 |
8351             T30_RESOLUTION_INCH_BASED | T30_RESOLUTION_METRIC_BASED;
8352         }
8353
8354  ((T30_INFO *)&nlc[1])->recording_properties =
8355    T30_RECORDING_WIDTH_ISO_A3 |
8356    (T30_RECORDING_LENGTH_UNLIMITED << 2) |
8357    (T30_MIN_SCANLINE_TIME_00_00_00 << 4);
8358       }
8359       if(plci->B3_prot == 5)
8360       {
8361         if (i & 0x0002) /* Accept incoming fax-polling requests */
8362           fax_control_bits |= T30_CONTROL_BIT_ACCEPT_POLLING;
8363         if (i & 0x2000) /* Do not use MR compression */
8364           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_2D_CODING;
8365         if (i & 0x4000) /* Do not use MMR compression */
8366           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_T6_CODING;
8367         if (i & 0x8000) /* Do not use ECM */
8368           fax_control_bits &= ~T30_CONTROL_BIT_ENABLE_ECM;
8369         if (plci->fax_connect_info_length != 0)
8370         {
8371           ((T30_INFO *)&nlc[1])->resolution = ((T30_INFO   *)plci->fax_connect_info_buffer)->resolution;
8372           ((T30_INFO *)&nlc[1])->data_format = ((T30_INFO   *)plci->fax_connect_info_buffer)->data_format;
8373           ((T30_INFO *)&nlc[1])->recording_properties = ((T30_INFO   *)plci->fax_connect_info_buffer)->recording_properties;
8374           fax_control_bits |= GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low) &
8375             (T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
8376         }
8377       }
8378       /* copy station id to NLC */
8379       for(i=0; i<20; i++)
8380       {
8381         if(i<b3_config_parms[2].length)
8382         {
8383           ((T30_INFO *)&nlc[1])->station_id[i] = ((byte   *)b3_config_parms[2].info)[1+i];
8384         }
8385         else
8386         {
8387           ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
8388         }
8389       }
8390       ((T30_INFO *)&nlc[1])->station_id_len = 20;
8391       /* copy head line to NLC */
8392       if(b3_config_parms[3].length)
8393       {
8394
8395         pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20])));
8396         if (pos != 0)
8397         {
8398           if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
8399             pos = 0;
8400           else
8401           {
8402             ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8403             ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8404             len = (byte)b3_config_parms[2].length;
8405             if (len > 20)
8406               len = 20;
8407             if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
8408             {
8409               for (i = 0; i < len; i++)
8410                 ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte   *)b3_config_parms[2].info)[1+i];
8411               ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8412               ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
8413             }
8414           }
8415         }
8416
8417         len = (byte)b3_config_parms[3].length;
8418         if (len > CAPI_MAX_HEAD_LINE_SPACE - pos)
8419           len = (byte)(CAPI_MAX_HEAD_LINE_SPACE - pos);
8420         ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
8421         nlc[0] += (byte)(pos + len);
8422         for (i = 0; i < len; i++)
8423           ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte   *)b3_config_parms[3].info)[1+i];
8424         }
8425       else
8426         ((T30_INFO *)&nlc[1])->head_line_len = 0;
8427
8428       plci->nsf_control_bits = 0;
8429       if(plci->B3_prot == 5)
8430       {
8431         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8432          && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x8000)) /* Private SUB/SEP/PWD enable */
8433         {
8434           plci->requested_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
8435         }
8436         if ((plci->adapter->man_profile.private_options & (1L << PRIVATE_FAX_NONSTANDARD))
8437          && (GET_WORD((byte   *)b3_config_parms[1].info) & 0x4000)) /* Private non-standard facilities enable */
8438         {
8439           plci->requested_options |= 1L << PRIVATE_FAX_NONSTANDARD;
8440         }
8441         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8442           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
8443         {
8444         if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8445           & (1L << PRIVATE_FAX_SUB_SEP_PWD))
8446         {
8447           fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SUBADDRESS | T30_CONTROL_BIT_ACCEPT_PASSWORD;
8448           if (fax_control_bits & T30_CONTROL_BIT_ACCEPT_POLLING)
8449             fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
8450           }
8451             len = nlc[0];
8452           pos = ((byte)(((T30_INFO *) 0)->station_id + 20));
8453    if (pos < plci->fax_connect_info_length)
8454    {
8455      for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8456               nlc[++len] = plci->fax_connect_info_buffer[pos++];
8457           }
8458    else
8459      nlc[++len] = 0;
8460    if (pos < plci->fax_connect_info_length)
8461    {
8462      for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8463               nlc[++len] = plci->fax_connect_info_buffer[pos++];
8464           }
8465    else
8466      nlc[++len] = 0;
8467           if ((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[plci->appl->Id-1])
8468             & (1L << PRIVATE_FAX_NONSTANDARD))
8469           {
8470      if ((pos < plci->fax_connect_info_length) && (plci->fax_connect_info_buffer[pos] != 0))
8471      {
8472               if ((plci->fax_connect_info_buffer[pos] >= 3) && (plci->fax_connect_info_buffer[pos+1] >= 2))
8473                 plci->nsf_control_bits = GET_WORD(&plci->fax_connect_info_buffer[pos+2]);
8474        for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
8475                 nlc[++len] = plci->fax_connect_info_buffer[pos++];
8476             }
8477      else
8478      {
8479               if(api_parse(&b3_config->info[1], (word)b3_config->length, "wwsss", b3_config_parms))
8480               {
8481                 dbug(1,dprintf("non-standard facilities info missing or wrong format"));
8482                 nlc[++len] = 0;
8483               }
8484        else
8485        {
8486                 if ((b3_config_parms[4].length >= 3) && (b3_config_parms[4].info[1] >= 2))
8487                   plci->nsf_control_bits = GET_WORD(&b3_config_parms[4].info[2]);
8488          nlc[++len] = (byte)(b3_config_parms[4].length);
8489          for (i = 0; i < b3_config_parms[4].length; i++)
8490     nlc[++len] = b3_config_parms[4].info[1+i];
8491        }
8492             }
8493           }
8494             nlc[0] = len;
8495    if ((plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
8496     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
8497    {
8498             ((T30_INFO *)&nlc[1])->operating_mode = T30_OPERATING_MODE_CAPI_NEG;
8499           }
8500         }
8501       }
8502
8503       PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
8504       len = ((byte)(((T30_INFO *) 0)->station_id + 20));
8505       for (i = 0; i < len; i++)
8506         plci->fax_connect_info_buffer[i] = nlc[1+i];
8507       ((T30_INFO   *) plci->fax_connect_info_buffer)->head_line_len = 0;
8508       i += ((T30_INFO *)&nlc[1])->head_line_len;
8509       while (i < nlc[0])
8510         plci->fax_connect_info_buffer[len++] = nlc[++i];
8511       plci->fax_connect_info_length = len;
8512     }
8513     else
8514     {
8515       nlc[0] = 14;
8516       if(b3_config->length!=16)
8517         return _B3_PARM_NOT_SUPPORTED;
8518       for(i=0; i<12; i++) nlc[1+i] = b3_config->info[1+i];
8519       if(GET_WORD(&b3_config->info[13])!=8 && GET_WORD(&b3_config->info[13])!=128)
8520         return _B3_PARM_NOT_SUPPORTED;
8521       nlc[13] = b3_config->info[13];
8522       if(GET_WORD(&b3_config->info[15])>=nlc[13])
8523         return _B3_PARM_NOT_SUPPORTED;
8524       nlc[14] = b3_config->info[15];
8525     }
8526   }
8527   else
8528   {
8529     if (plci->B3_prot == 4 
8530      || plci->B3_prot == 5 /*T.30 - FAX*/ ) return _B3_PARM_NOT_SUPPORTED;
8531   }
8532   add_p(plci, NLC, nlc);
8533   return 0;
8534 }
8535
8536 /*----------------------------------------------------------------*/
8537 /*      make the same as add_b23, but only for the modem related  */
8538 /*      L2 and L3 B-Chan protocol.                                */
8539 /*                                                                */
8540 /*      Enabled L2 and L3 Configurations:                         */
8541 /*        If L1 == Modem all negotiation                          */
8542 /*          only L2 == Modem with full negotiation is allowed     */
8543 /*        If L1 == Modem async or sync                            */
8544 /*          only L2 == Transparent is allowed                     */
8545 /*        L3 == Modem or L3 == Transparent are allowed            */
8546 /*      B2 Configuration for modem:                               */
8547 /*          word : enable/disable compression, bitoptions         */
8548 /*      B3 Configuration for modem:                               */
8549 /*          empty                                                 */
8550 /*----------------------------------------------------------------*/
8551 static word add_modem_b23 (PLCI  * plci, API_PARSE* bp_parms)
8552 {
8553   static byte lli[12] = {1,1};
8554   static byte llc[3] = {2,0,0};
8555   static byte dlc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
8556     API_PARSE mdm_config[2];
8557   word i;
8558   word b2_config = 0;
8559
8560   for(i=0;i<2;i++) mdm_config[i].length = 0;
8561   for(i=0;i<sizeof(dlc);i++) dlc[i] = 0;
8562
8563   if (((GET_WORD(bp_parms[0].info) == B1_MODEM_ALL_NEGOTIATE)
8564     && (GET_WORD(bp_parms[1].info) != B2_MODEM_EC_COMPRESSION))
8565    || ((GET_WORD(bp_parms[0].info) != B1_MODEM_ALL_NEGOTIATE)
8566     && (GET_WORD(bp_parms[1].info) != B2_TRANSPARENT)))
8567   {
8568     return (_B_STACK_NOT_SUPPORTED);
8569   }
8570   if ((GET_WORD(bp_parms[2].info) != B3_MODEM)
8571    && (GET_WORD(bp_parms[2].info) != B3_TRANSPARENT))
8572   {
8573     return (_B_STACK_NOT_SUPPORTED);
8574   }
8575
8576   plci->B2_prot = (byte) GET_WORD(bp_parms[1].info);
8577   plci->B3_prot = (byte) GET_WORD(bp_parms[2].info);
8578
8579   if ((GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION) && bp_parms[4].length)
8580   {
8581     if (api_parse (&bp_parms[4].info[1],
8582                   (word)bp_parms[4].length, "w",
8583                   mdm_config))
8584     {
8585       return (_WRONG_MESSAGE_FORMAT);
8586     }
8587     b2_config = GET_WORD(mdm_config[0].info);
8588   }
8589
8590   /* OK, L2 is modem */
8591
8592   lli[0] = 1;
8593   lli[1] = 1;
8594   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)
8595     lli[1] |= 2;
8596   if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_OOB_CHANNEL)
8597     lli[1] |= 4;
8598
8599   if ((lli[1] & 0x02) && (diva_xdi_extended_features & DIVA_CAPI_USE_CMA)) {
8600     lli[1] |= 0x10;
8601     if (plci->rx_dma_descriptor <= 0) {
8602       plci->rx_dma_descriptor=diva_get_dma_descriptor(plci,&plci->rx_dma_magic);
8603       if (plci->rx_dma_descriptor >= 0)
8604         plci->rx_dma_descriptor++;
8605     }
8606     if (plci->rx_dma_descriptor > 0) {
8607       lli[1] |= 0x40;
8608       lli[0] = 6;
8609       lli[2] = (byte)(plci->rx_dma_descriptor - 1);
8610       lli[3] = (byte)plci->rx_dma_magic;
8611       lli[4] = (byte)(plci->rx_dma_magic >>  8);
8612       lli[5] = (byte)(plci->rx_dma_magic >> 16);
8613       lli[6] = (byte)(plci->rx_dma_magic >> 24);
8614     }
8615   }
8616
8617   if (DIVA_CAPI_SUPPORTS_NO_CANCEL(plci->adapter)) {
8618     lli[1] |= 0x20;
8619   }
8620
8621   llc[1] = (plci->call_dir & (CALL_DIR_ORIGINATE | CALL_DIR_FORCE_OUTG_NL)) ?
8622     /*V42*/ 10 : /*V42_IN*/ 9;
8623   llc[2] = 4;                      /* pass L3 always transparent */
8624   add_p(plci, LLI, lli);
8625   add_p(plci, LLC, llc);
8626   i =  1;
8627   PUT_WORD (&dlc[i], plci->appl->MaxDataLength);
8628   i += 2;
8629   if (GET_WORD(bp_parms[1].info) == B2_MODEM_EC_COMPRESSION)
8630   {
8631     if (bp_parms[4].length)
8632   {
8633     dbug(1, dprintf("MDM b2_config=%02x", b2_config));
8634     dlc[i++] = 3; /* Addr A */
8635     dlc[i++] = 1; /* Addr B */
8636     dlc[i++] = 7; /* modulo mode */
8637     dlc[i++] = 7; /* window size */
8638     dlc[i++] = 0; /* XID len Lo  */
8639     dlc[i++] = 0; /* XID len Hi  */
8640
8641     if (b2_config & MDM_B2_DISABLE_V42bis)
8642     {
8643       dlc[i] |= DLC_MODEMPROT_DISABLE_V42_V42BIS;
8644     }
8645     if (b2_config & MDM_B2_DISABLE_MNP)
8646     {
8647       dlc[i] |= DLC_MODEMPROT_DISABLE_MNP_MNP5;
8648     }
8649     if (b2_config & MDM_B2_DISABLE_TRANS)
8650     {
8651       dlc[i] |= DLC_MODEMPROT_REQUIRE_PROTOCOL;
8652     }
8653     if (b2_config & MDM_B2_DISABLE_V42)
8654     {
8655       dlc[i] |= DLC_MODEMPROT_DISABLE_V42_DETECT;
8656     }
8657     if (b2_config & MDM_B2_DISABLE_COMP)
8658     {
8659       dlc[i] |= DLC_MODEMPROT_DISABLE_COMPRESSION;
8660     }
8661     i++;
8662   }
8663   }
8664   else
8665   {
8666     dlc[i++] = 3; /* Addr A */
8667     dlc[i++] = 1; /* Addr B */
8668     dlc[i++] = 7; /* modulo mode */
8669     dlc[i++] = 7; /* window size */
8670     dlc[i++] = 0; /* XID len Lo  */
8671     dlc[i++] = 0; /* XID len Hi  */
8672     dlc[i++] = DLC_MODEMPROT_DISABLE_V42_V42BIS |
8673                DLC_MODEMPROT_DISABLE_MNP_MNP5 |
8674                DLC_MODEMPROT_DISABLE_V42_DETECT |
8675                DLC_MODEMPROT_DISABLE_COMPRESSION;
8676   }
8677   dlc[0] = (byte)(i - 1);
8678 /* HexDump ("DLC", sizeof(dlc), &dlc[0]); */
8679   add_p(plci, DLC, dlc);
8680   return (0);
8681 }
8682
8683
8684 /*------------------------------------------------------------------*/
8685 /* send a request for the signaling entity                          */
8686 /*------------------------------------------------------------------*/
8687
8688 void sig_req(PLCI   * plci, byte req, byte Id)
8689 {
8690   if(!plci) return;
8691   if(plci->adapter->adapter_disabled) return;
8692   dbug(1,dprintf("sig_req(%x)",req));
8693   if (req == REMOVE)
8694     plci->sig_remove_id = plci->Sig.Id;
8695   if(plci->req_in==plci->req_in_start) {
8696     plci->req_in +=2;
8697     plci->RBuffer[plci->req_in++] = 0;
8698   }
8699   PUT_WORD(&plci->RBuffer[plci->req_in_start], plci->req_in-plci->req_in_start-2);
8700   plci->RBuffer[plci->req_in++] = Id;   /* sig/nl flag */
8701   plci->RBuffer[plci->req_in++] = req;  /* request */
8702   plci->RBuffer[plci->req_in++] = 0;    /* channel */
8703   plci->req_in_start = plci->req_in;
8704 }
8705
8706 /*------------------------------------------------------------------*/
8707 /* send a request for the network layer entity                      */
8708 /*------------------------------------------------------------------*/
8709
8710 void nl_req_ncci(PLCI   * plci, byte req, byte ncci)
8711 {
8712   if(!plci) return;
8713   if(plci->adapter->adapter_disabled) return;
8714   dbug(1,dprintf("nl_req %02x %02x %02x", plci->Id, req, ncci));
8715   if (req == REMOVE)
8716   {
8717     plci->nl_remove_id = plci->NL.Id;
8718     ncci_remove (plci, 0, (byte)(ncci != 0));
8719     ncci = 0;
8720   }
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++] = 1;    /* sig/nl flag */
8727   plci->RBuffer[plci->req_in++] = req;  /* request */
8728   plci->RBuffer[plci->req_in++] = plci->adapter->ncci_ch[ncci];   /* channel */
8729   plci->req_in_start = plci->req_in;
8730 }
8731
8732 void send_req(PLCI   * plci)
8733 {
8734   ENTITY   * e;
8735   word l;
8736 /*  word i; */
8737
8738   if(!plci) return;
8739   if(plci->adapter->adapter_disabled) return;
8740   channel_xmit_xon (plci);
8741
8742         /* if nothing to do, return */
8743   if(plci->req_in==plci->req_out) return;
8744   dbug(1,dprintf("send_req(in=%d,out=%d)",plci->req_in,plci->req_out));
8745
8746   if(plci->nl_req || plci->sig_req) return;
8747
8748   l = GET_WORD(&plci->RBuffer[plci->req_out]);
8749   plci->req_out += 2;
8750   plci->XData[0].P = &plci->RBuffer[plci->req_out];
8751   plci->req_out += l;
8752   if(plci->RBuffer[plci->req_out]==1)
8753   {
8754     e = &plci->NL;
8755     plci->req_out++;
8756     e->Req = plci->nl_req = plci->RBuffer[plci->req_out++];
8757     e->ReqCh = plci->RBuffer[plci->req_out++];
8758     if(!(e->Id & 0x1f))
8759     {
8760       e->Id = NL_ID;
8761       plci->RBuffer[plci->req_out-4] = CAI;
8762       plci->RBuffer[plci->req_out-3] = 1;
8763       plci->RBuffer[plci->req_out-2] = (plci->Sig.Id==0xff) ? 0 : plci->Sig.Id;
8764       plci->RBuffer[plci->req_out-1] = 0;
8765       l+=3;
8766       plci->nl_global_req = plci->nl_req;
8767     }
8768     dbug(1,dprintf("%x:NLREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8769   }
8770   else
8771   {
8772     e = &plci->Sig;
8773     if(plci->RBuffer[plci->req_out])
8774       e->Id = plci->RBuffer[plci->req_out];
8775     plci->req_out++;
8776     e->Req = plci->sig_req = plci->RBuffer[plci->req_out++];
8777     e->ReqCh = plci->RBuffer[plci->req_out++];
8778     if(!(e->Id & 0x1f))
8779       plci->sig_global_req = plci->sig_req;
8780     dbug(1,dprintf("%x:SIGREQ(%x:%x:%x)",plci->adapter->Id,e->Id,e->Req,e->ReqCh));
8781   }
8782   plci->XData[0].PLength = l;
8783   e->X = plci->XData;
8784   plci->adapter->request(e);
8785   dbug(1,dprintf("send_ok"));
8786 }
8787
8788 void send_data(PLCI   * plci)
8789 {
8790   DIVA_CAPI_ADAPTER   * a;
8791   DATA_B3_DESC   * data;
8792   NCCI   *ncci_ptr;
8793   word ncci;
8794
8795   if (!plci->nl_req && plci->ncci_ring_list)
8796   {
8797     a = plci->adapter;
8798     ncci = plci->ncci_ring_list;
8799     do
8800     {
8801       ncci = a->ncci_next[ncci];
8802       ncci_ptr = &(a->ncci[ncci]);
8803       if (!(a->ncci_ch[ncci]
8804          && (a->ch_flow_control[a->ncci_ch[ncci]] & N_OK_FC_PENDING)))
8805       {
8806         if (ncci_ptr->data_pending)
8807         {
8808           if ((a->ncci_state[ncci] == CONNECTED)
8809            || (a->ncci_state[ncci] == INC_ACT_PENDING)
8810            || (plci->send_disc == ncci))
8811           {
8812             data = &(ncci_ptr->DBuffer[ncci_ptr->data_out]);
8813             if ((plci->B2_prot == B2_V120_ASYNC)
8814              || (plci->B2_prot == B2_V120_ASYNC_V42BIS)
8815              || (plci->B2_prot == B2_V120_BIT_TRANSPARENT))
8816             {
8817               plci->NData[1].P = TransmitBufferGet (plci->appl, data->P);
8818               plci->NData[1].PLength = data->Length;
8819               if (data->Flags & 0x10)
8820                 plci->NData[0].P = v120_break_header;
8821               else
8822                 plci->NData[0].P = v120_default_header;
8823               plci->NData[0].PLength = 1 ;
8824               plci->NL.XNum = 2;
8825               plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8826             }
8827             else
8828             {
8829               plci->NData[0].P = TransmitBufferGet (plci->appl, data->P);
8830               plci->NData[0].PLength = data->Length;
8831               if (data->Flags & 0x10)
8832                 plci->NL.Req = plci->nl_req = (byte)N_UDATA;
8833
8834               else if ((plci->B3_prot == B3_RTP) && (data->Flags & 0x01))
8835                 plci->NL.Req = plci->nl_req = (byte)N_BDATA;
8836
8837               else
8838                 plci->NL.Req = plci->nl_req = (byte)((data->Flags&0x07)<<4 |N_DATA);
8839             }
8840             plci->NL.X = plci->NData;
8841             plci->NL.ReqCh = a->ncci_ch[ncci];
8842             dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
8843             plci->data_sent = true;
8844             plci->data_sent_ptr = data->P;
8845             a->request(&plci->NL);
8846           }
8847           else {
8848             cleanup_ncci_data (plci, ncci);
8849           }
8850         }
8851         else if (plci->send_disc == ncci)
8852         {
8853           /* dprintf("N_DISC"); */
8854           plci->NData[0].PLength = 0;
8855           plci->NL.ReqCh = a->ncci_ch[ncci];
8856           plci->NL.Req = plci->nl_req = N_DISC;
8857           a->request(&plci->NL);
8858           plci->command = _DISCONNECT_B3_R;
8859           plci->send_disc = 0;
8860         }
8861       }
8862     } while (!plci->nl_req && (ncci != plci->ncci_ring_list));
8863     plci->ncci_ring_list = ncci;
8864   }
8865 }
8866
8867 void listen_check(DIVA_CAPI_ADAPTER   * a)
8868 {
8869   word i,j;
8870   PLCI   * plci;
8871   byte activnotifiedcalls = 0;
8872
8873   dbug(1,dprintf("listen_check(%d,%d)",a->listen_active,a->max_listen));
8874   if (!remove_started && !a->adapter_disabled)
8875   {
8876     for(i=0;i<a->max_plci;i++)
8877     {
8878       plci = &(a->plci[i]);
8879       if(plci->notifiedcall) activnotifiedcalls++;
8880     }
8881     dbug(1,dprintf("listen_check(%d)",activnotifiedcalls));
8882
8883     for(i=a->listen_active; i < ((word)(a->max_listen+activnotifiedcalls)); i++) {
8884       if((j=get_plci(a))) {
8885         a->listen_active++;
8886         plci = &a->plci[j-1];
8887         plci->State = LISTENING;
8888
8889         add_p(plci,OAD,"\x01\xfd");
8890
8891         add_p(plci,KEY,"\x04\x43\x41\x32\x30");
8892
8893         add_p(plci,CAI,"\x01\xc0");
8894         add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
8895         add_p(plci,LLI,"\x01\xc4");                  /* support Dummy CR FAC + MWI + SpoofNotify */       
8896         add_p(plci,SHIFT|6,NULL);
8897         add_p(plci,SIN,"\x02\x00\x00");
8898         plci->internal_command = LISTEN_SIG_ASSIGN_PEND;     /* do indicate_req if OK  */
8899         sig_req(plci,ASSIGN,DSIG_ID);
8900         send_req(plci);
8901       }
8902     }
8903   }
8904 }
8905
8906 /*------------------------------------------------------------------*/
8907 /* functions for all parameters sent in INDs                        */
8908 /*------------------------------------------------------------------*/
8909
8910 void IndParse(PLCI   * plci, word * parms_id, byte   ** parms, byte multiIEsize)
8911 {
8912   word ploc;            /* points to current location within packet */
8913   byte w;
8914   byte wlen;
8915   byte codeset,lock;
8916   byte   * in;
8917   word i;
8918   word code;
8919   word mIEindex = 0;
8920   ploc = 0;
8921   codeset = 0;
8922   lock = 0;
8923
8924   in = plci->Sig.RBuffer->P;
8925   for(i=0; i<parms_id[0]; i++)   /* multiIE parms_id contains just the 1st */
8926   {                            /* element but parms array is larger      */
8927     parms[i] = (byte   *)"";
8928   }
8929   for(i=0; i<multiIEsize; i++)
8930   {
8931     parms[i] = (byte   *)"";
8932   }
8933
8934   while(ploc<plci->Sig.RBuffer->length-1) {
8935
8936         /* read information element id and length                   */
8937     w = in[ploc];
8938
8939     if(w & 0x80) {
8940 /*    w &=0xf0; removed, cannot detect congestion levels */
8941 /*    upper 4 bit masked with w==SHIFT now               */
8942       wlen = 0;
8943     }
8944     else {
8945       wlen = (byte)(in[ploc+1]+1);
8946     }
8947         /* check if length valid (not exceeding end of packet)      */
8948     if((ploc+wlen) > 270) return ;
8949     if(lock & 0x80) lock &=0x7f;
8950     else codeset = lock;
8951
8952     if((w&0xf0)==SHIFT) {
8953       codeset = in[ploc];
8954       if(!(codeset & 0x08)) lock = (byte)(codeset & 7);
8955       codeset &=7;
8956       lock |=0x80;
8957     }
8958     else {
8959       if(w==ESC && wlen>=3) code = in[ploc+2] |0x800;
8960       else code = w;
8961       code |= (codeset<<8);
8962
8963       for(i=1; i<parms_id[0]+1 && parms_id[i]!=code; i++);
8964
8965       if(i<parms_id[0]+1) {
8966         if(!multiIEsize) { /* with multiIEs use next field index,          */
8967           mIEindex = i-1;    /* with normal IEs use same index like parms_id */
8968         }
8969
8970         parms[mIEindex] = &in[ploc+1];
8971         dbug(1,dprintf("mIE[%d]=0x%x",*parms[mIEindex],in[ploc]));
8972         if(parms_id[i]==OAD
8973         || parms_id[i]==CONN_NR
8974         || parms_id[i]==CAD) {
8975           if(in[ploc+2] &0x80) {
8976             in[ploc+0] = (byte)(in[ploc+1]+1);
8977             in[ploc+1] = (byte)(in[ploc+2] &0x7f);
8978             in[ploc+2] = 0x80;
8979             parms[mIEindex] = &in[ploc];
8980           }
8981         }
8982         mIEindex++;       /* effects multiIEs only */
8983       }
8984     }
8985
8986     ploc +=(wlen+1);
8987   }
8988   return ;
8989 }
8990
8991 /*------------------------------------------------------------------*/
8992 /* try to match a cip from received BC and HLC                      */
8993 /*------------------------------------------------------------------*/
8994
8995 byte ie_compare(byte   * ie1, byte * ie2)
8996 {
8997   word i;
8998   if(!ie1 || ! ie2) return false;
8999   if(!ie1[0]) return false;
9000   for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false;
9001   return true;
9002 }
9003
9004 word find_cip(DIVA_CAPI_ADAPTER   * a, byte   * bc, byte   * hlc)
9005 {
9006   word i;
9007   word j;
9008
9009   for(i=9;i && !ie_compare(bc,cip_bc[i][a->u_law]);i--);
9010
9011   for(j=16;j<29 &&
9012            (!ie_compare(bc,cip_bc[j][a->u_law]) || !ie_compare(hlc,cip_hlc[j])); j++);
9013   if(j==29) return i;
9014   return j;
9015 }
9016
9017
9018 static byte AddInfo(byte   **add_i,
9019                     byte   **fty_i,
9020                     byte   *esc_chi,
9021                     byte *facility)
9022 {
9023   byte i;
9024   byte j;
9025   byte k;
9026   byte flen;
9027   byte len=0;
9028    /* facility is a nested structure */
9029    /* FTY can be more than once      */
9030
9031   if(esc_chi[0] && !(esc_chi[esc_chi[0]])&0x7f )
9032   {
9033     add_i[0] = (byte   *)"\x02\x02\x00"; /* use neither b nor d channel */
9034   }
9035
9036   else
9037   {
9038     add_i[0] = (byte   *)"";
9039   }
9040   if(!fty_i[0][0])
9041   {
9042     add_i[3] = (byte   *)"";
9043   }
9044   else
9045   {    /* facility array found  */
9046     for(i=0,j=1;i<MAX_MULTI_IE && fty_i[i][0];i++)
9047     {
9048       dbug(1,dprintf("AddIFac[%d]",fty_i[i][0]));
9049       len += fty_i[i][0];
9050       len += 2;
9051       flen=fty_i[i][0];
9052       facility[j++]=0x1c; /* copy fac IE */
9053       for(k=0;k<=flen;k++,j++)
9054       {
9055         facility[j]=fty_i[i][k];
9056 /*      dbug(1,dprintf("%x ",facility[j])); */
9057       }
9058     }
9059     facility[0] = len;
9060     add_i[3] = facility;
9061   }
9062 /*  dbug(1,dprintf("FacArrLen=%d ",len)); */
9063   len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0];
9064   len += 4;                          /* calculate length of all */
9065   return(len);
9066 }
9067
9068 /*------------------------------------------------------------------*/
9069 /* voice and codec features                                         */
9070 /*------------------------------------------------------------------*/
9071
9072 void SetVoiceChannel(PLCI   *plci, byte   *chi, DIVA_CAPI_ADAPTER   * a)
9073 {
9074   byte voice_chi[] = "\x02\x18\x01";
9075   byte channel;
9076
9077   channel = chi[chi[0]]&0x3;
9078   dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel));
9079   voice_chi[2] = (channel) ? channel : 1;
9080   add_p(plci,FTY,"\x02\x01\x07");             /* B On, default on 1 */
9081   add_p(plci,ESC,voice_chi);                  /* Channel */
9082   sig_req(plci,TEL_CTRL,0);
9083   send_req(plci);
9084   if(a->AdvSignalPLCI)
9085   {
9086     adv_voice_write_coefs (a->AdvSignalPLCI, ADV_VOICE_WRITE_ACTIVATION);
9087   }
9088 }
9089
9090 void VoiceChannelOff(PLCI   *plci)
9091 {
9092   dbug(1,dprintf("ExtDevOFF"));
9093   add_p(plci,FTY,"\x02\x01\x08");             /* B Off */
9094   sig_req(plci,TEL_CTRL,0);
9095   send_req(plci);
9096   if(plci->adapter->AdvSignalPLCI)
9097   {
9098     adv_voice_clear_config (plci->adapter->AdvSignalPLCI);
9099   }
9100 }
9101
9102
9103 word AdvCodecSupport(DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, byte hook_listen)
9104 {
9105   word j;
9106   PLCI   *splci;
9107
9108   /* check if hardware supports handset with hook states (adv.codec) */
9109   /* or if just a on board codec is supported                        */
9110   /* the advanced codec plci is just for internal use                */
9111
9112   /* diva Pro with on-board codec:                                   */
9113   if(a->profile.Global_Options & HANDSET)
9114   {
9115     /* new call, but hook states are already signalled */
9116     if(a->AdvCodecFLAG)
9117     {
9118       if(a->AdvSignalAppl!=appl || a->AdvSignalPLCI)
9119       {
9120         dbug(1,dprintf("AdvSigPlci=0x%x",a->AdvSignalPLCI));
9121         return 0x2001; /* codec in use by another application */
9122       }
9123       if(plci!=0)
9124       {
9125         a->AdvSignalPLCI = plci;
9126         plci->tel=ADV_VOICE;
9127       }
9128       return 0;                      /* adv codec still used */
9129     }
9130     if((j=get_plci(a)))
9131     {
9132       splci = &a->plci[j-1];
9133       splci->tel = CODEC_PERMANENT;
9134       /* hook_listen indicates if a facility_req with handset/hook support */
9135       /* was sent. Otherwise if just a call on an external device was made */
9136       /* the codec will be used but the hook info will be discarded (just  */
9137       /* the external controller is in use                                 */
9138       if(hook_listen) splci->State = ADVANCED_VOICE_SIG;
9139       else
9140       {
9141         splci->State = ADVANCED_VOICE_NOSIG;
9142         if(plci)
9143         {
9144           plci->spoofed_msg = SPOOFING_REQUIRED;
9145         }
9146                                                /* indicate D-ch connect if  */
9147       }                                        /* codec is connected OK     */
9148       if(plci!=0)
9149       {
9150         a->AdvSignalPLCI = plci;
9151         plci->tel=ADV_VOICE;
9152       }
9153       a->AdvSignalAppl = appl;
9154       a->AdvCodecFLAG = true;
9155       a->AdvCodecPLCI = splci;
9156       add_p(splci,CAI,"\x01\x15");
9157       add_p(splci,LLI,"\x01\x00");
9158       add_p(splci,ESC,"\x02\x18\x00");
9159       add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9160       splci->internal_command = PERM_COD_ASSIGN;
9161       dbug(1,dprintf("Codec Assign"));
9162       sig_req(splci,ASSIGN,DSIG_ID);
9163       send_req(splci);
9164     }
9165     else
9166     {
9167       return 0x2001; /* wrong state, no more plcis */
9168     }
9169   }
9170   else if(a->profile.Global_Options & ON_BOARD_CODEC)
9171   {
9172     if(hook_listen) return 0x300B;               /* Facility not supported */
9173                                                  /* no hook with SCOM      */
9174     if(plci!=0) plci->tel = CODEC;
9175     dbug(1,dprintf("S/SCOM codec"));
9176     /* first time we use the scom-s codec we must shut down the internal   */
9177     /* handset application of the card. This can be done by an assign with */
9178     /* a cai with the 0x80 bit set. Assign return code is 'out of resource'*/
9179     if(!a->scom_appl_disable){
9180       if((j=get_plci(a))) {
9181         splci = &a->plci[j-1];
9182         add_p(splci,CAI,"\x01\x80");
9183         add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9184         sig_req(splci,ASSIGN,0xC0);  /* 0xc0 is the TEL_ID */
9185         send_req(splci);
9186         a->scom_appl_disable = true;
9187       }
9188       else{
9189         return 0x2001; /* wrong state, no more plcis */
9190       }
9191     }
9192   }
9193   else return 0x300B;               /* Facility not supported */
9194
9195   return 0;
9196 }
9197
9198
9199 void CodecIdCheck(DIVA_CAPI_ADAPTER   *a, PLCI   *plci)
9200 {
9201
9202   dbug(1,dprintf("CodecIdCheck"));
9203
9204   if(a->AdvSignalPLCI == plci)
9205   {
9206     dbug(1,dprintf("PLCI owns codec"));
9207     VoiceChannelOff(a->AdvCodecPLCI);
9208     if(a->AdvCodecPLCI->State == ADVANCED_VOICE_NOSIG)
9209     {
9210       dbug(1,dprintf("remove temp codec PLCI"));
9211       plci_remove(a->AdvCodecPLCI);
9212       a->AdvCodecFLAG  = 0;
9213       a->AdvCodecPLCI  = NULL;
9214       a->AdvSignalAppl = NULL;
9215     }
9216     a->AdvSignalPLCI = NULL;
9217   }
9218 }
9219
9220 /* -------------------------------------------------------------------
9221     Ask for physical address of card on PCI bus
9222    ------------------------------------------------------------------- */
9223 static void diva_ask_for_xdi_sdram_bar (DIVA_CAPI_ADAPTER  * a,
9224                                         IDI_SYNC_REQ  * preq) {
9225   a->sdram_bar = 0;
9226   if (diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR) {
9227     ENTITY   * e = (ENTITY   *)preq;
9228
9229     e->user[0] = a->Id - 1;
9230     preq->xdi_sdram_bar.info.bar    = 0;
9231     preq->xdi_sdram_bar.Req         = 0;
9232     preq->xdi_sdram_bar.Rc           = IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR;
9233
9234     (*(a->request))(e);
9235
9236     a->sdram_bar = preq->xdi_sdram_bar.info.bar;
9237     dbug(3,dprintf("A(%d) SDRAM BAR = %08x", a->Id, a->sdram_bar));
9238   }
9239 }
9240
9241 /* -------------------------------------------------------------------
9242      Ask XDI about extended features
9243    ------------------------------------------------------------------- */
9244 static void diva_get_extended_adapter_features (DIVA_CAPI_ADAPTER  * a) {
9245   IDI_SYNC_REQ   * preq;
9246     char buffer[              ((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ?                     (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
9247
9248     char features[4];
9249   preq = (IDI_SYNC_REQ   *)&buffer[0];
9250
9251   if (!diva_xdi_extended_features) {
9252     ENTITY   * e = (ENTITY   *)preq;
9253     diva_xdi_extended_features |= 0x80000000;
9254
9255     e->user[0] = a->Id - 1;
9256     preq->xdi_extended_features.Req = 0;
9257     preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
9258     preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
9259     preq->xdi_extended_features.info.features = &features[0];
9260
9261     (*(a->request))(e);
9262
9263     if (features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) {
9264       /*
9265          Check features located in the byte '0'
9266          */
9267       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_CMA) {
9268         diva_xdi_extended_features |= DIVA_CAPI_USE_CMA;
9269       }
9270       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_RX_DMA) {
9271         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_RX_DMA;
9272         dbug(1,dprintf("XDI provides RxDMA"));
9273       }
9274       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR) {
9275         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_SDRAM_BAR;
9276       }
9277       if (features[0] & DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC) {
9278         diva_xdi_extended_features |= DIVA_CAPI_XDI_PROVIDES_NO_CANCEL;
9279         dbug(3,dprintf("XDI provides NO_CANCEL_RC feature"));
9280       }
9281
9282     }
9283   }
9284
9285   diva_ask_for_xdi_sdram_bar (a, preq);
9286 }
9287
9288 /*------------------------------------------------------------------*/
9289 /* automatic law                                                    */
9290 /*------------------------------------------------------------------*/
9291 /* called from OS specific part after init time to get the Law              */
9292 /* a-law (Euro) and u-law (us,japan) use different BCs in the Setup message */
9293 void AutomaticLaw(DIVA_CAPI_ADAPTER   *a)
9294 {
9295   word j;
9296   PLCI   *splci;
9297
9298   if(a->automatic_law) {
9299     return;
9300   }
9301   if((j=get_plci(a))) {
9302     diva_get_extended_adapter_features (a);
9303     splci = &a->plci[j-1];
9304     a->automatic_lawPLCI = splci;
9305     a->automatic_law = 1;
9306     add_p(splci,CAI,"\x01\x80");
9307     add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9308     splci->internal_command = USELAW_REQ;
9309     splci->command = 0;
9310     splci->number = 0;
9311     sig_req(splci,ASSIGN,DSIG_ID);
9312     send_req(splci);
9313   }
9314 }
9315
9316 /* called from OS specific part if an application sends an Capi20Release */
9317 word CapiRelease(word Id)
9318 {
9319   word i, j, appls_found;
9320   PLCI   *plci;
9321   APPL   *this;
9322   DIVA_CAPI_ADAPTER   *a;
9323
9324   if (!Id)
9325   {
9326     dbug(0,dprintf("A: CapiRelease(Id==0)"));
9327     return (_WRONG_APPL_ID);
9328   }
9329
9330   this = &application[Id-1];               /* get application pointer */
9331
9332   for(i=0,appls_found=0; i<max_appl; i++)
9333   {
9334     if(application[i].Id)       /* an application has been found        */
9335     {
9336       appls_found++;
9337     }
9338   }
9339
9340   for(i=0; i<max_adapter; i++)             /* scan all adapters...    */
9341   {
9342     a = &adapter[i];
9343     if (a->request)
9344     {
9345       a->Info_Mask[Id-1] = 0;
9346       a->CIP_Mask[Id-1] = 0;
9347       a->Notification_Mask[Id-1] = 0;
9348       a->codec_listen[Id-1] = NULL;
9349       a->requested_options_table[Id-1] = 0;
9350       for(j=0; j<a->max_plci; j++)           /* and all PLCIs connected */
9351       {                                      /* with this application   */
9352         plci = &a->plci[j];
9353         if(plci->Id)                         /* if plci owns no application */
9354         {                                    /* it may be not jet connected */
9355           if(plci->State==INC_CON_PENDING
9356           || plci->State==INC_CON_ALERT)
9357           {
9358             if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9359             {
9360               clear_c_ind_mask_bit (plci, (word)(Id-1));
9361               if(c_ind_mask_empty (plci))
9362               {
9363                 sig_req(plci,HANGUP,0);
9364                 send_req(plci);
9365                 plci->State = OUTG_DIS_PENDING;
9366               }
9367             }
9368           }
9369           if(test_c_ind_mask_bit (plci, (word)(Id-1)))
9370           {
9371             clear_c_ind_mask_bit (plci, (word)(Id-1));
9372             if(c_ind_mask_empty (plci))
9373             {
9374               if(!plci->appl)
9375               {
9376                 plci_remove(plci);
9377                 plci->State = IDLE;
9378               }
9379             }
9380           }
9381           if(plci->appl==this)
9382           {
9383             plci->appl = NULL;
9384             plci_remove(plci);
9385             plci->State = IDLE;
9386           }
9387         }
9388       }
9389       listen_check(a);
9390
9391       if(a->flag_dynamic_l1_down)
9392       {
9393         if(appls_found==1)            /* last application does a capi release */
9394         {
9395           if((j=get_plci(a)))
9396           {
9397             plci = &a->plci[j-1];
9398             plci->command = 0;
9399             add_p(plci,OAD,"\x01\xfd");
9400             add_p(plci,CAI,"\x01\x80");
9401             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
9402             add_p(plci,SHIFT|6,NULL);
9403             add_p(plci,SIN,"\x02\x00\x00");
9404             plci->internal_command = REM_L1_SIG_ASSIGN_PEND;
9405             sig_req(plci,ASSIGN,DSIG_ID);
9406             add_p(plci,FTY,"\x02\xff\x06"); /* l1 down */
9407             sig_req(plci,SIG_CTRL,0);
9408             send_req(plci);
9409           }
9410         }
9411       }
9412       if(a->AdvSignalAppl==this)
9413       {
9414         this->NullCREnable = false;
9415         if (a->AdvCodecPLCI)
9416         {
9417           plci_remove(a->AdvCodecPLCI);
9418           a->AdvCodecPLCI->tel = 0;
9419           a->AdvCodecPLCI->adv_nl = 0;
9420         }
9421         a->AdvSignalAppl = NULL;
9422         a->AdvSignalPLCI = NULL;
9423         a->AdvCodecFLAG = 0;
9424         a->AdvCodecPLCI = NULL;
9425       }
9426     }
9427   }
9428
9429   this->Id = 0;
9430
9431   return GOOD;
9432 }
9433
9434 static word plci_remove_check(PLCI   *plci)
9435 {
9436   if(!plci) return true;
9437   if(!plci->NL.Id && c_ind_mask_empty (plci))
9438   {
9439     if(plci->Sig.Id == 0xff)
9440       plci->Sig.Id = 0;
9441     if(!plci->Sig.Id)
9442     {
9443       dbug(1,dprintf("plci_remove_complete(%x)",plci->Id));
9444       dbug(1,dprintf("tel=0x%x,Sig=0x%x",plci->tel,plci->Sig.Id));
9445       if (plci->Id)
9446       {
9447         CodecIdCheck(plci->adapter, plci);
9448         clear_b1_config (plci);
9449         ncci_remove (plci, 0, false);
9450         plci_free_msg_in_queue (plci);
9451         channel_flow_control_remove (plci);
9452         plci->Id = 0;
9453         plci->State = IDLE;
9454         plci->channels = 0;
9455         plci->appl = NULL;
9456         plci->notifiedcall = 0;
9457       }
9458       listen_check(plci->adapter);
9459       return true;
9460     }
9461   }
9462   return false;
9463 }
9464
9465
9466 /*------------------------------------------------------------------*/
9467
9468 static byte plci_nl_busy (PLCI   *plci)
9469 {
9470   /* only applicable for non-multiplexed protocols */
9471   return (plci->nl_req
9472     || (plci->ncci_ring_list
9473      && plci->adapter->ncci_ch[plci->ncci_ring_list]
9474      && (plci->adapter->ch_flow_control[plci->adapter->ncci_ch[plci->ncci_ring_list]] & N_OK_FC_PENDING)));
9475 }
9476
9477
9478 /*------------------------------------------------------------------*/
9479 /* DTMF facilities                                                  */
9480 /*------------------------------------------------------------------*/
9481
9482
9483 static struct
9484 {
9485   byte send_mask;
9486   byte listen_mask;
9487   byte character;
9488   byte code;
9489 } dtmf_digit_map[] =
9490 {
9491   { 0x01, 0x01, 0x23, DTMF_DIGIT_TONE_CODE_HASHMARK },
9492   { 0x01, 0x01, 0x2a, DTMF_DIGIT_TONE_CODE_STAR },
9493   { 0x01, 0x01, 0x30, DTMF_DIGIT_TONE_CODE_0 },
9494   { 0x01, 0x01, 0x31, DTMF_DIGIT_TONE_CODE_1 },
9495   { 0x01, 0x01, 0x32, DTMF_DIGIT_TONE_CODE_2 },
9496   { 0x01, 0x01, 0x33, DTMF_DIGIT_TONE_CODE_3 },
9497   { 0x01, 0x01, 0x34, DTMF_DIGIT_TONE_CODE_4 },
9498   { 0x01, 0x01, 0x35, DTMF_DIGIT_TONE_CODE_5 },
9499   { 0x01, 0x01, 0x36, DTMF_DIGIT_TONE_CODE_6 },
9500   { 0x01, 0x01, 0x37, DTMF_DIGIT_TONE_CODE_7 },
9501   { 0x01, 0x01, 0x38, DTMF_DIGIT_TONE_CODE_8 },
9502   { 0x01, 0x01, 0x39, DTMF_DIGIT_TONE_CODE_9 },
9503   { 0x01, 0x01, 0x41, DTMF_DIGIT_TONE_CODE_A },
9504   { 0x01, 0x01, 0x42, DTMF_DIGIT_TONE_CODE_B },
9505   { 0x01, 0x01, 0x43, DTMF_DIGIT_TONE_CODE_C },
9506   { 0x01, 0x01, 0x44, DTMF_DIGIT_TONE_CODE_D },
9507   { 0x01, 0x00, 0x61, DTMF_DIGIT_TONE_CODE_A },
9508   { 0x01, 0x00, 0x62, DTMF_DIGIT_TONE_CODE_B },
9509   { 0x01, 0x00, 0x63, DTMF_DIGIT_TONE_CODE_C },
9510   { 0x01, 0x00, 0x64, DTMF_DIGIT_TONE_CODE_D },
9511
9512   { 0x04, 0x04, 0x80, DTMF_SIGNAL_NO_TONE },
9513   { 0x00, 0x04, 0x81, DTMF_SIGNAL_UNIDENTIFIED_TONE },
9514   { 0x04, 0x04, 0x82, DTMF_SIGNAL_DIAL_TONE },
9515   { 0x04, 0x04, 0x83, DTMF_SIGNAL_PABX_INTERNAL_DIAL_TONE },
9516   { 0x04, 0x04, 0x84, DTMF_SIGNAL_SPECIAL_DIAL_TONE },
9517   { 0x04, 0x04, 0x85, DTMF_SIGNAL_SECOND_DIAL_TONE },
9518   { 0x04, 0x04, 0x86, DTMF_SIGNAL_RINGING_TONE },
9519   { 0x04, 0x04, 0x87, DTMF_SIGNAL_SPECIAL_RINGING_TONE },
9520   { 0x04, 0x04, 0x88, DTMF_SIGNAL_BUSY_TONE },
9521   { 0x04, 0x04, 0x89, DTMF_SIGNAL_CONGESTION_TONE },
9522   { 0x04, 0x04, 0x8a, DTMF_SIGNAL_SPECIAL_INFORMATION_TONE },
9523   { 0x04, 0x04, 0x8b, DTMF_SIGNAL_COMFORT_TONE },
9524   { 0x04, 0x04, 0x8c, DTMF_SIGNAL_HOLD_TONE },
9525   { 0x04, 0x04, 0x8d, DTMF_SIGNAL_RECORD_TONE },
9526   { 0x04, 0x04, 0x8e, DTMF_SIGNAL_CALLER_WAITING_TONE },
9527   { 0x04, 0x04, 0x8f, DTMF_SIGNAL_CALL_WAITING_TONE },
9528   { 0x04, 0x04, 0x90, DTMF_SIGNAL_PAY_TONE },
9529   { 0x04, 0x04, 0x91, DTMF_SIGNAL_POSITIVE_INDICATION_TONE },
9530   { 0x04, 0x04, 0x92, DTMF_SIGNAL_NEGATIVE_INDICATION_TONE },
9531   { 0x04, 0x04, 0x93, DTMF_SIGNAL_WARNING_TONE },
9532   { 0x04, 0x04, 0x94, DTMF_SIGNAL_INTRUSION_TONE },
9533   { 0x04, 0x04, 0x95, DTMF_SIGNAL_CALLING_CARD_SERVICE_TONE },
9534   { 0x04, 0x04, 0x96, DTMF_SIGNAL_PAYPHONE_RECOGNITION_TONE },
9535   { 0x04, 0x04, 0x97, DTMF_SIGNAL_CPE_ALERTING_SIGNAL },
9536   { 0x04, 0x04, 0x98, DTMF_SIGNAL_OFF_HOOK_WARNING_TONE },
9537   { 0x04, 0x04, 0xbf, DTMF_SIGNAL_INTERCEPT_TONE },
9538   { 0x04, 0x04, 0xc0, DTMF_SIGNAL_MODEM_CALLING_TONE },
9539   { 0x04, 0x04, 0xc1, DTMF_SIGNAL_FAX_CALLING_TONE },
9540   { 0x04, 0x04, 0xc2, DTMF_SIGNAL_ANSWER_TONE },
9541   { 0x04, 0x04, 0xc3, DTMF_SIGNAL_REVERSED_ANSWER_TONE },
9542   { 0x04, 0x04, 0xc4, DTMF_SIGNAL_ANSAM_TONE },
9543   { 0x04, 0x04, 0xc5, DTMF_SIGNAL_REVERSED_ANSAM_TONE },
9544   { 0x04, 0x04, 0xc6, DTMF_SIGNAL_BELL103_ANSWER_TONE },
9545   { 0x04, 0x04, 0xc7, DTMF_SIGNAL_FAX_FLAGS },
9546   { 0x04, 0x04, 0xc8, DTMF_SIGNAL_G2_FAX_GROUP_ID },
9547   { 0x00, 0x04, 0xc9, DTMF_SIGNAL_HUMAN_SPEECH },
9548   { 0x04, 0x04, 0xca, DTMF_SIGNAL_ANSWERING_MACHINE_390 },
9549   { 0x02, 0x02, 0xf1, DTMF_MF_DIGIT_TONE_CODE_1 },
9550   { 0x02, 0x02, 0xf2, DTMF_MF_DIGIT_TONE_CODE_2 },
9551   { 0x02, 0x02, 0xf3, DTMF_MF_DIGIT_TONE_CODE_3 },
9552   { 0x02, 0x02, 0xf4, DTMF_MF_DIGIT_TONE_CODE_4 },
9553   { 0x02, 0x02, 0xf5, DTMF_MF_DIGIT_TONE_CODE_5 },
9554   { 0x02, 0x02, 0xf6, DTMF_MF_DIGIT_TONE_CODE_6 },
9555   { 0x02, 0x02, 0xf7, DTMF_MF_DIGIT_TONE_CODE_7 },
9556   { 0x02, 0x02, 0xf8, DTMF_MF_DIGIT_TONE_CODE_8 },
9557   { 0x02, 0x02, 0xf9, DTMF_MF_DIGIT_TONE_CODE_9 },
9558   { 0x02, 0x02, 0xfa, DTMF_MF_DIGIT_TONE_CODE_0 },
9559   { 0x02, 0x02, 0xfb, DTMF_MF_DIGIT_TONE_CODE_K1 },
9560   { 0x02, 0x02, 0xfc, DTMF_MF_DIGIT_TONE_CODE_K2 },
9561   { 0x02, 0x02, 0xfd, DTMF_MF_DIGIT_TONE_CODE_KP },
9562   { 0x02, 0x02, 0xfe, DTMF_MF_DIGIT_TONE_CODE_S1 },
9563   { 0x02, 0x02, 0xff, DTMF_MF_DIGIT_TONE_CODE_ST },
9564
9565 };
9566
9567 #define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
9568
9569
9570 static void dtmf_enable_receiver (PLCI   *plci, byte enable_mask)
9571 {
9572   word min_digit_duration, min_gap_duration;
9573
9574   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_enable_receiver %02x",
9575     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9576     (char   *)(FILE_), __LINE__, enable_mask));
9577
9578   if (enable_mask != 0)
9579   {
9580     min_digit_duration = (plci->dtmf_rec_pulse_ms == 0) ? 40 : plci->dtmf_rec_pulse_ms;
9581     min_gap_duration = (plci->dtmf_rec_pause_ms == 0) ? 40 : plci->dtmf_rec_pause_ms;
9582     plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_ENABLE_RECEIVER;
9583     PUT_WORD (&plci->internal_req_buffer[1], min_digit_duration);
9584     PUT_WORD (&plci->internal_req_buffer[3], min_gap_duration);
9585     plci->NData[0].PLength = 5;
9586
9587     PUT_WORD (&plci->internal_req_buffer[5], INTERNAL_IND_BUFFER_SIZE);
9588     plci->NData[0].PLength += 2;
9589     capidtmf_recv_enable (&(plci->capidtmf_state), min_digit_duration, min_gap_duration);
9590
9591   }
9592   else
9593   {
9594     plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_DISABLE_RECEIVER;
9595     plci->NData[0].PLength = 1;
9596
9597     capidtmf_recv_disable (&(plci->capidtmf_state));
9598
9599   }
9600   plci->NData[0].P = plci->internal_req_buffer;
9601   plci->NL.X = plci->NData;
9602   plci->NL.ReqCh = 0;
9603   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9604   plci->adapter->request (&plci->NL);
9605 }
9606
9607
9608 static void dtmf_send_digits (PLCI   *plci, byte   *digit_buffer, word digit_count)
9609 {
9610   word w, i;
9611
9612   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_digits %d",
9613     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9614     (char   *)(FILE_), __LINE__, digit_count));
9615
9616   plci->internal_req_buffer[0] = DTMF_UDATA_REQUEST_SEND_DIGITS;
9617   w = (plci->dtmf_send_pulse_ms == 0) ? 40 : plci->dtmf_send_pulse_ms;
9618   PUT_WORD (&plci->internal_req_buffer[1], w);
9619   w = (plci->dtmf_send_pause_ms == 0) ? 40 : plci->dtmf_send_pause_ms;
9620   PUT_WORD (&plci->internal_req_buffer[3], w);
9621   for (i = 0; i < digit_count; i++)
9622   {
9623     w = 0;
9624     while ((w < DTMF_DIGIT_MAP_ENTRIES)
9625       && (digit_buffer[i] != dtmf_digit_map[w].character))
9626     {
9627       w++;
9628     }
9629     plci->internal_req_buffer[5+i] = (w < DTMF_DIGIT_MAP_ENTRIES) ?
9630       dtmf_digit_map[w].code : DTMF_DIGIT_TONE_CODE_STAR;
9631   }
9632   plci->NData[0].PLength = 5 + digit_count;
9633   plci->NData[0].P = plci->internal_req_buffer;
9634   plci->NL.X = plci->NData;
9635   plci->NL.ReqCh = 0;
9636   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
9637   plci->adapter->request (&plci->NL);
9638 }
9639
9640
9641 static void dtmf_rec_clear_config (PLCI   *plci)
9642 {
9643
9644   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_rec_clear_config",
9645     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9646     (char   *)(FILE_), __LINE__));
9647
9648   plci->dtmf_rec_active = 0;
9649   plci->dtmf_rec_pulse_ms = 0;
9650   plci->dtmf_rec_pause_ms = 0;
9651
9652   capidtmf_init (&(plci->capidtmf_state), plci->adapter->u_law);
9653
9654 }
9655
9656
9657 static void dtmf_send_clear_config (PLCI   *plci)
9658 {
9659
9660   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_send_clear_config",
9661     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
9662     (char   *)(FILE_), __LINE__));
9663
9664   plci->dtmf_send_requests = 0;
9665   plci->dtmf_send_pulse_ms = 0;
9666   plci->dtmf_send_pause_ms = 0;
9667 }
9668
9669
9670 static void dtmf_prepare_switch (dword Id, PLCI   *plci)
9671 {
9672
9673   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_prepare_switch",
9674     UnMapId (Id), (char   *)(FILE_), __LINE__));
9675
9676   while (plci->dtmf_send_requests != 0)
9677     dtmf_confirmation (Id, plci);
9678 }
9679
9680
9681 static word dtmf_save_config (dword Id, PLCI   *plci, byte Rc)
9682 {
9683
9684   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_save_config %02x %d",
9685     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9686
9687   return (GOOD);
9688 }
9689
9690
9691 static word dtmf_restore_config (dword Id, PLCI   *plci, byte Rc)
9692 {
9693   word Info;
9694
9695   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_restore_config %02x %d",
9696     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
9697
9698   Info = GOOD;
9699   if (plci->B1_facilities & B1_FACILITY_DTMFR)
9700   {
9701     switch (plci->adjust_b_state)
9702     {
9703     case ADJUST_B_RESTORE_DTMF_1:
9704       plci->internal_command = plci->adjust_b_command;
9705       if (plci_nl_busy (plci))
9706       {
9707         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
9708         break;
9709       }
9710       dtmf_enable_receiver (plci, plci->dtmf_rec_active);
9711       plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_2;
9712       break;
9713     case ADJUST_B_RESTORE_DTMF_2:
9714       if ((Rc != OK) && (Rc != OK_FC))
9715       {
9716         dbug (1, dprintf ("[%06lx] %s,%d: Reenable DTMF receiver failed %02x",
9717           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9718         Info = _WRONG_STATE;
9719         break;
9720       }
9721       break;
9722     }
9723   }
9724   return (Info);
9725 }
9726
9727
9728 static void dtmf_command (dword Id, PLCI   *plci, byte Rc)
9729 {
9730   word internal_command, Info;
9731   byte mask;
9732     byte result[4];
9733
9734   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_command %02x %04x %04x %d %d %d %d",
9735     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
9736     plci->dtmf_cmd, plci->dtmf_rec_pulse_ms, plci->dtmf_rec_pause_ms,
9737     plci->dtmf_send_pulse_ms, plci->dtmf_send_pause_ms));
9738
9739   Info = GOOD;
9740   result[0] = 2;
9741   PUT_WORD (&result[1], DTMF_SUCCESS);
9742   internal_command = plci->internal_command;
9743   plci->internal_command = 0;
9744   mask = 0x01;
9745   switch (plci->dtmf_cmd)
9746   {
9747
9748   case DTMF_LISTEN_TONE_START:
9749     mask <<= 1;
9750   case DTMF_LISTEN_MF_START:
9751     mask <<= 1;
9752
9753   case DTMF_LISTEN_START:
9754     switch (internal_command)
9755     {
9756     default:
9757       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9758         B1_FACILITY_DTMFR), DTMF_COMMAND_1);
9759     case DTMF_COMMAND_1:
9760       if (adjust_b_process (Id, plci, Rc) != GOOD)
9761       {
9762         dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9763           UnMapId (Id), (char   *)(FILE_), __LINE__));
9764         Info = _FACILITY_NOT_SUPPORTED;
9765         break;
9766       }
9767       if (plci->internal_command)
9768         return;
9769     case DTMF_COMMAND_2:
9770       if (plci_nl_busy (plci))
9771       {
9772         plci->internal_command = DTMF_COMMAND_2;
9773         return;
9774       }
9775       plci->internal_command = DTMF_COMMAND_3;
9776       dtmf_enable_receiver (plci, (byte)(plci->dtmf_rec_active | mask));
9777       return;
9778     case DTMF_COMMAND_3:
9779       if ((Rc != OK) && (Rc != OK_FC))
9780       {
9781         dbug (1, dprintf ("[%06lx] %s,%d: Enable DTMF receiver failed %02x",
9782           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9783         Info = _FACILITY_NOT_SUPPORTED;
9784         break;
9785       }
9786
9787       plci->tone_last_indication_code = DTMF_SIGNAL_NO_TONE;
9788
9789       plci->dtmf_rec_active |= mask;
9790       break;
9791     }
9792     break;
9793
9794
9795   case DTMF_LISTEN_TONE_STOP:
9796     mask <<= 1;
9797   case DTMF_LISTEN_MF_STOP:
9798     mask <<= 1;
9799
9800   case DTMF_LISTEN_STOP:
9801     switch (internal_command)
9802     {
9803     default:
9804       plci->dtmf_rec_active &= ~mask;
9805       if (plci->dtmf_rec_active)
9806         break;
9807 /*
9808     case DTMF_COMMAND_1:
9809       if (plci->dtmf_rec_active)
9810       {
9811         if (plci_nl_busy (plci))
9812         {
9813           plci->internal_command = DTMF_COMMAND_1;
9814           return;
9815         }
9816         plci->dtmf_rec_active &= ~mask;
9817         plci->internal_command = DTMF_COMMAND_2;
9818         dtmf_enable_receiver (plci, false);
9819         return;
9820       }
9821       Rc = OK;
9822     case DTMF_COMMAND_2:
9823       if ((Rc != OK) && (Rc != OK_FC))
9824       {
9825         dbug (1, dprintf ("[%06lx] %s,%d: Disable DTMF receiver failed %02x",
9826           UnMapId (Id), (char far *)(FILE_), __LINE__, Rc));
9827         Info = _FACILITY_NOT_SUPPORTED;
9828         break;
9829       }
9830 */
9831       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
9832         ~(B1_FACILITY_DTMFX | B1_FACILITY_DTMFR)), DTMF_COMMAND_3);
9833     case DTMF_COMMAND_3:
9834       if (adjust_b_process (Id, plci, Rc) != GOOD)
9835       {
9836         dbug (1, dprintf ("[%06lx] %s,%d: Unload DTMF failed",
9837           UnMapId (Id), (char   *)(FILE_), __LINE__));
9838         Info = _FACILITY_NOT_SUPPORTED;
9839         break;
9840       }
9841       if (plci->internal_command)
9842         return;
9843       break;
9844     }
9845     break;
9846
9847
9848   case DTMF_SEND_TONE:
9849     mask <<= 1;
9850   case DTMF_SEND_MF:
9851     mask <<= 1;
9852
9853   case DTMF_DIGITS_SEND:
9854     switch (internal_command)
9855     {
9856     default:
9857       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
9858         ((plci->dtmf_parameter_length != 0) ? B1_FACILITY_DTMFX | B1_FACILITY_DTMFR : B1_FACILITY_DTMFX)),
9859         DTMF_COMMAND_1);
9860     case DTMF_COMMAND_1:
9861       if (adjust_b_process (Id, plci, Rc) != GOOD)
9862       {
9863         dbug (1, dprintf ("[%06lx] %s,%d: Load DTMF failed",
9864           UnMapId (Id), (char   *)(FILE_), __LINE__));
9865         Info = _FACILITY_NOT_SUPPORTED;
9866         break;
9867       }
9868       if (plci->internal_command)
9869         return;
9870     case DTMF_COMMAND_2:
9871       if (plci_nl_busy (plci))
9872       {
9873         plci->internal_command = DTMF_COMMAND_2;
9874         return;
9875       }
9876       plci->dtmf_msg_number_queue[(plci->dtmf_send_requests)++] = plci->number;
9877       plci->internal_command = DTMF_COMMAND_3;
9878       dtmf_send_digits (plci, &plci->saved_msg.parms[3].info[1], plci->saved_msg.parms[3].length);
9879       return;
9880     case DTMF_COMMAND_3:
9881       if ((Rc != OK) && (Rc != OK_FC))
9882       {
9883         dbug (1, dprintf ("[%06lx] %s,%d: Send DTMF digits failed %02x",
9884           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
9885         if (plci->dtmf_send_requests != 0)
9886           (plci->dtmf_send_requests)--;
9887         Info = _FACILITY_NOT_SUPPORTED;
9888         break;
9889       }
9890       return;
9891     }
9892     break;
9893   }
9894   sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
9895     "wws", Info, SELECTOR_DTMF, result);
9896 }
9897
9898
9899 static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
9900 {
9901   word Info;
9902   word i, j;
9903   byte mask;
9904     API_PARSE dtmf_parms[5];
9905     byte result[40];
9906
9907   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_request",
9908     UnMapId (Id), (char   *)(FILE_), __LINE__));
9909
9910   Info = GOOD;
9911   result[0] = 2;
9912   PUT_WORD (&result[1], DTMF_SUCCESS);
9913   if (!(a->profile.Global_Options & GL_DTMF_SUPPORTED))
9914   {
9915     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
9916       UnMapId (Id), (char   *)(FILE_), __LINE__));
9917     Info = _FACILITY_NOT_SUPPORTED;
9918   }
9919   else if (api_parse (&msg[1].info[1], msg[1].length, "w", dtmf_parms))
9920   {
9921     dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
9922       UnMapId (Id), (char   *)(FILE_), __LINE__));
9923     Info = _WRONG_MESSAGE_FORMAT;
9924   }
9925
9926   else if ((GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9927     || (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_SEND_CODES))
9928   {
9929     if (!((a->requested_options_table[appl->Id-1])
9930         & (1L << PRIVATE_DTMF_TONE)))
9931     {
9932       dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9933         UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9934       PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9935     }
9936     else
9937     {
9938       for (i = 0; i < 32; i++)
9939         result[4 + i] = 0;
9940       if (GET_WORD (dtmf_parms[0].info) == DTMF_GET_SUPPORTED_DETECT_CODES)
9941       {
9942         for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9943         {
9944           if (dtmf_digit_map[i].listen_mask != 0)
9945             result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9946         }
9947       }
9948       else
9949       {
9950         for (i = 0; i < DTMF_DIGIT_MAP_ENTRIES; i++)
9951         {
9952           if (dtmf_digit_map[i].send_mask != 0)
9953             result[4 + (dtmf_digit_map[i].character >> 3)] |= (1 << (dtmf_digit_map[i].character & 0x7));
9954         }
9955       }
9956       result[0] = 3 + 32;
9957       result[3] = 32;
9958     }
9959   }
9960
9961   else if (plci == NULL)
9962   {
9963     dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
9964       UnMapId (Id), (char   *)(FILE_), __LINE__));
9965     Info = _WRONG_IDENTIFIER;
9966   }
9967   else
9968   {
9969     if (!plci->State
9970      || !plci->NL.Id || plci->nl_remove_id)
9971     {
9972       dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
9973         UnMapId (Id), (char   *)(FILE_), __LINE__));
9974       Info = _WRONG_STATE;
9975     }
9976     else
9977     {
9978       plci->command = 0;
9979       plci->dtmf_cmd = GET_WORD (dtmf_parms[0].info);
9980       mask = 0x01;
9981       switch (plci->dtmf_cmd)
9982       {
9983
9984       case DTMF_LISTEN_TONE_START:
9985       case DTMF_LISTEN_TONE_STOP:
9986         mask <<= 1;
9987       case DTMF_LISTEN_MF_START:
9988       case DTMF_LISTEN_MF_STOP:
9989         mask <<= 1;
9990         if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
9991           & (1L << PRIVATE_DTMF_TONE)))
9992         {
9993           dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
9994             UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
9995           PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
9996           break;
9997         }
9998
9999       case DTMF_LISTEN_START:
10000       case DTMF_LISTEN_STOP:
10001         if (!(a->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
10002          && !(a->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
10003         {
10004           dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
10005             UnMapId (Id), (char   *)(FILE_), __LINE__));
10006           Info = _FACILITY_NOT_SUPPORTED;
10007           break;
10008         }
10009         if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10010         {
10011           if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10012           {
10013             plci->dtmf_rec_pulse_ms = 0;
10014             plci->dtmf_rec_pause_ms = 0;
10015           }
10016           else
10017           {
10018             plci->dtmf_rec_pulse_ms = GET_WORD (dtmf_parms[1].info);
10019             plci->dtmf_rec_pause_ms = GET_WORD (dtmf_parms[2].info);
10020           }
10021         }
10022         start_internal_command (Id, plci, dtmf_command);
10023         return (false);
10024
10025
10026       case DTMF_SEND_TONE:
10027         mask <<= 1;
10028       case DTMF_SEND_MF:
10029         mask <<= 1;
10030         if (!((plci->requested_options_conn | plci->requested_options | plci->adapter->requested_options_table[appl->Id-1])
10031           & (1L << PRIVATE_DTMF_TONE)))
10032         {
10033           dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10034             UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (dtmf_parms[0].info)));
10035           PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10036           break;
10037         }
10038
10039       case DTMF_DIGITS_SEND:
10040         if (api_parse (&msg[1].info[1], msg[1].length, "wwws", dtmf_parms))
10041         {
10042           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
10043             UnMapId (Id), (char   *)(FILE_), __LINE__));
10044           Info = _WRONG_MESSAGE_FORMAT;
10045           break;
10046         }
10047         if (mask & DTMF_LISTEN_ACTIVE_FLAG)
10048         {
10049           plci->dtmf_send_pulse_ms = GET_WORD (dtmf_parms[1].info);
10050           plci->dtmf_send_pause_ms = GET_WORD (dtmf_parms[2].info);
10051         }
10052         i = 0;
10053         j = 0;
10054         while ((i < dtmf_parms[3].length) && (j < DTMF_DIGIT_MAP_ENTRIES))
10055         {
10056           j = 0;
10057           while ((j < DTMF_DIGIT_MAP_ENTRIES)
10058             && ((dtmf_parms[3].info[i+1] != dtmf_digit_map[j].character)
10059              || ((dtmf_digit_map[j].send_mask & mask) == 0)))
10060           {
10061             j++;
10062           }
10063           i++;
10064         }
10065         if (j == DTMF_DIGIT_MAP_ENTRIES)
10066         {
10067           dbug (1, dprintf ("[%06lx] %s,%d: Incorrect DTMF digit %02x",
10068             UnMapId (Id), (char   *)(FILE_), __LINE__, dtmf_parms[3].info[i]));
10069           PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
10070           break;
10071         }
10072         if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
10073         {
10074           dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
10075             UnMapId (Id), (char   *)(FILE_), __LINE__));
10076           Info = _WRONG_STATE;
10077           break;
10078         }
10079         api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
10080         start_internal_command (Id, plci, dtmf_command);
10081         return (false);
10082
10083       default:
10084         dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
10085           UnMapId (Id), (char   *)(FILE_), __LINE__, plci->dtmf_cmd));
10086         PUT_WORD (&result[1], DTMF_UNKNOWN_REQUEST);
10087       }
10088     }
10089   }
10090   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
10091     "wws", Info, SELECTOR_DTMF, result);
10092   return (false);
10093 }
10094
10095
10096 static void dtmf_confirmation (dword Id, PLCI   *plci)
10097 {
10098   word Info;
10099   word i;
10100     byte result[4];
10101
10102   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
10103     UnMapId (Id), (char   *)(FILE_), __LINE__));
10104
10105   Info = GOOD;
10106   result[0] = 2;
10107   PUT_WORD (&result[1], DTMF_SUCCESS);
10108   if (plci->dtmf_send_requests != 0)
10109   {
10110     sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->dtmf_msg_number_queue[0],
10111       "wws", GOOD, SELECTOR_DTMF, result);
10112     (plci->dtmf_send_requests)--;
10113     for (i = 0; i < plci->dtmf_send_requests; i++)
10114       plci->dtmf_msg_number_queue[i] = plci->dtmf_msg_number_queue[i+1];      
10115   }
10116 }
10117
10118
10119 static void dtmf_indication (dword Id, PLCI   *plci, byte   *msg, word length)
10120 {
10121   word i, j, n;
10122
10123   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_indication",
10124     UnMapId (Id), (char   *)(FILE_), __LINE__));
10125
10126   n = 0;
10127   for (i = 1; i < length; i++)
10128   {
10129     j = 0;
10130     while ((j < DTMF_DIGIT_MAP_ENTRIES)
10131       && ((msg[i] != dtmf_digit_map[j].code)
10132        || ((dtmf_digit_map[j].listen_mask & plci->dtmf_rec_active) == 0)))
10133     {
10134       j++;
10135     }
10136     if (j < DTMF_DIGIT_MAP_ENTRIES)
10137     {
10138
10139       if ((dtmf_digit_map[j].listen_mask & DTMF_TONE_LISTEN_ACTIVE_FLAG)
10140        && (plci->tone_last_indication_code == DTMF_SIGNAL_NO_TONE)
10141        && (dtmf_digit_map[j].character != DTMF_SIGNAL_UNIDENTIFIED_TONE))
10142       {
10143         if (n + 1 == i)
10144         {
10145           for (i = length; i > n + 1; i--)
10146             msg[i] = msg[i - 1];
10147           length++;
10148           i++;
10149         }
10150         msg[++n] = DTMF_SIGNAL_UNIDENTIFIED_TONE;
10151       }
10152       plci->tone_last_indication_code = dtmf_digit_map[j].character;
10153
10154       msg[++n] = dtmf_digit_map[j].character;
10155     }
10156   }
10157   if (n != 0)
10158   {
10159     msg[0] = (byte) n;
10160     sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "wS", SELECTOR_DTMF, msg);
10161   }
10162 }
10163
10164
10165 /*------------------------------------------------------------------*/
10166 /* DTMF parameters                                                  */
10167 /*------------------------------------------------------------------*/
10168
10169 static void dtmf_parameter_write (PLCI   *plci)
10170 {
10171   word i;
10172     byte parameter_buffer[DTMF_PARAMETER_BUFFER_SIZE + 2];
10173
10174   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_write",
10175     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10176     (char   *)(FILE_), __LINE__));
10177
10178   parameter_buffer[0] = plci->dtmf_parameter_length + 1;
10179   parameter_buffer[1] = DSP_CTRL_SET_DTMF_PARAMETERS;
10180   for (i = 0; i < plci->dtmf_parameter_length; i++)
10181     parameter_buffer[2+i] = plci->dtmf_parameter_buffer[i];
10182   add_p (plci, FTY, parameter_buffer);
10183   sig_req (plci, TEL_CTRL, 0);
10184   send_req (plci);
10185 }
10186
10187
10188 static void dtmf_parameter_clear_config (PLCI   *plci)
10189 {
10190
10191   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_clear_config",
10192     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10193     (char   *)(FILE_), __LINE__));
10194
10195   plci->dtmf_parameter_length = 0;
10196 }
10197
10198
10199 static void dtmf_parameter_prepare_switch (dword Id, PLCI   *plci)
10200 {
10201
10202   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_prepare_switch",
10203     UnMapId (Id), (char   *)(FILE_), __LINE__));
10204
10205 }
10206
10207
10208 static word dtmf_parameter_save_config (dword Id, PLCI   *plci, byte Rc)
10209 {
10210
10211   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_save_config %02x %d",
10212     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10213
10214   return (GOOD);
10215 }
10216
10217
10218 static word dtmf_parameter_restore_config (dword Id, PLCI   *plci, byte Rc)
10219 {
10220   word Info;
10221
10222   dbug (1, dprintf ("[%06lx] %s,%d: dtmf_parameter_restore_config %02x %d",
10223     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
10224
10225   Info = GOOD;
10226   if ((plci->B1_facilities & B1_FACILITY_DTMFR)
10227    && (plci->dtmf_parameter_length != 0))
10228   {
10229     switch (plci->adjust_b_state)
10230     {
10231     case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
10232       plci->internal_command = plci->adjust_b_command;
10233       if (plci->sig_req)
10234       {
10235         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
10236         break;
10237       }
10238       dtmf_parameter_write (plci);
10239       plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_2;
10240       break;
10241     case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
10242       if ((Rc != OK) && (Rc != OK_FC))
10243       {
10244         dbug (1, dprintf ("[%06lx] %s,%d: Restore DTMF parameters failed %02x",
10245           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10246         Info = _WRONG_STATE;
10247         break;
10248       }
10249       break;
10250     }
10251   }
10252   return (Info);
10253 }
10254
10255
10256 /*------------------------------------------------------------------*/
10257 /* Line interconnect facilities                                     */
10258 /*------------------------------------------------------------------*/
10259
10260
10261 LI_CONFIG   *li_config_table;
10262 word li_total_channels;
10263
10264
10265 /*------------------------------------------------------------------*/
10266 /* translate a CHI information element to a channel number          */
10267 /* returns 0xff - any channel                                       */
10268 /*         0xfe - chi wrong coding                                  */
10269 /*         0xfd - D-channel                                         */
10270 /*         0x00 - no channel                                        */
10271 /*         else channel number / PRI: timeslot                      */
10272 /* if channels is provided we accept more than one channel.         */
10273 /*------------------------------------------------------------------*/
10274
10275 static byte chi_to_channel (byte   *chi, dword *pchannelmap)
10276 {
10277   int p;
10278   int i;
10279   dword map;
10280   byte excl;
10281   byte ofs;
10282   byte ch;
10283
10284   if (pchannelmap) *pchannelmap = 0;
10285   if(!chi[0]) return 0xff;
10286   excl = 0;
10287
10288   if(chi[1] & 0x20) {
10289     if(chi[0]==1 && chi[1]==0xac) return 0xfd; /* exclusive d-channel */
10290     for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10291     if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10292     if((chi[1] |0xc8)!=0xe9) return 0xfe;
10293     if(chi[1] &0x08) excl = 0x40;
10294
10295         /* int. id present */
10296     if(chi[1] &0x40) {
10297       p=i+1;
10298       for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10299       if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10300     }
10301
10302         /* coding standard, Number/Map, Channel Type */
10303     p=i+1;
10304     for(i=p; i<chi[0] && !(chi[i] &0x80); i++);
10305     if(i==chi[0] || !(chi[i] &0x80)) return 0xfe;
10306     if((chi[p]|0xd0)!=0xd3) return 0xfe;
10307
10308         /* Number/Map */
10309     if(chi[p] &0x10) {
10310
10311         /* map */
10312       if((chi[0]-p)==4) ofs = 0;
10313       else if((chi[0]-p)==3) ofs = 1;
10314       else return 0xfe;
10315       ch = 0;
10316       map = 0;
10317       for(i=0; i<4 && p<chi[0]; i++) {
10318         p++;
10319         ch += 8;
10320         map <<= 8;
10321         if(chi[p]) {
10322           for (ch=0; !(chi[p] & (1 << ch)); ch++);
10323           map |= chi[p];
10324         }
10325       }
10326       ch += ofs;
10327       map <<= ofs;
10328     }
10329     else {
10330
10331         /* number */
10332       p=i+1;
10333       ch = chi[p] &0x3f;
10334       if(pchannelmap) {
10335         if((byte)(chi[0]-p)>30) return 0xfe;
10336         map = 0;
10337         for(i=p; i<=chi[0]; i++) {
10338           if ((chi[i] &0x7f) > 31) return 0xfe;
10339           map |= (1L << (chi[i] &0x7f));
10340         }
10341       }
10342       else {
10343         if(p!=chi[0]) return 0xfe;
10344         if (ch > 31) return 0xfe;
10345         map = (1L << ch);
10346       }
10347       if(chi[p] &0x40) return 0xfe;
10348     }
10349     if (pchannelmap) *pchannelmap = map;
10350     else if (map != ((dword)(1L << ch))) return 0xfe;
10351     return (byte)(excl | ch);
10352   }
10353   else {  /* not PRI */
10354     for(i=1; i<chi[0] && !(chi[i] &0x80); i++);
10355     if(i!=chi[0] || !(chi[i] &0x80)) return 0xfe;
10356     if(chi[1] &0x08) excl = 0x40;
10357
10358     switch(chi[1] |0x98) {
10359     case 0x98: return 0;
10360     case 0x99:
10361       if (pchannelmap) *pchannelmap = 2;
10362       return excl |1;
10363     case 0x9a:
10364       if (pchannelmap) *pchannelmap = 4;
10365       return excl |2;
10366     case 0x9b: return 0xff;
10367     case 0x9c: return 0xfd; /* d-ch */
10368     default: return 0xfe;
10369     }
10370   }
10371 }
10372
10373
10374 static void mixer_set_bchannel_id_esc (PLCI   *plci, byte bchannel_id)
10375 {
10376   DIVA_CAPI_ADAPTER   *a;
10377   PLCI   *splci;
10378   byte old_id;
10379
10380   a = plci->adapter;
10381   old_id = plci->li_bchannel_id;
10382   if (a->li_pri)
10383   {
10384     if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10385       li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10386     plci->li_bchannel_id = (bchannel_id & 0x1f) + 1;
10387     if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10388       li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10389   }
10390   else
10391   {
10392     if (((bchannel_id & 0x03) == 1) || ((bchannel_id & 0x03) == 2))
10393     {
10394       if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10395         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10396       plci->li_bchannel_id = bchannel_id & 0x03;
10397       if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10398       {
10399         splci = a->AdvSignalPLCI;
10400         if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10401         {
10402           if ((splci->li_bchannel_id != 0)
10403            && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10404           {
10405             li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10406           }
10407           splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10408           li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10409           dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id_esc %d",
10410             (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10411             (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10412         }
10413       }
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   }
10418   if ((old_id == 0) && (plci->li_bchannel_id != 0)
10419    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10420   {
10421     mixer_clear_config (plci);
10422   }
10423   dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id_esc %d %d",
10424     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10425     (char   *)(FILE_), __LINE__, bchannel_id, plci->li_bchannel_id));
10426 }
10427
10428
10429 static void mixer_set_bchannel_id (PLCI   *plci, byte   *chi)
10430 {
10431   DIVA_CAPI_ADAPTER   *a;
10432   PLCI   *splci;
10433   byte ch, old_id;
10434
10435   a = plci->adapter;
10436   old_id = plci->li_bchannel_id;
10437   ch = chi_to_channel (chi, NULL);
10438   if (!(ch & 0x80))
10439   {
10440     if (a->li_pri)
10441     {
10442       if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10443         li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10444       plci->li_bchannel_id = (ch & 0x1f) + 1;
10445       if (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == NULL)
10446         li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci = plci;
10447     }
10448     else
10449     {
10450       if (((ch & 0x1f) == 1) || ((ch & 0x1f) == 2))
10451       {
10452         if ((old_id != 0) && (li_config_table[a->li_base + (old_id - 1)].plci == plci))
10453           li_config_table[a->li_base + (old_id - 1)].plci = NULL;
10454         plci->li_bchannel_id = ch & 0x1f;
10455         if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI != plci) && (a->AdvSignalPLCI->tel == ADV_VOICE))
10456         {
10457           splci = a->AdvSignalPLCI;
10458           if (li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci == NULL)
10459           {
10460             if ((splci->li_bchannel_id != 0)
10461              && (li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci == splci))
10462             {
10463               li_config_table[a->li_base + (splci->li_bchannel_id - 1)].plci = NULL;
10464             }
10465             splci->li_bchannel_id = 3 - plci->li_bchannel_id;
10466             li_config_table[a->li_base + (2 - plci->li_bchannel_id)].plci = splci;
10467             dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
10468               (dword)((splci->Id << 8) | UnMapController (splci->adapter->Id)),
10469               (char   *)(FILE_), __LINE__, splci->li_bchannel_id));
10470           }
10471         }
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     }
10476   }
10477   if ((old_id == 0) && (plci->li_bchannel_id != 0)
10478    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
10479   {
10480     mixer_clear_config (plci);
10481   }
10482   dbug (1, dprintf ("[%06lx] %s,%d: mixer_set_bchannel_id %02x %d",
10483     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10484     (char   *)(FILE_), __LINE__, ch, plci->li_bchannel_id));
10485 }
10486
10487
10488 #define MIXER_MAX_DUMP_CHANNELS 34
10489
10490 static void mixer_calculate_coefs (DIVA_CAPI_ADAPTER   *a)
10491 {
10492 static char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
10493   word n, i, j;
10494   char *p;
10495     char hex_line[2 * MIXER_MAX_DUMP_CHANNELS + MIXER_MAX_DUMP_CHANNELS / 8 + 4];
10496
10497   dbug (1, dprintf ("[%06lx] %s,%d: mixer_calculate_coefs",
10498     (dword)(UnMapController (a->Id)), (char   *)(FILE_), __LINE__));
10499
10500   for (i = 0; i < li_total_channels; i++)
10501   {
10502     li_config_table[i].channel &= LI_CHANNEL_ADDRESSES_SET;
10503     if (li_config_table[i].chflags != 0)
10504       li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10505     else
10506     {
10507       for (j = 0; j < li_total_channels; j++)
10508       {
10509         if (((li_config_table[i].flag_table[j]) != 0)
10510          || ((li_config_table[j].flag_table[i]) != 0))
10511         {
10512           li_config_table[i].channel |= LI_CHANNEL_INVOLVED;
10513         }
10514         if (((li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE) != 0)
10515          || ((li_config_table[j].flag_table[i] & LI_FLAG_CONFERENCE) != 0))
10516         {
10517           li_config_table[i].channel |= LI_CHANNEL_CONFERENCE;
10518         }
10519       }
10520     }
10521   }
10522   for (i = 0; i < li_total_channels; i++)
10523   {
10524     for (j = 0; j < li_total_channels; j++)
10525     {
10526       li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC);
10527       if (li_config_table[i].flag_table[j] & LI_FLAG_CONFERENCE)
10528         li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10529     }
10530   }
10531   for (n = 0; n < li_total_channels; n++)
10532   {
10533     if (li_config_table[n].channel & LI_CHANNEL_CONFERENCE)
10534     {
10535       for (i = 0; i < li_total_channels; i++)
10536       {
10537         if (li_config_table[i].channel & LI_CHANNEL_CONFERENCE)
10538         {
10539           for (j = 0; j < li_total_channels; j++)
10540           {
10541             li_config_table[i].coef_table[j] |=
10542               li_config_table[i].coef_table[n] & li_config_table[n].coef_table[j];
10543           }
10544         }
10545       }
10546     }
10547   }
10548   for (i = 0; i < li_total_channels; i++)
10549   {
10550     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10551     {
10552       li_config_table[i].coef_table[i] &= ~LI_COEF_CH_CH;
10553       for (j = 0; j < li_total_channels; j++)
10554       {
10555         if (li_config_table[i].coef_table[j] & LI_COEF_CH_CH)
10556           li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE;
10557       }
10558       if (li_config_table[i].flag_table[i] & LI_FLAG_CONFERENCE)
10559         li_config_table[i].coef_table[i] |= LI_COEF_CH_CH;
10560     }
10561   }
10562   for (i = 0; i < li_total_channels; i++)
10563   {
10564     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10565     {
10566       for (j = 0; j < li_total_channels; j++)
10567       {
10568         if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10569           li_config_table[i].coef_table[j] |= LI_COEF_CH_CH;
10570         if (li_config_table[i].flag_table[j] & LI_FLAG_MONITOR)
10571           li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10572         if (li_config_table[i].flag_table[j] & LI_FLAG_MIX)
10573           li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10574         if (li_config_table[i].flag_table[j] & LI_FLAG_PCCONNECT)
10575           li_config_table[i].coef_table[j] |= LI_COEF_PC_PC;
10576       }
10577       if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10578       {
10579         for (j = 0; j < li_total_channels; j++)
10580         {
10581           if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10582           {
10583             li_config_table[i].coef_table[j] |= LI_COEF_CH_PC;
10584             if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10585               li_config_table[i].coef_table[j] |= LI_COEF_PC_CH | LI_COEF_PC_PC;
10586           }
10587         }
10588       }
10589       if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10590       {
10591         for (j = 0; j < li_total_channels; j++)
10592         {
10593           if (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT)
10594             li_config_table[j].coef_table[i] |= LI_COEF_PC_CH;
10595         }
10596       }
10597       if (li_config_table[i].chflags & LI_CHFLAG_LOOP)
10598       {
10599         for (j = 0; j < li_total_channels; j++)
10600         {
10601           if (li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
10602           {
10603             for (n = 0; n < li_total_channels; n++)
10604             {
10605               if (li_config_table[n].flag_table[i] & LI_FLAG_INTERCONNECT)
10606               {
10607                 li_config_table[n].coef_table[j] |= LI_COEF_CH_CH;
10608                 if (li_config_table[j].chflags & LI_CHFLAG_MIX)
10609                 {
10610                   li_config_table[n].coef_table[j] |= LI_COEF_PC_CH;
10611                   if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10612                     li_config_table[n].coef_table[j] |= LI_COEF_CH_PC | LI_COEF_PC_PC;
10613                 }
10614                 else if (li_config_table[n].chflags & LI_CHFLAG_MONITOR)
10615                   li_config_table[n].coef_table[j] |= LI_COEF_CH_PC;
10616               }
10617             }
10618           }
10619         }
10620       }
10621     }
10622   }
10623   for (i = 0; i < li_total_channels; i++)
10624   {
10625     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10626     {
10627       if (li_config_table[i].chflags & (LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP))
10628         li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10629       if (li_config_table[i].chflags & LI_CHFLAG_MONITOR)
10630         li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10631       if (li_config_table[i].chflags & LI_CHFLAG_MIX)
10632         li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10633       for (j = 0; j < li_total_channels; j++)
10634       {
10635         if ((li_config_table[i].flag_table[j] &
10636           (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_MONITOR))
10637          || (li_config_table[j].flag_table[i] &
10638           (LI_FLAG_INTERCONNECT | LI_FLAG_PCCONNECT | LI_FLAG_CONFERENCE | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX)))
10639         {
10640           li_config_table[i].channel |= LI_CHANNEL_ACTIVE;
10641         }
10642         if (li_config_table[i].flag_table[j] & (LI_FLAG_PCCONNECT | LI_FLAG_MONITOR))
10643           li_config_table[i].channel |= LI_CHANNEL_RX_DATA;
10644         if (li_config_table[j].flag_table[i] & (LI_FLAG_PCCONNECT | LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX))
10645           li_config_table[i].channel |= LI_CHANNEL_TX_DATA;
10646       }
10647       if (!(li_config_table[i].channel & LI_CHANNEL_ACTIVE))
10648       {
10649         li_config_table[i].coef_table[i] |= LI_COEF_PC_CH | LI_COEF_CH_PC;
10650         li_config_table[i].channel |= LI_CHANNEL_TX_DATA | LI_CHANNEL_RX_DATA;
10651       }
10652     }
10653   }
10654   for (i = 0; i < li_total_channels; i++)
10655   {
10656     if (li_config_table[i].channel & LI_CHANNEL_INVOLVED)
10657     {
10658       j = 0;
10659       while ((j < li_total_channels) && !(li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT))
10660         j++;
10661       if (j < li_total_channels)
10662       {
10663         for (j = 0; j < li_total_channels; j++)
10664         {
10665           li_config_table[i].coef_table[j] &= ~(LI_COEF_CH_CH | LI_COEF_PC_CH);
10666           if (li_config_table[i].flag_table[j] & LI_FLAG_ANNOUNCEMENT)
10667             li_config_table[i].coef_table[j] |= LI_COEF_PC_CH;
10668         }
10669       }
10670     }
10671   }
10672   n = li_total_channels;
10673   if (n > MIXER_MAX_DUMP_CHANNELS)
10674     n = MIXER_MAX_DUMP_CHANNELS;
10675   p = hex_line;
10676   for (j = 0; j < n; j++)
10677   {
10678     if ((j & 0x7) == 0)
10679       *(p++) = ' ';
10680     *(p++) = hex_digit_table[li_config_table[j].curchnl >> 4];
10681     *(p++) = hex_digit_table[li_config_table[j].curchnl & 0xf];
10682   }
10683   *p = '\0';
10684   dbug (1, dprintf ("[%06lx] CURRENT %s",
10685     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10686   p = hex_line;
10687   for (j = 0; j < n; j++)
10688   {
10689     if ((j & 0x7) == 0)
10690       *(p++) = ' ';
10691     *(p++) = hex_digit_table[li_config_table[j].channel >> 4];
10692     *(p++) = hex_digit_table[li_config_table[j].channel & 0xf];
10693   }
10694   *p = '\0';
10695   dbug (1, dprintf ("[%06lx] CHANNEL %s",
10696     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10697   p = hex_line;
10698   for (j = 0; j < n; j++)
10699   {
10700     if ((j & 0x7) == 0)
10701       *(p++) = ' ';
10702     *(p++) = hex_digit_table[li_config_table[j].chflags >> 4];
10703     *(p++) = hex_digit_table[li_config_table[j].chflags & 0xf];
10704   }
10705   *p = '\0';
10706   dbug (1, dprintf ("[%06lx] CHFLAG  %s",
10707     (dword)(UnMapController (a->Id)), (char   *) hex_line));
10708   for (i = 0; i < n; i++)
10709   {
10710     p = hex_line;
10711     for (j = 0; j < n; j++)
10712     {
10713       if ((j & 0x7) == 0)
10714         *(p++) = ' ';
10715       *(p++) = hex_digit_table[li_config_table[i].flag_table[j] >> 4];
10716       *(p++) = hex_digit_table[li_config_table[i].flag_table[j] & 0xf];
10717     }
10718     *p = '\0';
10719     dbug (1, dprintf ("[%06lx] FLAG[%02x]%s",
10720       (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10721   }
10722   for (i = 0; i < n; i++)
10723   {
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[i].coef_table[j] >> 4];
10730       *(p++) = hex_digit_table[li_config_table[i].coef_table[j] & 0xf];
10731     }
10732     *p = '\0';
10733     dbug (1, dprintf ("[%06lx] COEF[%02x]%s",
10734       (dword)(UnMapController (a->Id)), i, (char   *) hex_line));
10735   }
10736 }
10737
10738
10739 static struct
10740 {
10741   byte mask;
10742   byte line_flags;
10743 } mixer_write_prog_pri[] =
10744 {
10745   { LI_COEF_CH_CH, 0 },
10746   { LI_COEF_CH_PC, MIXER_COEF_LINE_TO_PC_FLAG },
10747   { LI_COEF_PC_CH, MIXER_COEF_LINE_FROM_PC_FLAG },
10748   { LI_COEF_PC_PC, MIXER_COEF_LINE_TO_PC_FLAG | MIXER_COEF_LINE_FROM_PC_FLAG }
10749 };
10750
10751 static struct
10752 {
10753   byte from_ch;
10754   byte to_ch;
10755   byte mask;
10756   byte xconnect_override;
10757 } mixer_write_prog_bri[] =
10758 {
10759   { 0, 0, LI_COEF_CH_CH, 0x01 },  /* B      to B      */
10760   { 1, 0, LI_COEF_CH_CH, 0x01 },  /* Alt B  to B      */
10761   { 0, 0, LI_COEF_PC_CH, 0x80 },  /* PC     to B      */
10762   { 1, 0, LI_COEF_PC_CH, 0x01 },  /* Alt PC to B      */
10763   { 2, 0, LI_COEF_CH_CH, 0x00 },  /* IC     to B      */
10764   { 3, 0, LI_COEF_CH_CH, 0x00 },  /* Alt IC to B      */
10765   { 0, 0, LI_COEF_CH_PC, 0x80 },  /* B      to PC     */
10766   { 1, 0, LI_COEF_CH_PC, 0x01 },  /* Alt B  to PC     */
10767   { 0, 0, LI_COEF_PC_PC, 0x01 },  /* PC     to PC     */
10768   { 1, 0, LI_COEF_PC_PC, 0x01 },  /* Alt PC to PC     */
10769   { 2, 0, LI_COEF_CH_PC, 0x00 },  /* IC     to PC     */
10770   { 3, 0, LI_COEF_CH_PC, 0x00 },  /* Alt IC to PC     */
10771   { 0, 2, LI_COEF_CH_CH, 0x00 },  /* B      to IC     */
10772   { 1, 2, LI_COEF_CH_CH, 0x00 },  /* Alt B  to IC     */
10773   { 0, 2, LI_COEF_PC_CH, 0x00 },  /* PC     to IC     */
10774   { 1, 2, LI_COEF_PC_CH, 0x00 },  /* Alt PC to IC     */
10775   { 2, 2, LI_COEF_CH_CH, 0x00 },  /* IC     to IC     */
10776   { 3, 2, LI_COEF_CH_CH, 0x00 },  /* Alt IC to IC     */
10777   { 1, 1, LI_COEF_CH_CH, 0x01 },  /* Alt B  to Alt B  */
10778   { 0, 1, LI_COEF_CH_CH, 0x01 },  /* B      to Alt B  */
10779   { 1, 1, LI_COEF_PC_CH, 0x80 },  /* Alt PC to Alt B  */
10780   { 0, 1, LI_COEF_PC_CH, 0x01 },  /* PC     to Alt B  */
10781   { 3, 1, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt B  */
10782   { 2, 1, LI_COEF_CH_CH, 0x00 },  /* IC     to Alt B  */
10783   { 1, 1, LI_COEF_CH_PC, 0x80 },  /* Alt B  to Alt PC */
10784   { 0, 1, LI_COEF_CH_PC, 0x01 },  /* B      to Alt PC */
10785   { 1, 1, LI_COEF_PC_PC, 0x01 },  /* Alt PC to Alt PC */
10786   { 0, 1, LI_COEF_PC_PC, 0x01 },  /* PC     to Alt PC */
10787   { 3, 1, LI_COEF_CH_PC, 0x00 },  /* Alt IC to Alt PC */
10788   { 2, 1, LI_COEF_CH_PC, 0x00 },  /* IC     to Alt PC */
10789   { 1, 3, LI_COEF_CH_CH, 0x00 },  /* Alt B  to Alt IC */
10790   { 0, 3, LI_COEF_CH_CH, 0x00 },  /* B      to Alt IC */
10791   { 1, 3, LI_COEF_PC_CH, 0x00 },  /* Alt PC to Alt IC */
10792   { 0, 3, LI_COEF_PC_CH, 0x00 },  /* PC     to Alt IC */
10793   { 3, 3, LI_COEF_CH_CH, 0x00 },  /* Alt IC to Alt IC */
10794   { 2, 3, LI_COEF_CH_CH, 0x00 }   /* IC     to Alt IC */
10795 };
10796
10797 static byte mixer_swapped_index_bri[] =
10798 {
10799   18,  /* B      to B      */
10800   19,  /* Alt B  to B      */
10801   20,  /* PC     to B      */
10802   21,  /* Alt PC to B      */
10803   22,  /* IC     to B      */
10804   23,  /* Alt IC to B      */
10805   24,  /* B      to PC     */
10806   25,  /* Alt B  to PC     */
10807   26,  /* PC     to PC     */
10808   27,  /* Alt PC to PC     */
10809   28,  /* IC     to PC     */
10810   29,  /* Alt IC to PC     */
10811   30,  /* B      to IC     */
10812   31,  /* Alt B  to IC     */
10813   32,  /* PC     to IC     */
10814   33,  /* Alt PC to IC     */
10815   34,  /* IC     to IC     */
10816   35,  /* Alt IC to IC     */
10817   0,   /* Alt B  to Alt B  */
10818   1,   /* B      to Alt B  */
10819   2,   /* Alt PC to Alt B  */
10820   3,   /* PC     to Alt B  */
10821   4,   /* Alt IC to Alt B  */
10822   5,   /* IC     to Alt B  */
10823   6,   /* Alt B  to Alt PC */
10824   7,   /* B      to Alt PC */
10825   8,   /* Alt PC to Alt PC */
10826   9,   /* PC     to Alt PC */
10827   10,  /* Alt IC to Alt PC */
10828   11,  /* IC     to Alt PC */
10829   12,  /* Alt B  to Alt IC */
10830   13,  /* B      to Alt IC */
10831   14,  /* Alt PC to Alt IC */
10832   15,  /* PC     to Alt IC */
10833   16,  /* Alt IC to Alt IC */
10834   17   /* IC     to Alt IC */
10835 };
10836
10837 static struct
10838 {
10839   byte mask;
10840   byte from_pc;
10841   byte to_pc;
10842 } xconnect_write_prog[] =
10843 {
10844   { LI_COEF_CH_CH, false, false },
10845   { LI_COEF_CH_PC, false, true },
10846   { LI_COEF_PC_CH, true, false },
10847   { LI_COEF_PC_PC, true, true }
10848 };
10849
10850
10851 static void xconnect_query_addresses (PLCI   *plci)
10852 {
10853   DIVA_CAPI_ADAPTER   *a;
10854   word w, ch;
10855   byte   *p;
10856
10857   dbug (1, dprintf ("[%06lx] %s,%d: xconnect_query_addresses",
10858     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10859     (char   *)(FILE_), __LINE__));
10860
10861   a = plci->adapter;
10862   if (a->li_pri && ((plci->li_bchannel_id == 0)
10863    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci)))
10864   {
10865     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10866       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10867       (char   *)(FILE_), __LINE__));
10868     return;
10869   }
10870   p = plci->internal_req_buffer;
10871   ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10872   *(p++) = UDATA_REQUEST_XCONNECT_FROM;
10873   w = ch;
10874   *(p++) = (byte) w;
10875   *(p++) = (byte)(w >> 8);
10876   w = ch | XCONNECT_CHANNEL_PORT_PC;
10877   *(p++) = (byte) w;
10878   *(p++) = (byte)(w >> 8);
10879   plci->NData[0].P = plci->internal_req_buffer;
10880   plci->NData[0].PLength = p - plci->internal_req_buffer;
10881   plci->NL.X = plci->NData;
10882   plci->NL.ReqCh = 0;
10883   plci->NL.Req = plci->nl_req = (byte) N_UDATA;
10884   plci->adapter->request (&plci->NL);
10885 }
10886
10887
10888 static void xconnect_write_coefs (PLCI   *plci, word internal_command)
10889 {
10890
10891   dbug (1, dprintf ("[%06lx] %s,%d: xconnect_write_coefs %04x",
10892     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
10893     (char   *)(FILE_), __LINE__, internal_command));
10894
10895   plci->li_write_command = internal_command;
10896   plci->li_write_channel = 0;
10897 }
10898
10899
10900 static byte xconnect_write_coefs_process (dword Id, PLCI   *plci, byte Rc)
10901 {
10902   DIVA_CAPI_ADAPTER   *a;
10903   word w, n, i, j, r, s, to_ch;
10904   dword d;
10905   byte   *p;
10906   struct xconnect_transfer_address_s   *transfer_address;
10907   byte ch_map[MIXER_CHANNELS_BRI];
10908
10909   dbug (1, dprintf ("[%06x] %s,%d: xconnect_write_coefs_process %02x %d",
10910     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->li_write_channel));
10911
10912   a = plci->adapter;
10913   if ((plci->li_bchannel_id == 0)
10914    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
10915   {
10916     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
10917       UnMapId (Id), (char   *)(FILE_), __LINE__));
10918     return (true);
10919   }
10920   i = a->li_base + (plci->li_bchannel_id - 1);
10921   j = plci->li_write_channel;
10922   p = plci->internal_req_buffer;
10923   if (j != 0)
10924   {
10925     if ((Rc != OK) && (Rc != OK_FC))
10926     {
10927       dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
10928         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
10929       return (false);
10930     }
10931   }
10932   if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
10933   {
10934     r = 0;
10935     s = 0;
10936     if (j < li_total_channels)
10937     {
10938       if (li_config_table[i].channel & LI_CHANNEL_ADDRESSES_SET)
10939       {
10940         s = ((li_config_table[i].send_b.card_address.low | li_config_table[i].send_b.card_address.high) ?
10941             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_PC | LI_COEF_PC_PC)) &
10942           ((li_config_table[i].send_pc.card_address.low | li_config_table[i].send_pc.card_address.high) ?
10943             (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_PC_CH));
10944       }
10945       r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10946       while ((j < li_total_channels)
10947         && ((r == 0)
10948          || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
10949          || (!li_config_table[j].adapter->li_pri
10950           && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
10951          || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
10952            || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
10953           && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
10954            || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
10955          || ((li_config_table[j].adapter->li_base != a->li_base)
10956           && !(r & s &
10957             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10958               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10959             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10960               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))))
10961       {
10962         j++;
10963         if (j < li_total_channels)
10964           r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
10965       }
10966     }
10967     if (j < li_total_channels)
10968     {
10969       plci->internal_command = plci->li_write_command;
10970       if (plci_nl_busy (plci))
10971         return (true);
10972       to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
10973       *(p++) = UDATA_REQUEST_XCONNECT_TO;
10974       do
10975       {
10976         if (li_config_table[j].adapter->li_base != a->li_base)
10977         {
10978           r &= s &
10979             ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
10980               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
10981             ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
10982               (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC));
10983         }
10984         n = 0;
10985         do
10986         {
10987           if (r & xconnect_write_prog[n].mask)
10988           {
10989             if (xconnect_write_prog[n].from_pc)
10990               transfer_address = &(li_config_table[j].send_pc);
10991             else
10992               transfer_address = &(li_config_table[j].send_b);
10993             d = transfer_address->card_address.low;
10994             *(p++) = (byte) d;
10995             *(p++) = (byte)(d >> 8);
10996             *(p++) = (byte)(d >> 16);
10997             *(p++) = (byte)(d >> 24);
10998             d = transfer_address->card_address.high;
10999             *(p++) = (byte) d;
11000             *(p++) = (byte)(d >> 8);
11001             *(p++) = (byte)(d >> 16);
11002             *(p++) = (byte)(d >> 24);
11003             d = transfer_address->offset;
11004             *(p++) = (byte) d;
11005             *(p++) = (byte)(d >> 8);
11006             *(p++) = (byte)(d >> 16);
11007             *(p++) = (byte)(d >> 24);
11008             w = xconnect_write_prog[n].to_pc ? to_ch | XCONNECT_CHANNEL_PORT_PC : to_ch;
11009             *(p++) = (byte) w;
11010             *(p++) = (byte)(w >> 8);
11011             w = ((li_config_table[i].coef_table[j] & xconnect_write_prog[n].mask) == 0) ? 0x01 :
11012               (li_config_table[i].adapter->u_law ?
11013                  (li_config_table[j].adapter->u_law ? 0x80 : 0x86) :
11014                  (li_config_table[j].adapter->u_law ? 0x7a : 0x80));
11015             *(p++) = (byte) w;
11016             *(p++) = (byte) 0;
11017             li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
11018           }
11019           n++;
11020         } while ((n < ARRAY_SIZE(xconnect_write_prog))
11021           && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11022         if (n == ARRAY_SIZE(xconnect_write_prog))
11023         {
11024           do
11025           {
11026             j++;
11027             if (j < li_total_channels)
11028               r = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11029           } while ((j < li_total_channels)
11030             && ((r == 0)
11031              || (!(li_config_table[j].channel & LI_CHANNEL_ADDRESSES_SET))
11032              || (!li_config_table[j].adapter->li_pri
11033               && (j >= li_config_table[j].adapter->li_base + MIXER_BCHANNELS_BRI))
11034              || (((li_config_table[j].send_b.card_address.low != li_config_table[i].send_b.card_address.low)
11035                || (li_config_table[j].send_b.card_address.high != li_config_table[i].send_b.card_address.high))
11036               && (!(a->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)
11037                || !(li_config_table[j].adapter->manufacturer_features & MANUFACTURER_FEATURE_DMACONNECT)))
11038              || ((li_config_table[j].adapter->li_base != a->li_base)
11039               && !(r & s &
11040                 ((li_config_table[j].send_b.card_address.low | li_config_table[j].send_b.card_address.high) ?
11041                   (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_PC_CH | LI_COEF_PC_PC)) &
11042                 ((li_config_table[j].send_pc.card_address.low | li_config_table[j].send_pc.card_address.high) ?
11043                   (LI_COEF_CH_CH | LI_COEF_CH_PC | LI_COEF_PC_CH | LI_COEF_PC_PC) : (LI_COEF_CH_CH | LI_COEF_CH_PC))))));
11044         }
11045       } while ((j < li_total_channels)
11046         && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
11047     }
11048     else if (j == li_total_channels)
11049     {
11050       plci->internal_command = plci->li_write_command;
11051       if (plci_nl_busy (plci))
11052         return (true);
11053       if (a->li_pri)
11054       {
11055         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11056         w = 0;
11057         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11058           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11059         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11060           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11061         *(p++) = (byte) w;
11062         *(p++) = (byte)(w >> 8);
11063       }
11064       else
11065       {
11066         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11067         w = 0;
11068         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11069          && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11070         {
11071           w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11072         }
11073         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11074           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11075         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11076           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11077         *(p++) = (byte) w;
11078         *(p++) = (byte)(w >> 8);
11079         for (j = 0; j < sizeof(ch_map); j += 2)
11080         {
11081           if (plci->li_bchannel_id == 2)
11082           {
11083             ch_map[j] = (byte)(j+1);
11084             ch_map[j+1] = (byte) j;
11085           }
11086           else
11087           {
11088             ch_map[j] = (byte) j;
11089             ch_map[j+1] = (byte)(j+1);
11090           }
11091         }
11092         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11093         {
11094           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11095           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11096           if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11097           {
11098             *p = (mixer_write_prog_bri[n].xconnect_override != 0) ?
11099               mixer_write_prog_bri[n].xconnect_override :
11100               ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11101             if ((i >= a->li_base + MIXER_BCHANNELS_BRI) || (j >= a->li_base + MIXER_BCHANNELS_BRI))
11102             {
11103               w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11104               li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11105             }
11106           }
11107           else
11108           {
11109             *p = 0x00;
11110             if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11111             {
11112               w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11113               if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11114                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11115             }
11116           }
11117           p++;
11118         }
11119       }
11120       j = li_total_channels + 1;
11121     }
11122   }
11123   else
11124   {
11125     if (j <= li_total_channels)
11126     {
11127       plci->internal_command = plci->li_write_command;
11128       if (plci_nl_busy (plci))
11129         return (true);
11130       if (j < a->li_base)
11131         j = a->li_base;
11132       if (a->li_pri)
11133       {
11134         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
11135         w = 0;
11136         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11137           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11138         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11139           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11140         *(p++) = (byte) w;
11141         *(p++) = (byte)(w >> 8);
11142         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
11143         {
11144           *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
11145           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11146           {
11147             w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11148             if (w & mixer_write_prog_pri[n].mask)
11149             {
11150               *(p++) = (li_config_table[i].coef_table[j] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11151               li_config_table[i].coef_table[j] ^= mixer_write_prog_pri[n].mask << 4;
11152             }
11153             else
11154               *(p++) = 0x00;
11155           }
11156           *(p++) = (byte)((plci->li_bchannel_id - 1) | MIXER_COEF_LINE_ROW_FLAG | mixer_write_prog_pri[n].line_flags);
11157           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
11158           {
11159             w = ((li_config_table[j].coef_table[i] & 0xf) ^ (li_config_table[j].coef_table[i] >> 4));
11160             if (w & mixer_write_prog_pri[n].mask)
11161             {
11162               *(p++) = (li_config_table[j].coef_table[i] & mixer_write_prog_pri[n].mask) ? 0x80 : 0x01;
11163               li_config_table[j].coef_table[i] ^= mixer_write_prog_pri[n].mask << 4;
11164             }
11165             else
11166               *(p++) = 0x00;
11167           }
11168         }
11169       }
11170       else
11171       {
11172         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_BRI;
11173         w = 0;
11174         if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI)
11175          && (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length))
11176         {
11177           w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
11178         }
11179         if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
11180           w |= MIXER_FEATURE_ENABLE_TX_DATA;
11181         if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
11182           w |= MIXER_FEATURE_ENABLE_RX_DATA;
11183         *(p++) = (byte) w;
11184         *(p++) = (byte)(w >> 8);
11185         for (j = 0; j < sizeof(ch_map); j += 2)
11186         {
11187           if (plci->li_bchannel_id == 2)
11188           {
11189             ch_map[j] = (byte)(j+1);
11190             ch_map[j+1] = (byte) j;
11191           }
11192           else
11193           {
11194             ch_map[j] = (byte) j;
11195             ch_map[j+1] = (byte)(j+1);
11196           }
11197         }
11198         for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
11199         {
11200           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
11201           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
11202           if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
11203           {
11204             *p = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
11205             w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
11206             li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
11207           }
11208           else
11209           {
11210             *p = 0x00;
11211             if ((a->AdvSignalPLCI != NULL) && (a->AdvSignalPLCI->tel == ADV_VOICE))
11212             {
11213               w = (plci == a->AdvSignalPLCI) ? n : mixer_swapped_index_bri[n];
11214               if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w < a->adv_voice_coef_length)
11215                 *p = a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + w];
11216             }
11217           }
11218           p++;
11219         }
11220       }
11221       j = li_total_channels + 1;
11222     }
11223   }
11224   plci->li_write_channel = j;
11225   if (p != plci->internal_req_buffer)
11226   {
11227     plci->NData[0].P = plci->internal_req_buffer;
11228     plci->NData[0].PLength = p - plci->internal_req_buffer;
11229     plci->NL.X = plci->NData;
11230     plci->NL.ReqCh = 0;
11231     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
11232     plci->adapter->request (&plci->NL);
11233   }
11234   return (true);
11235 }
11236
11237
11238 static void mixer_notify_update (PLCI   *plci, byte others)
11239 {
11240   DIVA_CAPI_ADAPTER   *a;
11241   word i, w;
11242   PLCI   *notify_plci;
11243     byte msg[sizeof(CAPI_MSG_HEADER) + 6];
11244
11245   dbug (1, dprintf ("[%06lx] %s,%d: mixer_notify_update %d",
11246     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11247     (char   *)(FILE_), __LINE__, others));
11248
11249   a = plci->adapter;
11250   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
11251   {
11252     if (others)
11253       plci->li_notify_update = true;
11254     i = 0;
11255     do
11256     {
11257       notify_plci = NULL;
11258       if (others)
11259       {
11260         while ((i < li_total_channels) && (li_config_table[i].plci == NULL))
11261           i++;
11262         if (i < li_total_channels)
11263           notify_plci = li_config_table[i++].plci;
11264       }
11265       else
11266       {
11267         if ((plci->li_bchannel_id != 0)
11268          && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11269         {
11270           notify_plci = plci;
11271         }
11272       }
11273       if ((notify_plci != NULL)
11274        && !notify_plci->li_notify_update
11275        && (notify_plci->appl != NULL)
11276        && (notify_plci->State)
11277        && notify_plci->NL.Id && !notify_plci->nl_remove_id)
11278       {
11279         notify_plci->li_notify_update = true;
11280         ((CAPI_MSG *) msg)->header.length = 18;
11281         ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
11282         ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
11283         ((CAPI_MSG *) msg)->header.number = 0;
11284         ((CAPI_MSG *) msg)->header.controller = notify_plci->adapter->Id;
11285         ((CAPI_MSG *) msg)->header.plci = notify_plci->Id;
11286         ((CAPI_MSG *) msg)->header.ncci = 0;
11287         ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
11288         ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
11289         PUT_WORD (&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
11290         ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
11291         w = api_put (notify_plci->appl, (CAPI_MSG *) msg);
11292         if (w != _QUEUE_FULL)
11293         {
11294           if (w != 0)
11295           {
11296             dbug (1, dprintf ("[%06lx] %s,%d: Interconnect notify failed %06x %d",
11297               (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11298               (char   *)(FILE_), __LINE__,
11299               (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
11300           }
11301           notify_plci->li_notify_update = false;
11302         }
11303       }
11304     } while (others && (notify_plci != NULL));
11305     if (others)
11306       plci->li_notify_update = false;
11307   }
11308 }
11309
11310
11311 static void mixer_clear_config (PLCI   *plci)
11312 {
11313   DIVA_CAPI_ADAPTER   *a;
11314   word i, j;
11315
11316   dbug (1, dprintf ("[%06lx] %s,%d: mixer_clear_config",
11317     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
11318     (char   *)(FILE_), __LINE__));
11319
11320   plci->li_notify_update = false;
11321   plci->li_plci_b_write_pos = 0;
11322   plci->li_plci_b_read_pos = 0;
11323   plci->li_plci_b_req_pos = 0;
11324   a = plci->adapter;
11325   if ((plci->li_bchannel_id != 0)
11326    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11327   {
11328     i = a->li_base + (plci->li_bchannel_id - 1);
11329     li_config_table[i].curchnl = 0;
11330     li_config_table[i].channel = 0;
11331     li_config_table[i].chflags = 0;
11332     for (j = 0; j < li_total_channels; j++)
11333     {
11334       li_config_table[j].flag_table[i] = 0;
11335       li_config_table[i].flag_table[j] = 0;
11336       li_config_table[i].coef_table[j] = 0;
11337       li_config_table[j].coef_table[i] = 0;
11338     }
11339     if (!a->li_pri)
11340     {
11341       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11342       if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11343       {
11344         i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11345         li_config_table[i].curchnl = 0;
11346         li_config_table[i].channel = 0;
11347         li_config_table[i].chflags = 0;
11348         for (j = 0; j < li_total_channels; j++)
11349         {
11350           li_config_table[i].flag_table[j] = 0;
11351           li_config_table[j].flag_table[i] = 0;
11352           li_config_table[i].coef_table[j] = 0;
11353           li_config_table[j].coef_table[i] = 0;
11354         }
11355         if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11356         {
11357           i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11358           li_config_table[i].curchnl = 0;
11359           li_config_table[i].channel = 0;
11360           li_config_table[i].chflags = 0;
11361           for (j = 0; j < li_total_channels; j++)
11362           {
11363             li_config_table[i].flag_table[j] = 0;
11364             li_config_table[j].flag_table[i] = 0;
11365             li_config_table[i].coef_table[j] = 0;
11366             li_config_table[j].coef_table[i] = 0;
11367           }
11368         }
11369       }
11370     }
11371   }
11372 }
11373
11374
11375 static void mixer_prepare_switch (dword Id, PLCI   *plci)
11376 {
11377
11378   dbug (1, dprintf ("[%06lx] %s,%d: mixer_prepare_switch",
11379     UnMapId (Id), (char   *)(FILE_), __LINE__));
11380
11381   do
11382   {
11383     mixer_indication_coefs_set (Id, plci);
11384   } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11385 }
11386
11387
11388 static word mixer_save_config (dword Id, PLCI   *plci, byte Rc)
11389 {
11390   DIVA_CAPI_ADAPTER   *a;
11391   word i, j;
11392
11393   dbug (1, dprintf ("[%06lx] %s,%d: mixer_save_config %02x %d",
11394     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11395
11396   a = plci->adapter;
11397   if ((plci->li_bchannel_id != 0)
11398    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11399   {
11400     i = a->li_base + (plci->li_bchannel_id - 1);
11401     for (j = 0; j < li_total_channels; j++)
11402     {
11403       li_config_table[i].coef_table[j] &= 0xf;
11404       li_config_table[j].coef_table[i] &= 0xf;
11405     }
11406     if (!a->li_pri)
11407       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
11408   }
11409   return (GOOD);
11410 }
11411
11412
11413 static word mixer_restore_config (dword Id, PLCI   *plci, byte Rc)
11414 {
11415   DIVA_CAPI_ADAPTER   *a;
11416   word Info;
11417
11418   dbug (1, dprintf ("[%06lx] %s,%d: mixer_restore_config %02x %d",
11419     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
11420
11421   Info = GOOD;
11422   a = plci->adapter;
11423   if ((plci->B1_facilities & B1_FACILITY_MIXER)
11424    && (plci->li_bchannel_id != 0)
11425    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
11426   {
11427     switch (plci->adjust_b_state)
11428     {
11429     case ADJUST_B_RESTORE_MIXER_1:
11430       if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11431       {
11432         plci->internal_command = plci->adjust_b_command;
11433         if (plci_nl_busy (plci))
11434         {
11435           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
11436           break;
11437         }
11438         xconnect_query_addresses (plci);
11439         plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_2;
11440         break;
11441       }
11442       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11443       Rc = OK;
11444     case ADJUST_B_RESTORE_MIXER_2:
11445     case ADJUST_B_RESTORE_MIXER_3:
11446     case ADJUST_B_RESTORE_MIXER_4:
11447       if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
11448       {
11449         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B query addresses failed %02x",
11450           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
11451         Info = _WRONG_STATE;
11452         break;
11453       }
11454       if (Rc == OK)
11455       {
11456         if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11457           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_3;
11458         else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)
11459           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11460       }
11461       else if (Rc == 0)
11462       {
11463         if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
11464           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_4;
11465         else if (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
11466           plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_5;
11467       }
11468       if (plci->adjust_b_state != ADJUST_B_RESTORE_MIXER_5)
11469       {
11470         plci->internal_command = plci->adjust_b_command;
11471         break;
11472       }
11473     case ADJUST_B_RESTORE_MIXER_5:
11474       xconnect_write_coefs (plci, plci->adjust_b_command);
11475       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_6;
11476       Rc = OK;
11477     case ADJUST_B_RESTORE_MIXER_6:
11478       if (!xconnect_write_coefs_process (Id, plci, Rc))
11479       {
11480         dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11481           UnMapId (Id), (char   *)(FILE_), __LINE__));
11482         Info = _FACILITY_NOT_SUPPORTED;
11483         break;
11484       }
11485       if (plci->internal_command)
11486         break;
11487       plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_7;
11488     case ADJUST_B_RESTORE_MIXER_7:
11489       break;
11490     }
11491   }
11492   return (Info);
11493 }
11494
11495
11496 static void mixer_command (dword Id, PLCI   *plci, byte Rc)
11497 {
11498   DIVA_CAPI_ADAPTER   *a;
11499   word i, internal_command, Info;
11500
11501   dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
11502     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
11503     plci->li_cmd));
11504
11505   Info = GOOD;
11506   a = plci->adapter;
11507   internal_command = plci->internal_command;
11508   plci->internal_command = 0;
11509   switch (plci->li_cmd)
11510   {
11511   case LI_REQ_CONNECT:
11512   case LI_REQ_DISCONNECT:
11513   case LI_REQ_SILENT_UPDATE:
11514     switch (internal_command)
11515     {
11516     default:
11517       if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11518       {
11519         adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
11520           B1_FACILITY_MIXER), MIXER_COMMAND_1);
11521       }
11522     case MIXER_COMMAND_1:
11523       if (plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11524       {
11525         if (adjust_b_process (Id, plci, Rc) != GOOD)
11526         {
11527           dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
11528             UnMapId (Id), (char   *)(FILE_), __LINE__));
11529           Info = _FACILITY_NOT_SUPPORTED;
11530           break;
11531         }
11532         if (plci->internal_command)
11533           return;
11534       }
11535       plci->li_plci_b_req_pos = plci->li_plci_b_write_pos;
11536       if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11537        || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11538         && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11539          ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11540       {
11541         xconnect_write_coefs (plci, MIXER_COMMAND_2);
11542       }
11543       else
11544       {
11545         do
11546         {
11547           mixer_indication_coefs_set (Id, plci);
11548         } while (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos);
11549       }
11550     case MIXER_COMMAND_2:
11551       if ((plci->li_channel_bits & LI_CHANNEL_INVOLVED)
11552        || ((get_b1_facilities (plci, plci->B1_resource) & B1_FACILITY_MIXER)
11553         && (add_b1_facilities (plci, plci->B1_resource, (word)(plci->B1_facilities &
11554          ~B1_FACILITY_MIXER)) == plci->B1_resource)))
11555       {
11556         if (!xconnect_write_coefs_process (Id, plci, Rc))
11557         {
11558           dbug (1, dprintf ("[%06lx] %s,%d: Write mixer coefs failed",
11559             UnMapId (Id), (char   *)(FILE_), __LINE__));
11560           if (plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11561           {
11562             do
11563             {
11564               plci->li_plci_b_write_pos = (plci->li_plci_b_write_pos == 0) ?
11565                 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11566               i = (plci->li_plci_b_write_pos == 0) ?
11567                 LI_PLCI_B_QUEUE_ENTRIES-1 : plci->li_plci_b_write_pos - 1;
11568             } while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
11569               && !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
11570           }
11571           Info = _FACILITY_NOT_SUPPORTED;
11572           break;
11573         }
11574         if (plci->internal_command)
11575           return;
11576       }
11577       if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11578       {
11579         adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
11580           ~B1_FACILITY_MIXER), MIXER_COMMAND_3);
11581       }
11582     case MIXER_COMMAND_3:
11583       if (!(plci->li_channel_bits & LI_CHANNEL_INVOLVED))
11584       {
11585         if (adjust_b_process (Id, plci, Rc) != GOOD)
11586         {
11587           dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
11588             UnMapId (Id), (char   *)(FILE_), __LINE__));
11589           Info = _FACILITY_NOT_SUPPORTED;
11590           break;
11591         }
11592         if (plci->internal_command)
11593           return;
11594       }
11595       break;
11596     }
11597     break;
11598   }
11599   if ((plci->li_bchannel_id == 0)
11600    || (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci != plci))
11601   {
11602     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out %d",
11603       UnMapId (Id), (char   *)(FILE_), __LINE__, (int)(plci->li_bchannel_id)));
11604   }
11605   else
11606   {
11607     i = a->li_base + (plci->li_bchannel_id - 1);
11608     li_config_table[i].curchnl = plci->li_channel_bits;
11609     if (!a->li_pri && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
11610     {
11611       i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
11612       li_config_table[i].curchnl = plci->li_channel_bits;
11613       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
11614       {
11615         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
11616         li_config_table[i].curchnl = plci->li_channel_bits;
11617       }
11618     }
11619   }
11620 }
11621
11622
11623 static void li_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11624   dword plci_b_id, byte connect, dword li_flags)
11625 {
11626   word i, ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11627   PLCI   *plci_b;
11628   DIVA_CAPI_ADAPTER   *a_b;
11629
11630   a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11631   plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11632   ch_a = a->li_base + (plci->li_bchannel_id - 1);
11633   if (!a->li_pri && (plci->tel == ADV_VOICE)
11634    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11635   {
11636     ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11637     ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11638       a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11639   }
11640   else
11641   {
11642     ch_a_v = ch_a;
11643     ch_a_s = ch_a;
11644   }
11645   ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11646   if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11647    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11648   {
11649     ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11650     ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11651       a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11652   }
11653   else
11654   {
11655     ch_b_v = ch_b;
11656     ch_b_s = ch_b;
11657   }
11658   if (connect)
11659   {
11660     li_config_table[ch_a].flag_table[ch_a_v] &= ~LI_FLAG_MONITOR;
11661     li_config_table[ch_a].flag_table[ch_a_s] &= ~LI_FLAG_MONITOR;
11662     li_config_table[ch_a_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11663     li_config_table[ch_a_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11664   }
11665   li_config_table[ch_a].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11666   li_config_table[ch_a].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11667   li_config_table[ch_b_v].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11668   li_config_table[ch_b_s].flag_table[ch_a] &= ~(LI_FLAG_ANNOUNCEMENT | LI_FLAG_MIX);
11669   if (ch_a_v == ch_b_v)
11670   {
11671     li_config_table[ch_a_v].flag_table[ch_b_v] &= ~LI_FLAG_CONFERENCE;
11672     li_config_table[ch_a_s].flag_table[ch_b_s] &= ~LI_FLAG_CONFERENCE;
11673   }
11674   else
11675   {
11676     if (li_config_table[ch_a_v].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11677     {
11678       for (i = 0; i < li_total_channels; i++)
11679       {
11680         if (i != ch_a_v)
11681           li_config_table[ch_a_v].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11682       }
11683     }
11684     if (li_config_table[ch_a_s].flag_table[ch_b_v] & LI_FLAG_CONFERENCE)
11685     {
11686       for (i = 0; i < li_total_channels; i++)
11687       {
11688         if (i != ch_a_s)
11689           li_config_table[ch_a_s].flag_table[i] &= ~LI_FLAG_CONFERENCE;
11690       }
11691     }
11692     if (li_config_table[ch_b_v].flag_table[ch_a_v] & LI_FLAG_CONFERENCE)
11693     {
11694       for (i = 0; i < li_total_channels; i++)
11695       {
11696         if (i != ch_a_v)
11697           li_config_table[i].flag_table[ch_a_v] &= ~LI_FLAG_CONFERENCE;
11698       }
11699     }
11700     if (li_config_table[ch_b_v].flag_table[ch_a_s] & LI_FLAG_CONFERENCE)
11701     {
11702       for (i = 0; i < li_total_channels; i++)
11703       {
11704         if (i != ch_a_s)
11705           li_config_table[i].flag_table[ch_a_s] &= ~LI_FLAG_CONFERENCE;
11706       }
11707     }
11708   }
11709   if (li_flags & LI_FLAG_CONFERENCE_A_B)
11710   {
11711     li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11712     li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11713     li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11714     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11715   }
11716   if (li_flags & LI_FLAG_CONFERENCE_B_A)
11717   {
11718     li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11719     li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11720     li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11721     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11722   }
11723   if (li_flags & LI_FLAG_MONITOR_A)
11724   {
11725     li_config_table[ch_a].flag_table[ch_a_v] |= LI_FLAG_MONITOR;
11726     li_config_table[ch_a].flag_table[ch_a_s] |= LI_FLAG_MONITOR;
11727   }
11728   if (li_flags & LI_FLAG_MONITOR_B)
11729   {
11730     li_config_table[ch_a].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11731     li_config_table[ch_a].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11732   }
11733   if (li_flags & LI_FLAG_ANNOUNCEMENT_A)
11734   {
11735     li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11736     li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11737   }
11738   if (li_flags & LI_FLAG_ANNOUNCEMENT_B)
11739   {
11740     li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11741     li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_ANNOUNCEMENT;
11742   }
11743   if (li_flags & LI_FLAG_MIX_A)
11744   {
11745     li_config_table[ch_a_v].flag_table[ch_a] |= LI_FLAG_MIX;
11746     li_config_table[ch_a_s].flag_table[ch_a] |= LI_FLAG_MIX;
11747   }
11748   if (li_flags & LI_FLAG_MIX_B)
11749   {
11750     li_config_table[ch_b_v].flag_table[ch_a] |= LI_FLAG_MIX;
11751     li_config_table[ch_b_s].flag_table[ch_a] |= LI_FLAG_MIX;
11752   }
11753   if (ch_a_v != ch_a_s)
11754   {
11755     li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11756     li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11757   }
11758   if (ch_b_v != ch_b_s)
11759   {
11760     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11761     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11762   }
11763 }
11764
11765
11766 static void li2_update_connect (dword Id, DIVA_CAPI_ADAPTER   *a, PLCI   *plci,
11767   dword plci_b_id, byte connect, dword li_flags)
11768 {
11769   word ch_a, ch_a_v, ch_a_s, ch_b, ch_b_v, ch_b_s;
11770   PLCI   *plci_b;
11771   DIVA_CAPI_ADAPTER   *a_b;
11772
11773   a_b = &(adapter[MapController ((byte)(plci_b_id & 0x7f)) - 1]);
11774   plci_b = &(a_b->plci[((plci_b_id >> 8) & 0xff) - 1]);
11775   ch_a = a->li_base + (plci->li_bchannel_id - 1);
11776   if (!a->li_pri && (plci->tel == ADV_VOICE)
11777    && (plci == a->AdvSignalPLCI) && (Id & EXT_CONTROLLER))
11778   {
11779     ch_a_v = ch_a + MIXER_IC_CHANNEL_BASE;
11780     ch_a_s = (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11781       a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id) : ch_a_v;
11782   }
11783   else
11784   {
11785     ch_a_v = ch_a;
11786     ch_a_s = ch_a;
11787   }
11788   ch_b = a_b->li_base + (plci_b->li_bchannel_id - 1);
11789   if (!a_b->li_pri && (plci_b->tel == ADV_VOICE)
11790    && (plci_b == a_b->AdvSignalPLCI) && (plci_b_id & EXT_CONTROLLER))
11791   {
11792     ch_b_v = ch_b + MIXER_IC_CHANNEL_BASE;
11793     ch_b_s = (a_b->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC) ?
11794       a_b->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci_b->li_bchannel_id) : ch_b_v;
11795   }
11796   else
11797   {
11798     ch_b_v = ch_b;
11799     ch_b_s = ch_b;
11800   }
11801   if (connect)
11802   {
11803     li_config_table[ch_b].flag_table[ch_b_v] &= ~LI_FLAG_MONITOR;
11804     li_config_table[ch_b].flag_table[ch_b_s] &= ~LI_FLAG_MONITOR;
11805     li_config_table[ch_b_v].flag_table[ch_b] &= ~LI_FLAG_MIX;
11806     li_config_table[ch_b_s].flag_table[ch_b] &= ~LI_FLAG_MIX;
11807     li_config_table[ch_b].flag_table[ch_b] &= ~LI_FLAG_PCCONNECT;
11808     li_config_table[ch_b].chflags &= ~(LI_CHFLAG_MONITOR | LI_CHFLAG_MIX | LI_CHFLAG_LOOP);
11809   }
11810   li_config_table[ch_b_v].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11811   li_config_table[ch_b_s].flag_table[ch_a_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11812   li_config_table[ch_b_v].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11813   li_config_table[ch_b_s].flag_table[ch_a_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11814   li_config_table[ch_a_v].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11815   li_config_table[ch_a_v].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11816   li_config_table[ch_a_s].flag_table[ch_b_v] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11817   li_config_table[ch_a_s].flag_table[ch_b_s] &= ~(LI_FLAG_INTERCONNECT | LI_FLAG_CONFERENCE);
11818   if (li_flags & LI2_FLAG_INTERCONNECT_A_B)
11819   {
11820     li_config_table[ch_b_v].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11821     li_config_table[ch_b_s].flag_table[ch_a_v] |= LI_FLAG_INTERCONNECT;
11822     li_config_table[ch_b_v].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11823     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_INTERCONNECT;
11824   }
11825   if (li_flags & LI2_FLAG_INTERCONNECT_B_A)
11826   {
11827     li_config_table[ch_a_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11828     li_config_table[ch_a_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11829     li_config_table[ch_a_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11830     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11831   }
11832   if (li_flags & LI2_FLAG_MONITOR_B)
11833   {
11834     li_config_table[ch_b].flag_table[ch_b_v] |= LI_FLAG_MONITOR;
11835     li_config_table[ch_b].flag_table[ch_b_s] |= LI_FLAG_MONITOR;
11836   }
11837   if (li_flags & LI2_FLAG_MIX_B)
11838   {
11839     li_config_table[ch_b_v].flag_table[ch_b] |= LI_FLAG_MIX;
11840     li_config_table[ch_b_s].flag_table[ch_b] |= LI_FLAG_MIX;
11841   }
11842   if (li_flags & LI2_FLAG_MONITOR_X)
11843     li_config_table[ch_b].chflags |= LI_CHFLAG_MONITOR;
11844   if (li_flags & LI2_FLAG_MIX_X)
11845     li_config_table[ch_b].chflags |= LI_CHFLAG_MIX;
11846   if (li_flags & LI2_FLAG_LOOP_B)
11847   {
11848     li_config_table[ch_b_v].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11849     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_INTERCONNECT;
11850     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11851     li_config_table[ch_b_s].flag_table[ch_b_s] |= LI_FLAG_INTERCONNECT;
11852   }
11853   if (li_flags & LI2_FLAG_LOOP_PC)
11854     li_config_table[ch_b].flag_table[ch_b] |= LI_FLAG_PCCONNECT;
11855   if (li_flags & LI2_FLAG_LOOP_X)
11856     li_config_table[ch_b].chflags |= LI_CHFLAG_LOOP;
11857   if (li_flags & LI2_FLAG_PCCONNECT_A_B)
11858     li_config_table[ch_b_s].flag_table[ch_a_s] |= LI_FLAG_PCCONNECT;
11859   if (li_flags & LI2_FLAG_PCCONNECT_B_A)
11860     li_config_table[ch_a_s].flag_table[ch_b_s] |= LI_FLAG_PCCONNECT;
11861   if (ch_a_v != ch_a_s)
11862   {
11863     li_config_table[ch_a_v].flag_table[ch_a_s] |= LI_FLAG_CONFERENCE;
11864     li_config_table[ch_a_s].flag_table[ch_a_v] |= LI_FLAG_CONFERENCE;
11865   }
11866   if (ch_b_v != ch_b_s)
11867   {
11868     li_config_table[ch_b_v].flag_table[ch_b_s] |= LI_FLAG_CONFERENCE;
11869     li_config_table[ch_b_s].flag_table[ch_b_v] |= LI_FLAG_CONFERENCE;
11870   }
11871 }
11872
11873
11874 static word li_check_main_plci (dword Id, PLCI   *plci)
11875 {
11876   if (plci == NULL)
11877   {
11878     dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
11879       UnMapId (Id), (char   *)(FILE_), __LINE__));
11880     return (_WRONG_IDENTIFIER);
11881   }
11882   if (!plci->State
11883    || !plci->NL.Id || plci->nl_remove_id
11884    || (plci->li_bchannel_id == 0))
11885   {
11886     dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
11887       UnMapId (Id), (char   *)(FILE_), __LINE__));
11888     return (_WRONG_STATE);
11889   }
11890   li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = plci;
11891   return (GOOD);
11892 }
11893
11894
11895 static PLCI   *li_check_plci_b (dword Id, PLCI   *plci,
11896   dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11897 {
11898   byte ctlr_b;
11899   PLCI   *plci_b;
11900
11901   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11902     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11903   {
11904     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11905       UnMapId (Id), (char   *)(FILE_), __LINE__));
11906     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11907     return (NULL);
11908   }
11909   ctlr_b = 0;
11910   if ((plci_b_id & 0x7f) != 0)
11911   {
11912     ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11913     if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11914       ctlr_b = 0;
11915   }
11916   if ((ctlr_b == 0)
11917    || (((plci_b_id >> 8) & 0xff) == 0)
11918    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11919   {
11920     dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11921       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11922     PUT_WORD (p_result, _WRONG_IDENTIFIER);
11923     return (NULL);
11924   }
11925   plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11926   if (!plci_b->State
11927    || !plci_b->NL.Id || plci_b->nl_remove_id
11928    || (plci_b->li_bchannel_id == 0))
11929   {
11930     dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11931       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11932     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11933     return (NULL);
11934   }
11935   li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci = plci_b;
11936   if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
11937     ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
11938    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
11939     || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
11940   {
11941     dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
11942       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11943     PUT_WORD (p_result, _WRONG_IDENTIFIER);
11944     return (NULL);
11945   }
11946   if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
11947     (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
11948   {
11949     dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
11950       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
11951     PUT_WORD (p_result, _REQUEST_NOT_ALLOWED_IN_THIS_STATE);
11952     return (NULL);
11953   }
11954   return (plci_b);
11955 }
11956
11957
11958 static PLCI   *li2_check_plci_b (dword Id, PLCI   *plci,
11959   dword plci_b_id, word plci_b_write_pos, byte   *p_result)
11960 {
11961   byte ctlr_b;
11962   PLCI   *plci_b;
11963
11964   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
11965     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
11966   {
11967     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
11968       UnMapId (Id), (char   *)(FILE_), __LINE__));
11969     PUT_WORD (p_result, _WRONG_STATE);
11970     return (NULL);
11971   }
11972   ctlr_b = 0;
11973   if ((plci_b_id & 0x7f) != 0)
11974   {
11975     ctlr_b = MapController ((byte)(plci_b_id & 0x7f));
11976     if ((ctlr_b > max_adapter) || ((ctlr_b != 0) && (adapter[ctlr_b - 1].request == NULL)))
11977       ctlr_b = 0;
11978   }
11979   if ((ctlr_b == 0)
11980    || (((plci_b_id >> 8) & 0xff) == 0)
11981    || (((plci_b_id >> 8) & 0xff) > adapter[ctlr_b - 1].max_plci))
11982   {
11983     dbug (1, dprintf ("[%06lx] %s,%d: LI invalid second PLCI %08lx",
11984       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11985     PUT_WORD (p_result, _WRONG_IDENTIFIER);
11986     return (NULL);
11987   }
11988   plci_b = &(adapter[ctlr_b - 1].plci[((plci_b_id >> 8) & 0xff) - 1]);
11989   if (!plci_b->State
11990    || !plci_b->NL.Id || plci_b->nl_remove_id
11991    || (plci_b->li_bchannel_id == 0)
11992    || (li_config_table[plci_b->adapter->li_base + (plci_b->li_bchannel_id - 1)].plci != plci_b))
11993   {
11994     dbug (1, dprintf ("[%06lx] %s,%d: LI peer in wrong state %08lx",
11995       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
11996     PUT_WORD (p_result, _WRONG_STATE);
11997     return (NULL);
11998   }
11999   if (((byte)(plci_b_id & ~EXT_CONTROLLER)) !=
12000     ((byte)(UnMapController (plci->adapter->Id) & ~EXT_CONTROLLER))
12001    && (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12002     || !(plci_b->adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)))
12003   {
12004     dbug (1, dprintf ("[%06lx] %s,%d: LI not on same ctrl %08lx",
12005       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b_id));
12006     PUT_WORD (p_result, _WRONG_IDENTIFIER);
12007     return (NULL);
12008   }
12009   if (!(get_b1_facilities (plci_b, add_b1_facilities (plci_b, plci_b->B1_resource,
12010     (word)(plci_b->B1_facilities | B1_FACILITY_MIXER))) & B1_FACILITY_MIXER))
12011   {
12012     dbug (1, dprintf ("[%06lx] %s,%d: Interconnect peer cannot mix %d",
12013       UnMapId (Id), (char   *)(FILE_), __LINE__, plci_b->B1_resource));
12014     PUT_WORD (p_result, _WRONG_STATE);
12015     return (NULL);
12016   }
12017   return (plci_b);
12018 }
12019
12020
12021 static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12022 {
12023   word Info;
12024   word i;
12025   dword d, li_flags, plci_b_id;
12026   PLCI   *plci_b;
12027     API_PARSE li_parms[3];
12028     API_PARSE li_req_parms[3];
12029     API_PARSE li_participant_struct[2];
12030     API_PARSE li_participant_parms[3];
12031   word participant_parms_pos;
12032   byte result_buffer[32];
12033   byte   *result;
12034   word result_pos;
12035   word plci_b_write_pos;
12036
12037   dbug (1, dprintf ("[%06lx] %s,%d: mixer_request",
12038     UnMapId (Id), (char   *)(FILE_), __LINE__));
12039
12040   Info = GOOD;
12041   result = result_buffer;
12042   result_buffer[0] = 0;
12043   if (!(a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED))
12044   {
12045     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12046       UnMapId (Id), (char   *)(FILE_), __LINE__));
12047     Info = _FACILITY_NOT_SUPPORTED;
12048   }
12049   else if (api_parse (&msg[1].info[1], msg[1].length, "ws", li_parms))
12050   {
12051     dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12052       UnMapId (Id), (char   *)(FILE_), __LINE__));
12053     Info = _WRONG_MESSAGE_FORMAT;
12054   }
12055   else
12056   {
12057     result_buffer[0] = 3;
12058     PUT_WORD (&result_buffer[1], GET_WORD (li_parms[0].info));
12059     result_buffer[3] = 0;
12060     switch (GET_WORD (li_parms[0].info))
12061     {
12062     case LI_GET_SUPPORTED_SERVICES:
12063       if (appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12064       {
12065         result_buffer[0] = 17;
12066         result_buffer[3] = 14;
12067         PUT_WORD (&result_buffer[4], GOOD);
12068         d = 0;
12069         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_CH)
12070           d |= LI_CONFERENCING_SUPPORTED;
12071         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12072           d |= LI_MONITORING_SUPPORTED;
12073         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12074           d |= LI_ANNOUNCEMENTS_SUPPORTED | LI_MIXING_SUPPORTED;
12075         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12076           d |= LI_CROSS_CONTROLLER_SUPPORTED;
12077         PUT_DWORD (&result_buffer[6], d);
12078         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12079         {
12080           d = 0;
12081           for (i = 0; i < li_total_channels; i++)
12082           {
12083             if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12084              && (li_config_table[i].adapter->li_pri
12085               || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12086             {
12087               d++;
12088             }
12089           }
12090         }
12091         else
12092         {
12093           d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12094         }
12095         PUT_DWORD (&result_buffer[10], d / 2);
12096         PUT_DWORD (&result_buffer[14], d);
12097       }
12098       else
12099       {
12100         result_buffer[0] = 25;
12101         result_buffer[3] = 22;
12102         PUT_WORD (&result_buffer[4], GOOD);
12103         d = LI2_ASYMMETRIC_SUPPORTED | LI2_B_LOOPING_SUPPORTED | LI2_X_LOOPING_SUPPORTED;
12104         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_CH_PC)
12105           d |= LI2_MONITORING_SUPPORTED | LI2_REMOTE_MONITORING_SUPPORTED;
12106         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_CH)
12107           d |= LI2_MIXING_SUPPORTED | LI2_REMOTE_MIXING_SUPPORTED;
12108         if (a->manufacturer_features & MANUFACTURER_FEATURE_MIXER_PC_PC)
12109           d |= LI2_PC_LOOPING_SUPPORTED;
12110         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12111           d |= LI2_CROSS_CONTROLLER_SUPPORTED;
12112         PUT_DWORD (&result_buffer[6], d);
12113         d = a->li_pri ? a->li_channels : MIXER_BCHANNELS_BRI;
12114         PUT_DWORD (&result_buffer[10], d / 2);
12115         PUT_DWORD (&result_buffer[14], d - 1);
12116         if (a->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12117         {
12118           d = 0;
12119           for (i = 0; i < li_total_channels; i++)
12120           {
12121             if ((li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
12122              && (li_config_table[i].adapter->li_pri
12123               || (i < li_config_table[i].adapter->li_base + MIXER_BCHANNELS_BRI)))
12124             {
12125               d++;
12126             }
12127           }
12128         }
12129         PUT_DWORD (&result_buffer[18], d / 2);
12130         PUT_DWORD (&result_buffer[22], d - 1);
12131       }
12132       break;
12133
12134     case LI_REQ_CONNECT:
12135       if (li_parms[1].length == 8)
12136       {
12137         appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12138         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "dd", li_req_parms))
12139         {
12140           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12141             UnMapId (Id), (char   *)(FILE_), __LINE__));
12142           Info = _WRONG_MESSAGE_FORMAT;
12143           break;
12144         }
12145         plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12146         li_flags = GET_DWORD (li_req_parms[1].info);
12147         Info = li_check_main_plci (Id, plci);
12148         result_buffer[0] = 9;
12149         result_buffer[3] = 6;
12150         PUT_DWORD (&result_buffer[4], plci_b_id);
12151         PUT_WORD (&result_buffer[8], GOOD);
12152         if (Info != GOOD)
12153           break;
12154         result = plci->saved_msg.info;
12155         for (i = 0; i <= result_buffer[0]; i++)
12156           result[i] = result_buffer[i];
12157         plci_b_write_pos = plci->li_plci_b_write_pos;
12158         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12159         if (plci_b == NULL)
12160           break;
12161         li_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12162         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
12163         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12164         plci->li_plci_b_write_pos = plci_b_write_pos;
12165       }
12166       else
12167       {
12168         appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12169         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "ds", li_req_parms))
12170         {
12171           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12172             UnMapId (Id), (char   *)(FILE_), __LINE__));
12173           Info = _WRONG_MESSAGE_FORMAT;
12174           break;
12175         }
12176         li_flags = GET_DWORD (li_req_parms[0].info) & ~(LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A);
12177         Info = li_check_main_plci (Id, plci);
12178         result_buffer[0] = 7;
12179         result_buffer[3] = 4;
12180         PUT_WORD (&result_buffer[4], Info);
12181         result_buffer[6] = 0;
12182         if (Info != GOOD)
12183           break;
12184         result = plci->saved_msg.info;
12185         for (i = 0; i <= result_buffer[0]; i++)
12186           result[i] = result_buffer[i];
12187         plci_b_write_pos = plci->li_plci_b_write_pos;
12188         participant_parms_pos = 0;
12189         result_pos = 7;
12190         li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags);
12191         while (participant_parms_pos < li_req_parms[1].length)
12192         {
12193           result[result_pos] = 6;
12194           result_pos += 7;
12195           PUT_DWORD (&result[result_pos - 6], 0);
12196           PUT_WORD (&result[result_pos - 2], GOOD);
12197           if (api_parse (&li_req_parms[1].info[1 + participant_parms_pos],
12198             (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12199           {
12200             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12201               UnMapId (Id), (char   *)(FILE_), __LINE__));
12202             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12203             break;
12204           }
12205           if (api_parse (&li_participant_struct[0].info[1],
12206             li_participant_struct[0].length, "dd", li_participant_parms))
12207           {
12208             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12209               UnMapId (Id), (char   *)(FILE_), __LINE__));
12210             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12211             break;
12212           }
12213           plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12214           li_flags = GET_DWORD (li_participant_parms[1].info);
12215           PUT_DWORD (&result[result_pos - 6], plci_b_id);
12216           if (sizeof(result) - result_pos < 7)
12217           {
12218             dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12219               UnMapId (Id), (char   *)(FILE_), __LINE__));
12220             PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12221             break;
12222           }
12223           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12224           if (plci_b != NULL)
12225           {
12226             li2_update_connect (Id, a, plci, plci_b_id, true, li_flags);
12227             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
12228               ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
12229               LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
12230             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12231           }
12232           participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12233             (&li_req_parms[1].info[1]));
12234         }
12235         result[0] = (byte)(result_pos - 1);
12236         result[3] = (byte)(result_pos - 4);
12237         result[6] = (byte)(result_pos - 7);
12238         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12239         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12240          || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12241         {
12242           plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12243           plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12244         }
12245         else
12246           plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12247         plci->li_plci_b_write_pos = plci_b_write_pos;
12248       }
12249       mixer_calculate_coefs (a);
12250       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12251       mixer_notify_update (plci, true);
12252       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12253         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12254       plci->command = 0;
12255       plci->li_cmd = GET_WORD (li_parms[0].info);
12256       start_internal_command (Id, plci, mixer_command);
12257       return (false);
12258
12259     case LI_REQ_DISCONNECT:
12260       if (li_parms[1].length == 4)
12261       {
12262         appl->appl_flags |= APPL_FLAG_OLD_LI_SPEC;
12263         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "d", li_req_parms))
12264         {
12265           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12266             UnMapId (Id), (char   *)(FILE_), __LINE__));
12267           Info = _WRONG_MESSAGE_FORMAT;
12268           break;
12269         }
12270         plci_b_id = GET_DWORD (li_req_parms[0].info) & 0xffff;
12271         Info = li_check_main_plci (Id, plci);
12272         result_buffer[0] = 9;
12273         result_buffer[3] = 6;
12274         PUT_DWORD (&result_buffer[4], GET_DWORD (li_req_parms[0].info));
12275         PUT_WORD (&result_buffer[8], GOOD);
12276         if (Info != GOOD)
12277           break;
12278         result = plci->saved_msg.info;
12279         for (i = 0; i <= result_buffer[0]; i++)
12280           result[i] = result_buffer[i];
12281         plci_b_write_pos = plci->li_plci_b_write_pos;
12282         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
12283         if (plci_b == NULL)
12284           break;
12285         li_update_connect (Id, a, plci, plci_b_id, false, 0);
12286         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
12287         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12288         plci->li_plci_b_write_pos = plci_b_write_pos;
12289       }
12290       else
12291       {
12292         appl->appl_flags &= ~APPL_FLAG_OLD_LI_SPEC;
12293         if (api_parse (&li_parms[1].info[1], li_parms[1].length, "s", li_req_parms))
12294         {
12295           dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12296             UnMapId (Id), (char   *)(FILE_), __LINE__));
12297           Info = _WRONG_MESSAGE_FORMAT;
12298           break;
12299         }
12300         Info = li_check_main_plci (Id, plci);
12301         result_buffer[0] = 7;
12302         result_buffer[3] = 4;
12303         PUT_WORD (&result_buffer[4], Info);
12304         result_buffer[6] = 0;
12305         if (Info != GOOD)
12306           break;
12307         result = plci->saved_msg.info;
12308         for (i = 0; i <= result_buffer[0]; i++)
12309           result[i] = result_buffer[i];
12310         plci_b_write_pos = plci->li_plci_b_write_pos;
12311         participant_parms_pos = 0;
12312         result_pos = 7;
12313         while (participant_parms_pos < li_req_parms[0].length)
12314         {
12315           result[result_pos] = 6;
12316           result_pos += 7;
12317           PUT_DWORD (&result[result_pos - 6], 0);
12318           PUT_WORD (&result[result_pos - 2], GOOD);
12319           if (api_parse (&li_req_parms[0].info[1 + participant_parms_pos],
12320             (word)(li_parms[1].length - participant_parms_pos), "s", li_participant_struct))
12321           {
12322             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12323               UnMapId (Id), (char   *)(FILE_), __LINE__));
12324             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12325             break;
12326           }
12327           if (api_parse (&li_participant_struct[0].info[1],
12328             li_participant_struct[0].length, "d", li_participant_parms))
12329           {
12330             dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12331               UnMapId (Id), (char   *)(FILE_), __LINE__));
12332             PUT_WORD (&result[result_pos - 2], _WRONG_MESSAGE_FORMAT);
12333             break;
12334           }
12335           plci_b_id = GET_DWORD (li_participant_parms[0].info) & 0xffff;
12336           PUT_DWORD (&result[result_pos - 6], plci_b_id);
12337           if (sizeof(result) - result_pos < 7)
12338           {
12339             dbug (1, dprintf ("[%06lx] %s,%d: LI result overrun",
12340               UnMapId (Id), (char   *)(FILE_), __LINE__));
12341             PUT_WORD (&result[result_pos - 2], _WRONG_STATE);
12342             break;
12343           }
12344           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
12345           if (plci_b != NULL)
12346           {
12347             li2_update_connect (Id, a, plci, plci_b_id, false, 0);
12348             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12349             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12350           }
12351           participant_parms_pos = (word)((&li_participant_struct[0].info[1 + li_participant_struct[0].length]) -
12352             (&li_req_parms[0].info[1]));
12353         }
12354         result[0] = (byte)(result_pos - 1);
12355         result[3] = (byte)(result_pos - 4);
12356         result[6] = (byte)(result_pos - 7);
12357         i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12358         if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12359          || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12360         {
12361           plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12362           plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12363         }
12364         else
12365           plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12366         plci->li_plci_b_write_pos = plci_b_write_pos;
12367       }
12368       mixer_calculate_coefs (a);
12369       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12370       mixer_notify_update (plci, true);
12371       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12372         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12373       plci->command = 0;
12374       plci->li_cmd = GET_WORD (li_parms[0].info);
12375       start_internal_command (Id, plci, mixer_command);
12376       return (false);
12377
12378     case LI_REQ_SILENT_UPDATE:
12379       if (!plci || !plci->State
12380        || !plci->NL.Id || plci->nl_remove_id
12381        || (plci->li_bchannel_id == 0)
12382        || (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci != plci))
12383       {
12384         dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12385           UnMapId (Id), (char   *)(FILE_), __LINE__));
12386         return (false);
12387       }
12388       plci_b_write_pos = plci->li_plci_b_write_pos;
12389       if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12390         LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 2)
12391       {
12392         dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12393           UnMapId (Id), (char   *)(FILE_), __LINE__));
12394         return (false);
12395       }
12396       i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
12397       if ((plci_b_write_pos == plci->li_plci_b_read_pos)
12398        || (plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG))
12399       {
12400         plci->li_plci_b_queue[plci_b_write_pos] = LI_PLCI_B_SKIP_FLAG | LI_PLCI_B_LAST_FLAG;
12401         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12402       }
12403       else
12404         plci->li_plci_b_queue[i] |= LI_PLCI_B_LAST_FLAG;
12405       plci->li_plci_b_write_pos = plci_b_write_pos;
12406       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
12407       plci->command = 0;
12408       plci->li_cmd = GET_WORD (li_parms[0].info);
12409       start_internal_command (Id, plci, mixer_command);
12410       return (false);
12411
12412     default:
12413       dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
12414         UnMapId (Id), (char   *)(FILE_), __LINE__, GET_WORD (li_parms[0].info)));
12415       Info = _FACILITY_NOT_SUPPORTED;
12416     }
12417   }
12418   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12419     "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
12420   return (false);
12421 }
12422
12423
12424 static void mixer_indication_coefs_set (dword Id, PLCI   *plci)
12425 {
12426   dword d;
12427   DIVA_CAPI_ADAPTER   *a;
12428     byte result[12];
12429
12430   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
12431     UnMapId (Id), (char   *)(FILE_), __LINE__));
12432
12433   a = plci->adapter;
12434   if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
12435   {
12436     do
12437     {
12438       d = plci->li_plci_b_queue[plci->li_plci_b_read_pos];
12439       if (!(d & LI_PLCI_B_SKIP_FLAG))
12440       {
12441         if (plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12442         {
12443           if (d & LI_PLCI_B_DISC_FLAG)
12444           {
12445             result[0] = 5;
12446             PUT_WORD (&result[1], LI_IND_DISCONNECT);
12447             result[3] = 2;
12448             PUT_WORD (&result[4], _LI_USER_INITIATED);
12449           }
12450           else
12451           {
12452             result[0] = 7;
12453             PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12454             result[3] = 4;
12455             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12456           }
12457         }
12458         else
12459         {
12460           if (d & LI_PLCI_B_DISC_FLAG)
12461           {
12462             result[0] = 9;
12463             PUT_WORD (&result[1], LI_IND_DISCONNECT);
12464             result[3] = 6;
12465             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12466             PUT_WORD (&result[8], _LI_USER_INITIATED);
12467           }
12468           else
12469           {
12470             result[0] = 7;
12471             PUT_WORD (&result[1], LI_IND_CONNECT_ACTIVE);
12472             result[3] = 4;
12473             PUT_DWORD (&result[4], d & ~LI_PLCI_B_FLAG_MASK);
12474           }
12475         }
12476         sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0,
12477           "ws", SELECTOR_LINE_INTERCONNECT, result);
12478       }
12479       plci->li_plci_b_read_pos = (plci->li_plci_b_read_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ?
12480         0 : plci->li_plci_b_read_pos + 1;
12481     } while (!(d & LI_PLCI_B_LAST_FLAG) && (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos));
12482   }
12483 }
12484
12485
12486 static void mixer_indication_xconnect_from (dword Id, PLCI   *plci, byte   *msg, word length)
12487 {
12488   word i, j, ch;
12489   struct xconnect_transfer_address_s s,   *p;
12490   DIVA_CAPI_ADAPTER   *a;
12491
12492   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_from %d",
12493     UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12494
12495   a = plci->adapter;
12496   i = 1;
12497   for (i = 1; i < length; i += 16)
12498   {
12499     s.card_address.low = msg[i] | (msg[i+1] << 8) | (((dword)(msg[i+2])) << 16) | (((dword)(msg[i+3])) << 24);
12500     s.card_address.high = msg[i+4] | (msg[i+5] << 8) | (((dword)(msg[i+6])) << 16) | (((dword)(msg[i+7])) << 24);
12501     s.offset = msg[i+8] | (msg[i+9] << 8) | (((dword)(msg[i+10])) << 16) | (((dword)(msg[i+11])) << 24);
12502     ch = msg[i+12] | (msg[i+13] << 8);
12503     j = ch & XCONNECT_CHANNEL_NUMBER_MASK;
12504     if (!a->li_pri && (plci->li_bchannel_id == 2))
12505       j = 1 - j;
12506     j += a->li_base;
12507     if (ch & XCONNECT_CHANNEL_PORT_PC)
12508       p = &(li_config_table[j].send_pc);
12509     else
12510       p = &(li_config_table[j].send_b);
12511     p->card_address.low = s.card_address.low;
12512     p->card_address.high = s.card_address.high;
12513     p->offset = s.offset;
12514     li_config_table[j].channel |= LI_CHANNEL_ADDRESSES_SET;
12515   }
12516   if (plci->internal_command_queue[0]
12517    && ((plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_2)
12518     || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_3)
12519     || (plci->adjust_b_state == ADJUST_B_RESTORE_MIXER_4)))
12520   {
12521     (*(plci->internal_command_queue[0]))(Id, plci, 0);
12522     if (!plci->internal_command)
12523       next_internal_command (Id, plci);
12524   }
12525   mixer_notify_update (plci, true);
12526 }
12527
12528
12529 static void mixer_indication_xconnect_to (dword Id, PLCI   *plci, byte   *msg, word length)
12530 {
12531
12532   dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_xconnect_to %d",
12533     UnMapId (Id), (char   *)(FILE_), __LINE__, (int) length));
12534
12535 }
12536
12537
12538 static byte mixer_notify_source_removed (PLCI   *plci, dword plci_b_id)
12539 {
12540   word plci_b_write_pos;
12541
12542   plci_b_write_pos = plci->li_plci_b_write_pos;
12543   if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
12544     LI_PLCI_B_QUEUE_ENTRIES + plci->li_plci_b_read_pos) - plci_b_write_pos - 1 < 1)
12545   {
12546     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
12547       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12548       (char   *)(FILE_), __LINE__));
12549     return (false);
12550   }
12551   plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
12552   plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
12553   plci->li_plci_b_write_pos = plci_b_write_pos;
12554   return (true);
12555 }
12556
12557
12558 static void mixer_remove (PLCI   *plci)
12559 {
12560   DIVA_CAPI_ADAPTER   *a;
12561   PLCI   *notify_plci;
12562   dword plci_b_id;
12563   word i, j;
12564
12565   dbug (1, dprintf ("[%06lx] %s,%d: mixer_remove",
12566     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12567     (char   *)(FILE_), __LINE__));
12568
12569   a = plci->adapter;
12570   plci_b_id = (plci->Id << 8) | UnMapController (plci->adapter->Id);
12571   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
12572   {
12573     if ((plci->li_bchannel_id != 0)
12574      && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
12575     {
12576       i = a->li_base + (plci->li_bchannel_id - 1);
12577       if ((li_config_table[i].curchnl | li_config_table[i].channel) & LI_CHANNEL_INVOLVED)
12578       {
12579         for (j = 0; j < li_total_channels; j++)
12580         {
12581           if ((li_config_table[i].flag_table[j] & LI_FLAG_INTERCONNECT)
12582            || (li_config_table[j].flag_table[i] & LI_FLAG_INTERCONNECT))
12583           {
12584             notify_plci = li_config_table[j].plci;
12585             if ((notify_plci != NULL)
12586              && (notify_plci != plci)
12587              && (notify_plci->appl != NULL)
12588              && !(notify_plci->appl->appl_flags & APPL_FLAG_OLD_LI_SPEC)
12589              && (notify_plci->State)
12590              && notify_plci->NL.Id && !notify_plci->nl_remove_id)
12591             {
12592               mixer_notify_source_removed (notify_plci, plci_b_id);
12593             }
12594           }
12595         }
12596         mixer_clear_config (plci);
12597         mixer_calculate_coefs (a);
12598         mixer_notify_update (plci, true);
12599       }
12600       li_config_table[i].plci = NULL;
12601       plci->li_bchannel_id = 0;
12602     }
12603   }
12604 }
12605
12606
12607 /*------------------------------------------------------------------*/
12608 /* Echo canceller facilities                                        */
12609 /*------------------------------------------------------------------*/
12610
12611
12612 static void ec_write_parameters (PLCI   *plci)
12613 {
12614   word w;
12615     byte parameter_buffer[6];
12616
12617   dbug (1, dprintf ("[%06lx] %s,%d: ec_write_parameters",
12618     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12619     (char   *)(FILE_), __LINE__));
12620
12621   parameter_buffer[0] = 5;
12622   parameter_buffer[1] = DSP_CTRL_SET_LEC_PARAMETERS;
12623   PUT_WORD (&parameter_buffer[2], plci->ec_idi_options);
12624   plci->ec_idi_options &= ~LEC_RESET_COEFFICIENTS;
12625   w = (plci->ec_tail_length == 0) ? 128 : plci->ec_tail_length;
12626   PUT_WORD (&parameter_buffer[4], w);
12627   add_p (plci, FTY, parameter_buffer);
12628   sig_req (plci, TEL_CTRL, 0);
12629   send_req (plci);
12630 }
12631
12632
12633 static void ec_clear_config (PLCI   *plci)
12634 {
12635
12636   dbug (1, dprintf ("[%06lx] %s,%d: ec_clear_config",
12637     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
12638     (char   *)(FILE_), __LINE__));
12639
12640   plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12641     LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING;
12642   plci->ec_tail_length = 0;
12643 }
12644
12645
12646 static void ec_prepare_switch (dword Id, PLCI   *plci)
12647 {
12648
12649   dbug (1, dprintf ("[%06lx] %s,%d: ec_prepare_switch",
12650     UnMapId (Id), (char   *)(FILE_), __LINE__));
12651
12652 }
12653
12654
12655 static word ec_save_config (dword Id, PLCI   *plci, byte Rc)
12656 {
12657
12658   dbug (1, dprintf ("[%06lx] %s,%d: ec_save_config %02x %d",
12659     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12660
12661   return (GOOD);
12662 }
12663
12664
12665 static word ec_restore_config (dword Id, PLCI   *plci, byte Rc)
12666 {
12667   word Info;
12668
12669   dbug (1, dprintf ("[%06lx] %s,%d: ec_restore_config %02x %d",
12670     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
12671
12672   Info = GOOD;
12673   if (plci->B1_facilities & B1_FACILITY_EC)
12674   {
12675     switch (plci->adjust_b_state)
12676     {
12677     case ADJUST_B_RESTORE_EC_1:
12678       plci->internal_command = plci->adjust_b_command;
12679       if (plci->sig_req)
12680       {
12681         plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
12682         break;
12683       }
12684       ec_write_parameters (plci);
12685       plci->adjust_b_state = ADJUST_B_RESTORE_EC_2;
12686       break;
12687     case ADJUST_B_RESTORE_EC_2:
12688       if ((Rc != OK) && (Rc != OK_FC))
12689       {
12690         dbug (1, dprintf ("[%06lx] %s,%d: Restore EC failed %02x",
12691           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12692         Info = _WRONG_STATE;
12693         break;
12694       }
12695       break;
12696     }
12697   }
12698   return (Info);
12699 }
12700
12701
12702 static void ec_command (dword Id, PLCI   *plci, byte Rc)
12703 {
12704   word internal_command, Info;
12705     byte result[8];
12706
12707   dbug (1, dprintf ("[%06lx] %s,%d: ec_command %02x %04x %04x %04x %d",
12708     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command,
12709     plci->ec_cmd, plci->ec_idi_options, plci->ec_tail_length));
12710
12711   Info = GOOD;
12712   if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12713   {
12714     result[0] = 2;
12715     PUT_WORD (&result[1], EC_SUCCESS);
12716   }
12717   else
12718   {
12719     result[0] = 5;
12720     PUT_WORD (&result[1], plci->ec_cmd);
12721     result[3] = 2;
12722     PUT_WORD (&result[4], GOOD);
12723   }
12724   internal_command = plci->internal_command;
12725   plci->internal_command = 0;
12726   switch (plci->ec_cmd)
12727   {
12728   case EC_ENABLE_OPERATION:
12729   case EC_FREEZE_COEFFICIENTS:
12730   case EC_RESUME_COEFFICIENT_UPDATE:
12731   case EC_RESET_COEFFICIENTS:
12732     switch (internal_command)
12733     {
12734     default:
12735       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities |
12736         B1_FACILITY_EC), EC_COMMAND_1);
12737     case EC_COMMAND_1:
12738       if (adjust_b_process (Id, plci, Rc) != GOOD)
12739       {
12740         dbug (1, dprintf ("[%06lx] %s,%d: Load EC failed",
12741           UnMapId (Id), (char   *)(FILE_), __LINE__));
12742         Info = _FACILITY_NOT_SUPPORTED;
12743         break;
12744       }
12745       if (plci->internal_command)
12746         return;
12747     case EC_COMMAND_2:
12748       if (plci->sig_req)
12749       {
12750         plci->internal_command = EC_COMMAND_2;
12751         return;
12752       }
12753       plci->internal_command = EC_COMMAND_3;
12754       ec_write_parameters (plci);
12755       return;
12756     case EC_COMMAND_3:
12757       if ((Rc != OK) && (Rc != OK_FC))
12758       {
12759         dbug (1, dprintf ("[%06lx] %s,%d: Enable EC failed %02x",
12760           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12761         Info = _FACILITY_NOT_SUPPORTED;
12762         break;
12763       }
12764       break;
12765     }
12766     break;
12767
12768   case EC_DISABLE_OPERATION:
12769     switch (internal_command)
12770     {
12771     default:
12772     case EC_COMMAND_1:
12773       if (plci->B1_facilities & B1_FACILITY_EC)
12774       {
12775         if (plci->sig_req)
12776         {
12777           plci->internal_command = EC_COMMAND_1;
12778           return;
12779         }
12780         plci->internal_command = EC_COMMAND_2;
12781         ec_write_parameters (plci);
12782         return;
12783       }
12784       Rc = OK;
12785     case EC_COMMAND_2:
12786       if ((Rc != OK) && (Rc != OK_FC))
12787       {
12788         dbug (1, dprintf ("[%06lx] %s,%d: Disable EC failed %02x",
12789           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
12790         Info = _FACILITY_NOT_SUPPORTED;
12791         break;
12792       }
12793       adjust_b1_resource (Id, plci, NULL, (word)(plci->B1_facilities &
12794         ~B1_FACILITY_EC), EC_COMMAND_3);
12795     case EC_COMMAND_3:
12796       if (adjust_b_process (Id, plci, Rc) != GOOD)
12797       {
12798         dbug (1, dprintf ("[%06lx] %s,%d: Unload EC failed",
12799           UnMapId (Id), (char   *)(FILE_), __LINE__));
12800         Info = _FACILITY_NOT_SUPPORTED;
12801         break;
12802       }
12803       if (plci->internal_command)
12804         return;
12805       break;
12806     }
12807     break;
12808   }
12809   sendf (plci->appl, _FACILITY_R | CONFIRM, Id & 0xffffL, plci->number,
12810     "wws", Info, (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
12811     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
12812 }
12813
12814
12815 static byte ec_request (dword Id, word Number, DIVA_CAPI_ADAPTER   *a, PLCI   *plci, APPL   *appl, API_PARSE *msg)
12816 {
12817   word Info;
12818   word opt;
12819     API_PARSE ec_parms[3];
12820     byte result[16];
12821
12822   dbug (1, dprintf ("[%06lx] %s,%d: ec_request",
12823     UnMapId (Id), (char   *)(FILE_), __LINE__));
12824
12825   Info = GOOD;
12826   result[0] = 0;
12827   if (!(a->man_profile.private_options & (1L << PRIVATE_ECHO_CANCELLER)))
12828   {
12829     dbug (1, dprintf ("[%06lx] %s,%d: Facility not supported",
12830       UnMapId (Id), (char   *)(FILE_), __LINE__));
12831     Info = _FACILITY_NOT_SUPPORTED;
12832   }
12833   else
12834   {
12835     if (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
12836     {
12837       if (api_parse (&msg[1].info[1], msg[1].length, "w", ec_parms))
12838       {
12839         dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12840           UnMapId (Id), (char   *)(FILE_), __LINE__));
12841         Info = _WRONG_MESSAGE_FORMAT;
12842       }
12843       else
12844       {
12845         if (plci == NULL)
12846         {
12847           dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12848             UnMapId (Id), (char   *)(FILE_), __LINE__));
12849           Info = _WRONG_IDENTIFIER;
12850         }
12851         else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12852         {
12853           dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12854             UnMapId (Id), (char   *)(FILE_), __LINE__));
12855           Info = _WRONG_STATE;
12856         }
12857         else
12858         {
12859           plci->command = 0;
12860           plci->ec_cmd = GET_WORD (ec_parms[0].info);
12861           plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12862           result[0] = 2;
12863           PUT_WORD (&result[1], EC_SUCCESS);
12864           if (msg[1].length >= 4)
12865           {
12866             opt = GET_WORD (&ec_parms[0].info[2]);
12867             plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12868               LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12869             if (!(opt & EC_DISABLE_NON_LINEAR_PROCESSING))
12870               plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12871             if (opt & EC_DETECT_DISABLE_TONE)
12872               plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12873             if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12874               plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12875             if (msg[1].length >= 6)
12876             {
12877               plci->ec_tail_length = GET_WORD (&ec_parms[0].info[4]);
12878             }
12879           }
12880           switch (plci->ec_cmd)
12881           {
12882           case EC_ENABLE_OPERATION:
12883             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12884             start_internal_command (Id, plci, ec_command);
12885             return (false);
12886
12887           case EC_DISABLE_OPERATION:
12888             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12889               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12890               LEC_RESET_COEFFICIENTS;
12891             start_internal_command (Id, plci, ec_command);
12892             return (false);
12893
12894           case EC_FREEZE_COEFFICIENTS:
12895             plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
12896             start_internal_command (Id, plci, ec_command);
12897             return (false);
12898
12899           case EC_RESUME_COEFFICIENT_UPDATE:
12900             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12901             start_internal_command (Id, plci, ec_command);
12902             return (false);
12903
12904           case EC_RESET_COEFFICIENTS:
12905             plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
12906             start_internal_command (Id, plci, ec_command);
12907             return (false);
12908
12909           default:
12910             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12911               UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
12912             PUT_WORD (&result[1], EC_UNSUPPORTED_OPERATION);
12913           }
12914         }
12915       }
12916     }
12917     else
12918     {
12919       if (api_parse (&msg[1].info[1], msg[1].length, "ws", ec_parms))
12920       {
12921         dbug (1, dprintf ("[%06lx] %s,%d: Wrong message format",
12922           UnMapId (Id), (char   *)(FILE_), __LINE__));
12923         Info = _WRONG_MESSAGE_FORMAT;
12924       }
12925       else
12926       {
12927         if (GET_WORD (ec_parms[0].info) == EC_GET_SUPPORTED_SERVICES)
12928         {
12929           result[0] = 11;
12930           PUT_WORD (&result[1], EC_GET_SUPPORTED_SERVICES);
12931           result[3] = 8;
12932           PUT_WORD (&result[4], GOOD);
12933           PUT_WORD (&result[6], 0x0007);
12934           PUT_WORD (&result[8], LEC_MAX_SUPPORTED_TAIL_LENGTH);
12935           PUT_WORD (&result[10], 0);
12936         }
12937         else if (plci == NULL)
12938         {
12939           dbug (1, dprintf ("[%06lx] %s,%d: Wrong PLCI",
12940             UnMapId (Id), (char   *)(FILE_), __LINE__));
12941           Info = _WRONG_IDENTIFIER;
12942         }
12943         else if (!plci->State || !plci->NL.Id || plci->nl_remove_id)
12944         {
12945           dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
12946             UnMapId (Id), (char   *)(FILE_), __LINE__));
12947           Info = _WRONG_STATE;
12948         }
12949         else
12950         {
12951           plci->command = 0;
12952           plci->ec_cmd = GET_WORD (ec_parms[0].info);
12953           plci->ec_idi_options &= ~(LEC_MANUAL_DISABLE | LEC_RESET_COEFFICIENTS);
12954           result[0] = 5;
12955           PUT_WORD (&result[1], plci->ec_cmd);
12956           result[3] = 2;
12957           PUT_WORD (&result[4], GOOD);
12958           plci->ec_idi_options &= ~(LEC_ENABLE_NONLINEAR_PROCESSING |
12959             LEC_ENABLE_2100HZ_DETECTOR | LEC_REQUIRE_2100HZ_REVERSALS);
12960           plci->ec_tail_length = 0;
12961           if (ec_parms[1].length >= 2)
12962           {
12963             opt = GET_WORD (&ec_parms[1].info[1]);
12964             if (opt & EC_ENABLE_NON_LINEAR_PROCESSING)
12965               plci->ec_idi_options |= LEC_ENABLE_NONLINEAR_PROCESSING;
12966             if (opt & EC_DETECT_DISABLE_TONE)
12967               plci->ec_idi_options |= LEC_ENABLE_2100HZ_DETECTOR;
12968             if (!(opt & EC_DO_NOT_REQUIRE_REVERSALS))
12969               plci->ec_idi_options |= LEC_REQUIRE_2100HZ_REVERSALS;
12970             if (ec_parms[1].length >= 4)
12971             {
12972               plci->ec_tail_length = GET_WORD (&ec_parms[1].info[3]);
12973             }
12974           }
12975           switch (plci->ec_cmd)
12976           {
12977           case EC_ENABLE_OPERATION:
12978             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
12979             start_internal_command (Id, plci, ec_command);
12980             return (false);
12981
12982           case EC_DISABLE_OPERATION:
12983             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
12984               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
12985               LEC_RESET_COEFFICIENTS;
12986             start_internal_command (Id, plci, ec_command);
12987             return (false);
12988
12989           default:
12990             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
12991               UnMapId (Id), (char   *)(FILE_), __LINE__, plci->ec_cmd));
12992             PUT_WORD (&result[4], _FACILITY_SPECIFIC_FUNCTION_NOT_SUPP);
12993           }
12994         }
12995       }
12996     }
12997   }
12998   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
12999     "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13000     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13001   return (false);
13002 }
13003
13004
13005 static void ec_indication (dword Id, PLCI   *plci, byte   *msg, word length)
13006 {
13007     byte result[8];
13008
13009   dbug (1, dprintf ("[%06lx] %s,%d: ec_indication",
13010     UnMapId (Id), (char   *)(FILE_), __LINE__));
13011
13012   if (!(plci->ec_idi_options & LEC_MANUAL_DISABLE))
13013   {
13014     if (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC)
13015     {
13016       result[0] = 2;
13017       PUT_WORD (&result[1], 0);
13018       switch (msg[1])
13019       {
13020       case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13021         PUT_WORD (&result[1], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13022         break;
13023       case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13024         PUT_WORD (&result[1], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13025         break;
13026       case LEC_DISABLE_RELEASED:
13027         PUT_WORD (&result[1], EC_BYPASS_RELEASED);
13028         break;
13029       }
13030     }
13031     else
13032     {
13033       result[0] = 5;
13034       PUT_WORD (&result[1], EC_BYPASS_INDICATION);
13035       result[3] = 2;
13036       PUT_WORD (&result[4], 0);
13037       switch (msg[1])
13038       {
13039       case LEC_DISABLE_TYPE_CONTIGNUOUS_2100HZ:
13040         PUT_WORD (&result[4], EC_BYPASS_DUE_TO_CONTINUOUS_2100HZ);
13041         break;
13042       case LEC_DISABLE_TYPE_REVERSED_2100HZ:
13043         PUT_WORD (&result[4], EC_BYPASS_DUE_TO_REVERSED_2100HZ);
13044         break;
13045       case LEC_DISABLE_RELEASED:
13046         PUT_WORD (&result[4], EC_BYPASS_RELEASED);
13047         break;
13048       }
13049     }
13050     sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", (plci->appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
13051       PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
13052   }
13053 }
13054
13055
13056
13057 /*------------------------------------------------------------------*/
13058 /* Advanced voice                                                   */
13059 /*------------------------------------------------------------------*/
13060
13061 static void adv_voice_write_coefs (PLCI   *plci, word write_command)
13062 {
13063   DIVA_CAPI_ADAPTER   *a;
13064   word i;
13065   byte *p;
13066
13067   word w, n, j, k;
13068   byte ch_map[MIXER_CHANNELS_BRI];
13069
13070     byte coef_buffer[ADV_VOICE_COEF_BUFFER_SIZE + 2];
13071
13072   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_write_coefs %d",
13073     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13074     (char   *)(FILE_), __LINE__, write_command));
13075
13076   a = plci->adapter;
13077   p = coef_buffer + 1;
13078   *(p++) = DSP_CTRL_OLD_SET_MIXER_COEFFICIENTS;
13079   i = 0;
13080   while (i + sizeof(word) <= a->adv_voice_coef_length)
13081   {
13082     PUT_WORD (p, GET_WORD (a->adv_voice_coef_buffer + i));
13083     p += 2;
13084     i += 2;
13085   }
13086   while (i < ADV_VOICE_OLD_COEF_COUNT * sizeof(word))
13087   {
13088     PUT_WORD (p, 0x8000);
13089     p += 2;
13090     i += 2;
13091   }
13092
13093   if (!a->li_pri && (plci->li_bchannel_id == 0))
13094   {
13095     if ((li_config_table[a->li_base].plci == NULL) && (li_config_table[a->li_base + 1].plci != NULL))
13096     {
13097       plci->li_bchannel_id = 1;
13098       li_config_table[a->li_base].plci = plci;
13099       dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13100         (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13101         (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13102     }
13103     else if ((li_config_table[a->li_base].plci != NULL) && (li_config_table[a->li_base + 1].plci == NULL))
13104     {
13105       plci->li_bchannel_id = 2;
13106       li_config_table[a->li_base + 1].plci = plci;
13107       dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_set_bchannel_id %d",
13108         (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13109         (char   *)(FILE_), __LINE__, plci->li_bchannel_id));
13110     }
13111   }
13112   if (!a->li_pri && (plci->li_bchannel_id != 0)
13113    && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13114   {
13115     i = a->li_base + (plci->li_bchannel_id - 1);
13116     switch (write_command)
13117     {
13118     case ADV_VOICE_WRITE_ACTIVATION:
13119       j = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13120       k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13121       if (!(plci->B1_facilities & B1_FACILITY_MIXER))
13122       {
13123         li_config_table[j].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13124         li_config_table[i].flag_table[j] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13125       }
13126       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13127       {
13128         li_config_table[k].flag_table[i] |= LI_FLAG_CONFERENCE | LI_FLAG_MIX;
13129         li_config_table[i].flag_table[k] |= LI_FLAG_CONFERENCE | LI_FLAG_MONITOR;
13130         li_config_table[k].flag_table[j] |= LI_FLAG_CONFERENCE;
13131         li_config_table[j].flag_table[k] |= LI_FLAG_CONFERENCE;
13132       }
13133       mixer_calculate_coefs (a);
13134       li_config_table[i].curchnl = li_config_table[i].channel;
13135       li_config_table[j].curchnl = li_config_table[j].channel;
13136       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13137         li_config_table[k].curchnl = li_config_table[k].channel;
13138       break;
13139
13140     case ADV_VOICE_WRITE_DEACTIVATION:
13141       for (j = 0; j < li_total_channels; j++)
13142       {
13143         li_config_table[i].flag_table[j] = 0;
13144         li_config_table[j].flag_table[i] = 0;
13145       }
13146       k = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13147       for (j = 0; j < li_total_channels; j++)
13148       {
13149         li_config_table[k].flag_table[j] = 0;
13150         li_config_table[j].flag_table[k] = 0;
13151       }
13152       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13153       {
13154         k = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13155         for (j = 0; j < li_total_channels; j++)
13156         {
13157           li_config_table[k].flag_table[j] = 0;
13158           li_config_table[j].flag_table[k] = 0;
13159         }
13160       }
13161       mixer_calculate_coefs (a);
13162       break;
13163     }
13164     if (plci->B1_facilities & B1_FACILITY_MIXER)
13165     {
13166       w = 0;
13167       if (ADV_VOICE_NEW_COEF_BASE + sizeof(word) <= a->adv_voice_coef_length)
13168         w = GET_WORD (a->adv_voice_coef_buffer + ADV_VOICE_NEW_COEF_BASE);
13169       if (li_config_table[i].channel & LI_CHANNEL_TX_DATA)
13170         w |= MIXER_FEATURE_ENABLE_TX_DATA;
13171       if (li_config_table[i].channel & LI_CHANNEL_RX_DATA)
13172         w |= MIXER_FEATURE_ENABLE_RX_DATA;
13173       *(p++) = (byte) w;
13174       *(p++) = (byte)(w >> 8);
13175       for (j = 0; j < sizeof(ch_map); j += 2)
13176       {
13177         ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
13178         ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
13179       }
13180       for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
13181       {
13182         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
13183         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
13184         if (li_config_table[i].channel & li_config_table[j].channel & LI_CHANNEL_INVOLVED)
13185         {
13186           *(p++) = ((li_config_table[i].coef_table[j] & mixer_write_prog_bri[n].mask) ? 0x80 : 0x01);
13187           w = ((li_config_table[i].coef_table[j] & 0xf) ^ (li_config_table[i].coef_table[j] >> 4));
13188           li_config_table[i].coef_table[j] ^= (w & mixer_write_prog_bri[n].mask) << 4;
13189         }
13190         else
13191         {
13192           *(p++) = (ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n < a->adv_voice_coef_length) ?
13193             a->adv_voice_coef_buffer[ADV_VOICE_NEW_COEF_BASE + sizeof(word) + n] : 0x00;
13194         }
13195       }
13196     }
13197     else
13198     {
13199       for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13200         *(p++) = a->adv_voice_coef_buffer[i];
13201     }
13202   }
13203   else
13204
13205   {
13206     for (i = ADV_VOICE_NEW_COEF_BASE; i < a->adv_voice_coef_length; i++)
13207       *(p++) = a->adv_voice_coef_buffer[i];
13208   }
13209   coef_buffer[0] = (p - coef_buffer) - 1;
13210   add_p (plci, FTY, coef_buffer);
13211   sig_req (plci, TEL_CTRL, 0);
13212   send_req (plci);
13213 }
13214
13215
13216 static void adv_voice_clear_config (PLCI   *plci)
13217 {
13218   DIVA_CAPI_ADAPTER   *a;
13219
13220   word i, j;
13221
13222
13223   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_clear_config",
13224     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13225     (char   *)(FILE_), __LINE__));
13226
13227   a = plci->adapter;
13228   if ((plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13229   {
13230     a->adv_voice_coef_length = 0;
13231
13232     if (!a->li_pri && (plci->li_bchannel_id != 0)
13233      && (li_config_table[a->li_base + (plci->li_bchannel_id - 1)].plci == plci))
13234     {
13235       i = a->li_base + (plci->li_bchannel_id - 1);
13236       li_config_table[i].curchnl = 0;
13237       li_config_table[i].channel = 0;
13238       li_config_table[i].chflags = 0;
13239       for (j = 0; j < li_total_channels; j++)
13240       {
13241         li_config_table[i].flag_table[j] = 0;
13242         li_config_table[j].flag_table[i] = 0;
13243         li_config_table[i].coef_table[j] = 0;
13244         li_config_table[j].coef_table[i] = 0;
13245       }
13246       li_config_table[i].coef_table[i] |= LI_COEF_CH_PC_SET | LI_COEF_PC_CH_SET;
13247       i = a->li_base + MIXER_IC_CHANNEL_BASE + (plci->li_bchannel_id - 1);
13248       li_config_table[i].curchnl = 0;
13249       li_config_table[i].channel = 0;
13250       li_config_table[i].chflags = 0;
13251       for (j = 0; j < li_total_channels; j++)
13252       {
13253         li_config_table[i].flag_table[j] = 0;
13254         li_config_table[j].flag_table[i] = 0;
13255         li_config_table[i].coef_table[j] = 0;
13256         li_config_table[j].coef_table[i] = 0;
13257       }
13258       if (a->manufacturer_features & MANUFACTURER_FEATURE_SLAVE_CODEC)
13259       {
13260         i = a->li_base + MIXER_IC_CHANNEL_BASE + (2 - plci->li_bchannel_id);
13261         li_config_table[i].curchnl = 0;
13262         li_config_table[i].channel = 0;
13263         li_config_table[i].chflags = 0;
13264         for (j = 0; j < li_total_channels; j++)
13265         {
13266           li_config_table[i].flag_table[j] = 0;
13267           li_config_table[j].flag_table[i] = 0;
13268           li_config_table[i].coef_table[j] = 0;
13269           li_config_table[j].coef_table[i] = 0;
13270         }
13271       }
13272     }
13273
13274   }
13275 }
13276
13277
13278 static void adv_voice_prepare_switch (dword Id, PLCI   *plci)
13279 {
13280
13281   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_prepare_switch",
13282     UnMapId (Id), (char   *)(FILE_), __LINE__));
13283
13284 }
13285
13286
13287 static word adv_voice_save_config (dword Id, PLCI   *plci, byte Rc)
13288 {
13289
13290   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_save_config %02x %d",
13291     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13292
13293   return (GOOD);
13294 }
13295
13296
13297 static word adv_voice_restore_config (dword Id, PLCI   *plci, byte Rc)
13298 {
13299   DIVA_CAPI_ADAPTER   *a;
13300   word Info;
13301
13302   dbug (1, dprintf ("[%06lx] %s,%d: adv_voice_restore_config %02x %d",
13303     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13304
13305   Info = GOOD;
13306   a = plci->adapter;
13307   if ((plci->B1_facilities & B1_FACILITY_VOICE)
13308    && (plci->tel == ADV_VOICE) && (plci == a->AdvSignalPLCI))
13309   {
13310     switch (plci->adjust_b_state)
13311     {
13312     case ADJUST_B_RESTORE_VOICE_1:
13313       plci->internal_command = plci->adjust_b_command;
13314       if (plci->sig_req)
13315       {
13316         plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13317         break;
13318       }
13319       adv_voice_write_coefs (plci, ADV_VOICE_WRITE_UPDATE);
13320       plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_2;
13321       break;
13322     case ADJUST_B_RESTORE_VOICE_2:
13323       if ((Rc != OK) && (Rc != OK_FC))
13324       {
13325         dbug (1, dprintf ("[%06lx] %s,%d: Restore voice config failed %02x",
13326           UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13327         Info = _WRONG_STATE;
13328         break;
13329       }
13330       break;
13331     }
13332   }
13333   return (Info);
13334 }
13335
13336
13337
13338
13339 /*------------------------------------------------------------------*/
13340 /* B1 resource switching                                            */
13341 /*------------------------------------------------------------------*/
13342
13343 static byte b1_facilities_table[] =
13344 {
13345   0x00,  /* 0  No bchannel resources      */
13346   0x00,  /* 1  Codec (automatic law)      */
13347   0x00,  /* 2  Codec (A-law)              */
13348   0x00,  /* 3  Codec (y-law)              */
13349   0x00,  /* 4  HDLC for X.21              */
13350   0x00,  /* 5  HDLC                       */
13351   0x00,  /* 6  External Device 0          */
13352   0x00,  /* 7  External Device 1          */
13353   0x00,  /* 8  HDLC 56k                   */
13354   0x00,  /* 9  Transparent                */
13355   0x00,  /* 10 Loopback to network        */
13356   0x00,  /* 11 Test pattern to net        */
13357   0x00,  /* 12 Rate adaptation sync       */
13358   0x00,  /* 13 Rate adaptation async      */
13359   0x00,  /* 14 R-Interface                */
13360   0x00,  /* 15 HDLC 128k leased line      */
13361   0x00,  /* 16 FAX                        */
13362   0x00,  /* 17 Modem async                */
13363   0x00,  /* 18 Modem sync HDLC            */
13364   0x00,  /* 19 V.110 async HDLC           */
13365   0x12,  /* 20 Adv voice (Trans,mixer)    */
13366   0x00,  /* 21 Codec connected to IC      */
13367   0x0c,  /* 22 Trans,DTMF                 */
13368   0x1e,  /* 23 Trans,DTMF+mixer           */
13369   0x1f,  /* 24 Trans,DTMF+mixer+local     */
13370   0x13,  /* 25 Trans,mixer+local          */
13371   0x12,  /* 26 HDLC,mixer                 */
13372   0x12,  /* 27 HDLC 56k,mixer             */
13373   0x2c,  /* 28 Trans,LEC+DTMF             */
13374   0x3e,  /* 29 Trans,LEC+DTMF+mixer       */
13375   0x3f,  /* 30 Trans,LEC+DTMF+mixer+local */
13376   0x2c,  /* 31 RTP,LEC+DTMF               */
13377   0x3e,  /* 32 RTP,LEC+DTMF+mixer         */
13378   0x3f,  /* 33 RTP,LEC+DTMF+mixer+local   */
13379   0x00,  /* 34 Signaling task             */
13380   0x00,  /* 35 PIAFS                      */
13381   0x0c,  /* 36 Trans,DTMF+TONE            */
13382   0x1e,  /* 37 Trans,DTMF+TONE+mixer      */
13383   0x1f   /* 38 Trans,DTMF+TONE+mixer+local*/
13384 };
13385
13386
13387 static word get_b1_facilities (PLCI   * plci, byte b1_resource)
13388 {
13389   word b1_facilities;
13390
13391   b1_facilities = b1_facilities_table[b1_resource];
13392   if ((b1_resource == 9) || (b1_resource == 20) || (b1_resource == 25))
13393   {
13394
13395     if (!(((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13396        || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13397
13398     {
13399       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND)
13400         b1_facilities |= B1_FACILITY_DTMFX;
13401       if (plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)
13402         b1_facilities |= B1_FACILITY_DTMFR;
13403     }
13404   }
13405   if ((b1_resource == 17) || (b1_resource == 18))
13406   {
13407     if (plci->adapter->manufacturer_features & (MANUFACTURER_FEATURE_V18 | MANUFACTURER_FEATURE_VOWN))
13408       b1_facilities |= B1_FACILITY_DTMFX | B1_FACILITY_DTMFR;
13409   }
13410 /*
13411   dbug (1, dprintf ("[%06lx] %s,%d: get_b1_facilities %d %04x",
13412     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13413     (char far *)(FILE_), __LINE__, b1_resource, b1_facilites));
13414 */
13415   return (b1_facilities);
13416 }
13417
13418
13419 static byte add_b1_facilities (PLCI   * plci, byte b1_resource, word b1_facilities)
13420 {
13421   byte b;
13422
13423   switch (b1_resource)
13424   {
13425   case 5:
13426   case 26:
13427     if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13428       b = 26;
13429     else
13430       b = 5;
13431     break;
13432
13433   case 8:
13434   case 27:
13435     if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13436       b = 27;
13437     else
13438       b = 8;
13439     break;
13440
13441   case 9:
13442   case 20:
13443   case 22:
13444   case 23:
13445   case 24:
13446   case 25:
13447   case 28:
13448   case 29:
13449   case 30:
13450   case 36:
13451   case 37:
13452   case 38:
13453     if (b1_facilities & B1_FACILITY_EC)
13454     {
13455       if (b1_facilities & B1_FACILITY_LOCAL)
13456         b = 30;
13457       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13458         b = 29;
13459       else
13460         b = 28;
13461     }
13462
13463     else if ((b1_facilities & (B1_FACILITY_DTMFX | B1_FACILITY_DTMFR | B1_FACILITY_MIXER))
13464       && (((plci->requested_options_conn | plci->requested_options) & (1L << PRIVATE_DTMF_TONE))
13465        || (plci->appl && (plci->adapter->requested_options_table[plci->appl->Id-1] & (1L << PRIVATE_DTMF_TONE)))))
13466     {
13467       if (b1_facilities & B1_FACILITY_LOCAL)
13468         b = 38;
13469       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13470         b = 37;
13471       else
13472         b = 36;
13473     }
13474
13475     else if (((plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_HARDDTMF)
13476       && !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
13477      || ((b1_facilities & B1_FACILITY_DTMFR)
13478       && ((b1_facilities & B1_FACILITY_MIXER)
13479        || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE)))
13480      || ((b1_facilities & B1_FACILITY_DTMFX)
13481       && ((b1_facilities & B1_FACILITY_MIXER)
13482        || !(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_SOFTDTMF_SEND))))
13483     {
13484       if (b1_facilities & B1_FACILITY_LOCAL)
13485         b = 24;
13486       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13487         b = 23;
13488       else
13489         b = 22;
13490     }
13491     else
13492     {
13493       if (b1_facilities & B1_FACILITY_LOCAL)
13494         b = 25;
13495       else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13496         b = 20;
13497       else
13498         b = 9;
13499     }
13500     break;
13501
13502   case 31:
13503   case 32:
13504   case 33:
13505     if (b1_facilities & B1_FACILITY_LOCAL)
13506       b = 33;
13507     else if (b1_facilities & (B1_FACILITY_MIXER | B1_FACILITY_VOICE))
13508       b = 32;
13509     else
13510       b = 31;
13511     break;
13512
13513   default:
13514     b = b1_resource;
13515   }
13516   dbug (1, dprintf ("[%06lx] %s,%d: add_b1_facilities %d %04x %d %04x",
13517     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13518     (char   *)(FILE_), __LINE__,
13519     b1_resource, b1_facilities, b, get_b1_facilities (plci, b)));
13520   return (b);
13521 }
13522
13523
13524 static void adjust_b1_facilities (PLCI   *plci, byte new_b1_resource, word new_b1_facilities)
13525 {
13526   word removed_facilities;
13527
13528   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_facilities %d %04x %04x",
13529     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13530     (char   *)(FILE_), __LINE__, new_b1_resource, new_b1_facilities,
13531     new_b1_facilities & get_b1_facilities (plci, new_b1_resource)));
13532
13533   new_b1_facilities &= get_b1_facilities (plci, new_b1_resource);
13534   removed_facilities = plci->B1_facilities & ~new_b1_facilities;
13535
13536   if (removed_facilities & B1_FACILITY_EC)
13537     ec_clear_config (plci);
13538
13539
13540   if (removed_facilities & B1_FACILITY_DTMFR)
13541   {
13542     dtmf_rec_clear_config (plci);
13543     dtmf_parameter_clear_config (plci);
13544   }
13545   if (removed_facilities & B1_FACILITY_DTMFX)
13546     dtmf_send_clear_config (plci);
13547
13548
13549   if (removed_facilities & B1_FACILITY_MIXER)
13550     mixer_clear_config (plci);
13551
13552   if (removed_facilities & B1_FACILITY_VOICE)
13553     adv_voice_clear_config (plci);
13554   plci->B1_facilities = new_b1_facilities;
13555 }
13556
13557
13558 static void adjust_b_clear (PLCI   *plci)
13559 {
13560
13561   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_clear",
13562     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
13563     (char   *)(FILE_), __LINE__));
13564
13565   plci->adjust_b_restore = false;
13566 }
13567
13568
13569 static word adjust_b_process (dword Id, PLCI   *plci, byte Rc)
13570 {
13571   word Info;
13572   byte b1_resource;
13573   NCCI   * ncci_ptr;
13574     API_PARSE bp[2];
13575
13576   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_process %02x %d",
13577     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->adjust_b_state));
13578
13579   Info = GOOD;
13580   switch (plci->adjust_b_state)
13581   {
13582   case ADJUST_B_START:
13583     if ((plci->adjust_b_parms_msg == NULL)
13584      && (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13585      && ((plci->adjust_b_mode & ~(ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 |
13586       ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_RESTORE)) == 0))
13587     {
13588       b1_resource = (plci->adjust_b_mode == ADJUST_B_MODE_NO_RESOURCE) ?
13589         0 : add_b1_facilities (plci, plci->B1_resource, plci->adjust_b_facilities);
13590       if (b1_resource == plci->B1_resource)
13591       {
13592         adjust_b1_facilities (plci, b1_resource, plci->adjust_b_facilities);
13593         break;
13594       }
13595       if (plci->adjust_b_facilities & ~get_b1_facilities (plci, b1_resource))
13596       {
13597         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B nonsupported facilities %d %d %04x",
13598           UnMapId (Id), (char   *)(FILE_), __LINE__,
13599           plci->B1_resource, b1_resource, plci->adjust_b_facilities));
13600         Info = _WRONG_STATE;
13601         break;
13602       }
13603     }
13604     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13605     {
13606
13607       mixer_prepare_switch (Id, plci);
13608
13609
13610       dtmf_prepare_switch (Id, plci);
13611       dtmf_parameter_prepare_switch (Id, plci);
13612
13613
13614       ec_prepare_switch (Id, plci);
13615
13616       adv_voice_prepare_switch (Id, plci);
13617     }
13618     plci->adjust_b_state = ADJUST_B_SAVE_MIXER_1;
13619     Rc = OK;
13620   case ADJUST_B_SAVE_MIXER_1:
13621     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13622     {
13623
13624       Info = mixer_save_config (Id, plci, Rc);
13625       if ((Info != GOOD) || plci->internal_command)
13626         break;
13627
13628     }
13629     plci->adjust_b_state = ADJUST_B_SAVE_DTMF_1;
13630     Rc = OK;
13631   case ADJUST_B_SAVE_DTMF_1:
13632     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13633     {
13634
13635       Info = dtmf_save_config (Id, plci, Rc);
13636       if ((Info != GOOD) || plci->internal_command)
13637         break;
13638
13639     }
13640     plci->adjust_b_state = ADJUST_B_REMOVE_L23_1;
13641   case ADJUST_B_REMOVE_L23_1:
13642     if ((plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13643      && plci->NL.Id && !plci->nl_remove_id)
13644     {
13645       plci->internal_command = plci->adjust_b_command;
13646       if (plci->adjust_b_ncci != 0)
13647       {
13648         ncci_ptr = &(plci->adapter->ncci[plci->adjust_b_ncci]);
13649         while (ncci_ptr->data_pending)
13650         {
13651           plci->data_sent_ptr = ncci_ptr->DBuffer[ncci_ptr->data_out].P;
13652           data_rc (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13653         }
13654         while (ncci_ptr->data_ack_pending)
13655           data_ack (plci, plci->adapter->ncci_ch[plci->adjust_b_ncci]);
13656       }
13657       nl_req_ncci (plci, REMOVE,
13658         (byte)((plci->adjust_b_mode & ADJUST_B_MODE_CONNECT) ? plci->adjust_b_ncci : 0));
13659       send_req (plci);
13660       plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13661       break;
13662     }
13663     plci->adjust_b_state = ADJUST_B_REMOVE_L23_2;
13664     Rc = OK;
13665   case ADJUST_B_REMOVE_L23_2:
13666     if ((Rc != OK) && (Rc != OK_FC))
13667     {
13668       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B remove failed %02x",
13669         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13670       Info = _WRONG_STATE;
13671       break;
13672     }
13673     if (plci->adjust_b_mode & ADJUST_B_MODE_REMOVE_L23)
13674     {
13675       if (plci_nl_busy (plci))
13676       {
13677         plci->internal_command = plci->adjust_b_command;
13678         break;
13679       }
13680     }
13681     plci->adjust_b_state = ADJUST_B_SAVE_EC_1;
13682     Rc = OK;
13683   case ADJUST_B_SAVE_EC_1:
13684     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13685     {
13686
13687       Info = ec_save_config (Id, plci, Rc);
13688       if ((Info != GOOD) || plci->internal_command)
13689         break;
13690
13691     }
13692     plci->adjust_b_state = ADJUST_B_SAVE_DTMF_PARAMETER_1;
13693     Rc = OK;
13694   case ADJUST_B_SAVE_DTMF_PARAMETER_1:
13695     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13696     {
13697
13698       Info = dtmf_parameter_save_config (Id, plci, Rc);
13699       if ((Info != GOOD) || plci->internal_command)
13700         break;
13701
13702     }
13703     plci->adjust_b_state = ADJUST_B_SAVE_VOICE_1;
13704     Rc = OK;
13705   case ADJUST_B_SAVE_VOICE_1:
13706     if (plci->adjust_b_mode & ADJUST_B_MODE_SAVE)
13707     {
13708       Info = adv_voice_save_config (Id, plci, Rc);
13709       if ((Info != GOOD) || plci->internal_command)
13710         break;
13711     }
13712     plci->adjust_b_state = ADJUST_B_SWITCH_L1_1;
13713   case ADJUST_B_SWITCH_L1_1:
13714     if (plci->adjust_b_mode & ADJUST_B_MODE_SWITCH_L1)
13715     {
13716       if (plci->sig_req)
13717       {
13718         plci->internal_command = plci->adjust_b_command;
13719         break;
13720       }
13721       if (plci->adjust_b_parms_msg != NULL)
13722         api_load_msg (plci->adjust_b_parms_msg, bp);
13723       else
13724         api_load_msg (&plci->B_protocol, bp);
13725       Info = add_b1 (plci, bp,
13726         (word)((plci->adjust_b_mode & ADJUST_B_MODE_NO_RESOURCE) ? 2 : 0),
13727         plci->adjust_b_facilities);
13728       if (Info != GOOD)
13729       {
13730         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L1 parameters %d %04x",
13731           UnMapId (Id), (char   *)(FILE_), __LINE__,
13732           plci->B1_resource, plci->adjust_b_facilities));
13733         break;
13734       }
13735       plci->internal_command = plci->adjust_b_command;
13736       sig_req (plci, RESOURCES, 0);
13737       send_req (plci);
13738       plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13739       break;
13740     }
13741     plci->adjust_b_state = ADJUST_B_SWITCH_L1_2;
13742     Rc = OK;
13743   case ADJUST_B_SWITCH_L1_2:
13744     if ((Rc != OK) && (Rc != OK_FC))
13745     {
13746       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B switch failed %02x %d %04x",
13747         UnMapId (Id), (char   *)(FILE_), __LINE__,
13748         Rc, plci->B1_resource, plci->adjust_b_facilities));
13749       Info = _WRONG_STATE;
13750       break;
13751     }
13752     plci->adjust_b_state = ADJUST_B_RESTORE_VOICE_1;
13753     Rc = OK;
13754   case ADJUST_B_RESTORE_VOICE_1:
13755   case ADJUST_B_RESTORE_VOICE_2:
13756     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13757     {
13758       Info = adv_voice_restore_config (Id, plci, Rc);
13759       if ((Info != GOOD) || plci->internal_command)
13760         break;
13761     }
13762     plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_PARAMETER_1;
13763     Rc = OK;
13764   case ADJUST_B_RESTORE_DTMF_PARAMETER_1:
13765   case ADJUST_B_RESTORE_DTMF_PARAMETER_2:
13766     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13767     {
13768
13769       Info = dtmf_parameter_restore_config (Id, plci, Rc);
13770       if ((Info != GOOD) || plci->internal_command)
13771         break;
13772
13773     }
13774     plci->adjust_b_state = ADJUST_B_RESTORE_EC_1;
13775     Rc = OK;
13776   case ADJUST_B_RESTORE_EC_1:
13777   case ADJUST_B_RESTORE_EC_2:
13778     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13779     {
13780
13781       Info = ec_restore_config (Id, plci, Rc);
13782       if ((Info != GOOD) || plci->internal_command)
13783         break;
13784
13785     }
13786     plci->adjust_b_state = ADJUST_B_ASSIGN_L23_1;
13787   case ADJUST_B_ASSIGN_L23_1:
13788     if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13789     {
13790       if (plci_nl_busy (plci))
13791       {
13792         plci->internal_command = plci->adjust_b_command;
13793         break;
13794       }
13795       if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13796         plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
13797       if (plci->adjust_b_parms_msg != NULL)
13798         api_load_msg (plci->adjust_b_parms_msg, bp);
13799       else
13800         api_load_msg (&plci->B_protocol, bp);
13801       Info = add_b23 (plci, bp);
13802       if (Info != GOOD)
13803       {
13804         dbug (1, dprintf ("[%06lx] %s,%d: Adjust B invalid L23 parameters %04x",
13805           UnMapId (Id), (char   *)(FILE_), __LINE__, Info));
13806         break;
13807       }
13808       plci->internal_command = plci->adjust_b_command;
13809       nl_req_ncci (plci, ASSIGN, 0);
13810       send_req (plci);
13811       plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13812       break;
13813     }
13814     plci->adjust_b_state = ADJUST_B_ASSIGN_L23_2;
13815     Rc = ASSIGN_OK;
13816   case ADJUST_B_ASSIGN_L23_2:
13817     if ((Rc != OK) && (Rc != OK_FC) && (Rc != ASSIGN_OK))
13818     {
13819       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B assign failed %02x",
13820         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13821       Info = _WRONG_STATE;
13822       break;
13823     }
13824     if (plci->adjust_b_mode & ADJUST_B_MODE_ASSIGN_L23)
13825     {
13826       if (Rc != ASSIGN_OK)
13827       {
13828         plci->internal_command = plci->adjust_b_command;
13829         break;
13830       }
13831     }
13832     if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
13833     {
13834       plci->adjust_b_restore = true;
13835       break;
13836     }
13837     plci->adjust_b_state = ADJUST_B_CONNECT_1;
13838   case ADJUST_B_CONNECT_1:
13839     if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13840     {
13841       plci->internal_command = plci->adjust_b_command;
13842       if (plci_nl_busy (plci))
13843         break;
13844       nl_req_ncci (plci, N_CONNECT, 0);
13845       send_req (plci);
13846       plci->adjust_b_state = ADJUST_B_CONNECT_2;
13847       break;
13848     }
13849     plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13850     Rc = OK;
13851   case ADJUST_B_CONNECT_2:
13852   case ADJUST_B_CONNECT_3:
13853   case ADJUST_B_CONNECT_4:
13854     if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
13855     {
13856       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B connect failed %02x",
13857         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13858       Info = _WRONG_STATE;
13859       break;
13860     }
13861     if (Rc == OK)
13862     {
13863       if (plci->adjust_b_mode & ADJUST_B_MODE_CONNECT)
13864       {
13865         get_ncci (plci, (byte)(Id >> 16), plci->adjust_b_ncci);
13866         Id = (Id & 0xffff) | (((dword)(plci->adjust_b_ncci)) << 16);
13867       }
13868       if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13869         plci->adjust_b_state = ADJUST_B_CONNECT_3;
13870       else if (plci->adjust_b_state == ADJUST_B_CONNECT_4)
13871         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13872     }
13873     else if (Rc == 0)
13874     {
13875       if (plci->adjust_b_state == ADJUST_B_CONNECT_2)
13876         plci->adjust_b_state = ADJUST_B_CONNECT_4;
13877       else if (plci->adjust_b_state == ADJUST_B_CONNECT_3)
13878         plci->adjust_b_state = ADJUST_B_RESTORE_DTMF_1;
13879     }
13880     if (plci->adjust_b_state != ADJUST_B_RESTORE_DTMF_1)
13881     {
13882       plci->internal_command = plci->adjust_b_command;
13883       break;
13884     }
13885     Rc = OK;
13886   case ADJUST_B_RESTORE_DTMF_1:
13887   case ADJUST_B_RESTORE_DTMF_2:
13888     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13889     {
13890
13891       Info = dtmf_restore_config (Id, plci, Rc);
13892       if ((Info != GOOD) || plci->internal_command)
13893         break;
13894
13895     }
13896     plci->adjust_b_state = ADJUST_B_RESTORE_MIXER_1;
13897     Rc = OK;
13898   case ADJUST_B_RESTORE_MIXER_1:
13899   case ADJUST_B_RESTORE_MIXER_2:
13900   case ADJUST_B_RESTORE_MIXER_3:
13901   case ADJUST_B_RESTORE_MIXER_4:
13902   case ADJUST_B_RESTORE_MIXER_5:
13903   case ADJUST_B_RESTORE_MIXER_6:
13904   case ADJUST_B_RESTORE_MIXER_7:
13905     if (plci->adjust_b_mode & ADJUST_B_MODE_RESTORE)
13906     {
13907
13908       Info = mixer_restore_config (Id, plci, Rc);
13909       if ((Info != GOOD) || plci->internal_command)
13910         break;
13911
13912     }
13913     plci->adjust_b_state = ADJUST_B_END;
13914   case ADJUST_B_END:
13915     break;
13916   }
13917   return (Info);
13918 }
13919
13920
13921 static void adjust_b1_resource (dword Id, PLCI   *plci, API_SAVE   *bp_msg, word b1_facilities, word internal_command)
13922 {
13923
13924   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b1_resource %d %04x",
13925     UnMapId (Id), (char   *)(FILE_), __LINE__,
13926     plci->B1_resource, b1_facilities));
13927
13928   plci->adjust_b_parms_msg = bp_msg;
13929   plci->adjust_b_facilities = b1_facilities;
13930   plci->adjust_b_command = internal_command;
13931   plci->adjust_b_ncci = (word)(Id >> 16);
13932   if ((bp_msg == NULL) && (plci->B1_resource == 0))
13933     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_NO_RESOURCE | ADJUST_B_MODE_SWITCH_L1;
13934   else
13935     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_SWITCH_L1 | ADJUST_B_MODE_RESTORE;
13936   plci->adjust_b_state = ADJUST_B_START;
13937   dbug (1, dprintf ("[%06lx] %s,%d: Adjust B1 resource %d %04x...",
13938     UnMapId (Id), (char   *)(FILE_), __LINE__,
13939     plci->B1_resource, b1_facilities));
13940 }
13941
13942
13943 static void adjust_b_restore (dword Id, PLCI   *plci, byte Rc)
13944 {
13945   word internal_command;
13946
13947   dbug (1, dprintf ("[%06lx] %s,%d: adjust_b_restore %02x %04x",
13948     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
13949
13950   internal_command = plci->internal_command;
13951   plci->internal_command = 0;
13952   switch (internal_command)
13953   {
13954   default:
13955     plci->command = 0;
13956     if (plci->req_in != 0)
13957     {
13958       plci->internal_command = ADJUST_B_RESTORE_1;
13959       break;
13960     }
13961     Rc = OK;
13962   case ADJUST_B_RESTORE_1:
13963     if ((Rc != OK) && (Rc != OK_FC))
13964     {
13965       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B enqueued failed %02x",
13966         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
13967     }
13968     plci->adjust_b_parms_msg = NULL;
13969     plci->adjust_b_facilities = plci->B1_facilities;
13970     plci->adjust_b_command = ADJUST_B_RESTORE_2;
13971     plci->adjust_b_ncci = (word)(Id >> 16);
13972     plci->adjust_b_mode = ADJUST_B_MODE_RESTORE;
13973     plci->adjust_b_state = ADJUST_B_START;
13974     dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore...",
13975       UnMapId (Id), (char   *)(FILE_), __LINE__));
13976   case ADJUST_B_RESTORE_2:
13977     if (adjust_b_process (Id, plci, Rc) != GOOD)
13978     {
13979       dbug (1, dprintf ("[%06lx] %s,%d: Adjust B restore failed",
13980         UnMapId (Id), (char   *)(FILE_), __LINE__));
13981     }
13982     if (plci->internal_command)
13983       break;
13984     break;
13985   }
13986 }
13987
13988
13989 static void reset_b3_command (dword Id, PLCI   *plci, byte Rc)
13990 {
13991   word Info;
13992   word internal_command;
13993
13994   dbug (1, dprintf ("[%06lx] %s,%d: reset_b3_command %02x %04x",
13995     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
13996
13997   Info = GOOD;
13998   internal_command = plci->internal_command;
13999   plci->internal_command = 0;
14000   switch (internal_command)
14001   {
14002   default:
14003     plci->command = 0;
14004     plci->adjust_b_parms_msg = NULL;
14005     plci->adjust_b_facilities = plci->B1_facilities;
14006     plci->adjust_b_command = RESET_B3_COMMAND_1;
14007     plci->adjust_b_ncci = (word)(Id >> 16);
14008     plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_CONNECT;
14009     plci->adjust_b_state = ADJUST_B_START;
14010     dbug (1, dprintf ("[%06lx] %s,%d: Reset B3...",
14011       UnMapId (Id), (char   *)(FILE_), __LINE__));
14012   case RESET_B3_COMMAND_1:
14013     Info = adjust_b_process (Id, plci, Rc);
14014     if (Info != GOOD)
14015     {
14016       dbug (1, dprintf ("[%06lx] %s,%d: Reset failed",
14017         UnMapId (Id), (char   *)(FILE_), __LINE__));
14018       break;
14019     }
14020     if (plci->internal_command)
14021       return;
14022     break;
14023   }
14024 /*  sendf (plci->appl, _RESET_B3_R | CONFIRM, Id, plci->number, "w", Info);*/
14025   sendf(plci->appl,_RESET_B3_I,Id,0,"s","");
14026 }
14027
14028
14029 static void select_b_command (dword Id, PLCI   *plci, byte Rc)
14030 {
14031   word Info;
14032   word internal_command;
14033   byte esc_chi[3];
14034
14035   dbug (1, dprintf ("[%06lx] %s,%d: select_b_command %02x %04x",
14036     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14037
14038   Info = GOOD;
14039   internal_command = plci->internal_command;
14040   plci->internal_command = 0;
14041   switch (internal_command)
14042   {
14043   default:
14044     plci->command = 0;
14045     plci->adjust_b_parms_msg = &plci->saved_msg;
14046     if ((plci->tel == ADV_VOICE) && (plci == plci->adapter->AdvSignalPLCI))
14047       plci->adjust_b_facilities = plci->B1_facilities | B1_FACILITY_VOICE;
14048     else
14049       plci->adjust_b_facilities = plci->B1_facilities & ~B1_FACILITY_VOICE;
14050     plci->adjust_b_command = SELECT_B_COMMAND_1;
14051     plci->adjust_b_ncci = (word)(Id >> 16);
14052     if (plci->saved_msg.parms[0].length == 0)
14053     {
14054       plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14055         ADJUST_B_MODE_NO_RESOURCE;
14056     }
14057     else
14058     {
14059       plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_SWITCH_L1 |
14060         ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14061     }
14062     plci->adjust_b_state = ADJUST_B_START;
14063     dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol...",
14064       UnMapId (Id), (char   *)(FILE_), __LINE__));
14065   case SELECT_B_COMMAND_1:
14066     Info = adjust_b_process (Id, plci, Rc);
14067     if (Info != GOOD)
14068     {
14069       dbug (1, dprintf ("[%06lx] %s,%d: Select B protocol failed",
14070         UnMapId (Id), (char   *)(FILE_), __LINE__));
14071       break;
14072     }
14073     if (plci->internal_command)
14074       return;
14075     if (plci->tel == ADV_VOICE)
14076     {
14077       esc_chi[0] = 0x02;
14078       esc_chi[1] = 0x18;
14079       esc_chi[2] = plci->b_channel;
14080       SetVoiceChannel (plci->adapter->AdvCodecPLCI, esc_chi, plci->adapter);
14081     }
14082     break;
14083   }
14084   sendf (plci->appl, _SELECT_B_REQ | CONFIRM, Id, plci->number, "w", Info);
14085 }
14086
14087
14088 static void fax_connect_ack_command (dword Id, PLCI   *plci, byte Rc)
14089 {
14090   word Info;
14091   word internal_command;
14092
14093   dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
14094     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14095
14096   Info = GOOD;
14097   internal_command = plci->internal_command;
14098   plci->internal_command = 0;
14099   switch (internal_command)
14100   {
14101   default:
14102     plci->command = 0;
14103   case FAX_CONNECT_ACK_COMMAND_1:
14104     if (plci_nl_busy (plci))
14105     {
14106       plci->internal_command = FAX_CONNECT_ACK_COMMAND_1;
14107       return;
14108     }
14109     plci->internal_command = FAX_CONNECT_ACK_COMMAND_2;
14110     plci->NData[0].P = plci->fax_connect_info_buffer;
14111     plci->NData[0].PLength = plci->fax_connect_info_length;
14112     plci->NL.X = plci->NData;
14113     plci->NL.ReqCh = 0;
14114     plci->NL.Req = plci->nl_req = (byte) N_CONNECT_ACK;
14115     plci->adapter->request (&plci->NL);
14116     return;
14117   case FAX_CONNECT_ACK_COMMAND_2:
14118     if ((Rc != OK) && (Rc != OK_FC))
14119     {
14120       dbug (1, dprintf ("[%06lx] %s,%d: FAX issue CONNECT ACK failed %02x",
14121         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14122       break;
14123     }
14124   }
14125   if ((plci->ncpi_state & NCPI_VALID_CONNECT_B3_ACT)
14126    && !(plci->ncpi_state & NCPI_CONNECT_B3_ACT_SENT))
14127   {
14128     if (plci->B3_prot == 4)
14129       sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
14130     else
14131       sendf(plci->appl,_CONNECT_B3_ACTIVE_I,Id,0,"S",plci->ncpi_buffer);
14132     plci->ncpi_state |= NCPI_CONNECT_B3_ACT_SENT;
14133   }
14134 }
14135
14136
14137 static void fax_edata_ack_command (dword Id, PLCI   *plci, byte Rc)
14138 {
14139   word Info;
14140   word internal_command;
14141
14142   dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
14143     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14144
14145   Info = GOOD;
14146   internal_command = plci->internal_command;
14147   plci->internal_command = 0;
14148   switch (internal_command)
14149   {
14150   default:
14151     plci->command = 0;
14152   case FAX_EDATA_ACK_COMMAND_1:
14153     if (plci_nl_busy (plci))
14154     {
14155       plci->internal_command = FAX_EDATA_ACK_COMMAND_1;
14156       return;
14157     }
14158     plci->internal_command = FAX_EDATA_ACK_COMMAND_2;
14159     plci->NData[0].P = plci->fax_connect_info_buffer;
14160     plci->NData[0].PLength = plci->fax_edata_ack_length;
14161     plci->NL.X = plci->NData;
14162     plci->NL.ReqCh = 0;
14163     plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14164     plci->adapter->request (&plci->NL);
14165     return;
14166   case FAX_EDATA_ACK_COMMAND_2:
14167     if ((Rc != OK) && (Rc != OK_FC))
14168     {
14169       dbug (1, dprintf ("[%06lx] %s,%d: FAX issue EDATA ACK failed %02x",
14170         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14171       break;
14172     }
14173   }
14174 }
14175
14176
14177 static void fax_connect_info_command (dword Id, PLCI   *plci, byte Rc)
14178 {
14179   word Info;
14180   word internal_command;
14181
14182   dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_info_command %02x %04x",
14183     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14184
14185   Info = GOOD;
14186   internal_command = plci->internal_command;
14187   plci->internal_command = 0;
14188   switch (internal_command)
14189   {
14190   default:
14191     plci->command = 0;
14192   case FAX_CONNECT_INFO_COMMAND_1:
14193     if (plci_nl_busy (plci))
14194     {
14195       plci->internal_command = FAX_CONNECT_INFO_COMMAND_1;
14196       return;
14197     }
14198     plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14199     plci->NData[0].P = plci->fax_connect_info_buffer;
14200     plci->NData[0].PLength = plci->fax_connect_info_length;
14201     plci->NL.X = plci->NData;
14202     plci->NL.ReqCh = 0;
14203     plci->NL.Req = plci->nl_req = (byte) N_EDATA;
14204     plci->adapter->request (&plci->NL);
14205     return;
14206   case FAX_CONNECT_INFO_COMMAND_2:
14207     if ((Rc != OK) && (Rc != OK_FC))
14208     {
14209       dbug (1, dprintf ("[%06lx] %s,%d: FAX setting connect info failed %02x",
14210         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14211       Info = _WRONG_STATE;
14212       break;
14213     }
14214     if (plci_nl_busy (plci))
14215     {
14216       plci->internal_command = FAX_CONNECT_INFO_COMMAND_2;
14217       return;
14218     }
14219     plci->command = _CONNECT_B3_R;
14220     nl_req_ncci (plci, N_CONNECT, 0);
14221     send_req (plci);
14222     return;
14223   }
14224   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14225 }
14226
14227
14228 static void fax_adjust_b23_command (dword Id, PLCI   *plci, byte Rc)
14229 {
14230   word Info;
14231   word internal_command;
14232
14233   dbug (1, dprintf ("[%06lx] %s,%d: fax_adjust_b23_command %02x %04x",
14234     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14235
14236   Info = GOOD;
14237   internal_command = plci->internal_command;
14238   plci->internal_command = 0;
14239   switch (internal_command)
14240   {
14241   default:
14242     plci->command = 0;
14243     plci->adjust_b_parms_msg = NULL;
14244     plci->adjust_b_facilities = plci->B1_facilities;
14245     plci->adjust_b_command = FAX_ADJUST_B23_COMMAND_1;
14246     plci->adjust_b_ncci = (word)(Id >> 16);
14247     plci->adjust_b_mode = ADJUST_B_MODE_REMOVE_L23 | ADJUST_B_MODE_ASSIGN_L23;
14248     plci->adjust_b_state = ADJUST_B_START;
14249     dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust B23...",
14250       UnMapId (Id), (char   *)(FILE_), __LINE__));
14251   case FAX_ADJUST_B23_COMMAND_1:
14252     Info = adjust_b_process (Id, plci, Rc);
14253     if (Info != GOOD)
14254     {
14255       dbug (1, dprintf ("[%06lx] %s,%d: FAX adjust failed",
14256         UnMapId (Id), (char   *)(FILE_), __LINE__));
14257       break;
14258     }
14259     if (plci->internal_command)
14260       return;
14261   case FAX_ADJUST_B23_COMMAND_2:
14262     if (plci_nl_busy (plci))
14263     {
14264       plci->internal_command = FAX_ADJUST_B23_COMMAND_2;
14265       return;
14266     }
14267     plci->command = _CONNECT_B3_R;
14268     nl_req_ncci (plci, N_CONNECT, 0);
14269     send_req (plci);
14270     return;
14271   }
14272   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14273 }
14274
14275
14276 static void fax_disconnect_command (dword Id, PLCI   *plci, byte Rc)
14277 {
14278   word internal_command;
14279
14280   dbug (1, dprintf ("[%06lx] %s,%d: fax_disconnect_command %02x %04x",
14281     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14282
14283   internal_command = plci->internal_command;
14284   plci->internal_command = 0;
14285   switch (internal_command)
14286   {
14287   default:
14288     plci->command = 0;
14289     plci->internal_command = FAX_DISCONNECT_COMMAND_1;
14290     return;
14291   case FAX_DISCONNECT_COMMAND_1:
14292   case FAX_DISCONNECT_COMMAND_2:
14293   case FAX_DISCONNECT_COMMAND_3:
14294     if ((Rc != OK) && (Rc != OK_FC) && (Rc != 0))
14295     {
14296       dbug (1, dprintf ("[%06lx] %s,%d: FAX disconnect EDATA failed %02x",
14297         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14298       break;
14299     }
14300     if (Rc == OK)
14301     {
14302       if ((internal_command == FAX_DISCONNECT_COMMAND_1)
14303        || (internal_command == FAX_DISCONNECT_COMMAND_2))
14304       {
14305         plci->internal_command = FAX_DISCONNECT_COMMAND_2;
14306       }
14307     }
14308     else if (Rc == 0)
14309     {
14310       if (internal_command == FAX_DISCONNECT_COMMAND_1)
14311         plci->internal_command = FAX_DISCONNECT_COMMAND_3;
14312     }
14313     return;
14314   }
14315 }
14316
14317
14318
14319 static void rtp_connect_b3_req_command (dword Id, PLCI   *plci, byte Rc)
14320 {
14321   word Info;
14322   word internal_command;
14323
14324   dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_req_command %02x %04x",
14325     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14326
14327   Info = GOOD;
14328   internal_command = plci->internal_command;
14329   plci->internal_command = 0;
14330   switch (internal_command)
14331   {
14332   default:
14333     plci->command = 0;
14334   case RTP_CONNECT_B3_REQ_COMMAND_1:
14335     if (plci_nl_busy (plci))
14336     {
14337       plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_1;
14338       return;
14339     }
14340     plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14341     nl_req_ncci (plci, N_CONNECT, 0);
14342     send_req (plci);
14343     return;
14344   case RTP_CONNECT_B3_REQ_COMMAND_2:
14345     if ((Rc != OK) && (Rc != OK_FC))
14346     {
14347       dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect info failed %02x",
14348         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14349       Info = _WRONG_STATE;
14350       break;
14351     }
14352     if (plci_nl_busy (plci))
14353     {
14354       plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_2;
14355       return;
14356     }
14357     plci->internal_command = RTP_CONNECT_B3_REQ_COMMAND_3;
14358     plci->NData[0].PLength = plci->internal_req_buffer[0];
14359     plci->NData[0].P = plci->internal_req_buffer + 1;
14360     plci->NL.X = plci->NData;
14361     plci->NL.ReqCh = 0;
14362     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14363     plci->adapter->request (&plci->NL);
14364     break;
14365   case RTP_CONNECT_B3_REQ_COMMAND_3:
14366     return;
14367   }
14368   sendf (plci->appl, _CONNECT_B3_R | CONFIRM, Id, plci->number, "w", Info);
14369 }
14370
14371
14372 static void rtp_connect_b3_res_command (dword Id, PLCI   *plci, byte Rc)
14373 {
14374   word Info;
14375   word internal_command;
14376
14377   dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
14378     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14379
14380   Info = GOOD;
14381   internal_command = plci->internal_command;
14382   plci->internal_command = 0;
14383   switch (internal_command)
14384   {
14385   default:
14386     plci->command = 0;
14387   case RTP_CONNECT_B3_RES_COMMAND_1:
14388     if (plci_nl_busy (plci))
14389     {
14390       plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_1;
14391       return;
14392     }
14393     plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14394     nl_req_ncci (plci, N_CONNECT_ACK, (byte)(Id >> 16));
14395     send_req (plci);
14396     return;
14397   case RTP_CONNECT_B3_RES_COMMAND_2:
14398     if ((Rc != OK) && (Rc != OK_FC))
14399     {
14400       dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
14401         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
14402       Info = _WRONG_STATE;
14403       break;
14404     }
14405     if (plci_nl_busy (plci))
14406     {
14407       plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_2;
14408       return;
14409     }
14410     sendf (plci->appl, _CONNECT_B3_ACTIVE_I, Id, 0, "s", "");
14411     plci->internal_command = RTP_CONNECT_B3_RES_COMMAND_3;
14412     plci->NData[0].PLength = plci->internal_req_buffer[0];
14413     plci->NData[0].P = plci->internal_req_buffer + 1;
14414     plci->NL.X = plci->NData;
14415     plci->NL.ReqCh = 0;
14416     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
14417     plci->adapter->request (&plci->NL);
14418     return;
14419   case RTP_CONNECT_B3_RES_COMMAND_3:
14420     return;
14421   }
14422 }
14423
14424
14425
14426 static void hold_save_command (dword Id, PLCI   *plci, byte Rc)
14427 {
14428     byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
14429   word Info;
14430   word internal_command;
14431
14432   dbug (1, dprintf ("[%06lx] %s,%d: hold_save_command %02x %04x",
14433     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14434
14435   Info = GOOD;
14436   internal_command = plci->internal_command;
14437   plci->internal_command = 0;
14438   switch (internal_command)
14439   {
14440   default:
14441     if (!plci->NL.Id)
14442       break;
14443     plci->command = 0;
14444     plci->adjust_b_parms_msg = NULL;
14445     plci->adjust_b_facilities = plci->B1_facilities;
14446     plci->adjust_b_command = HOLD_SAVE_COMMAND_1;
14447     plci->adjust_b_ncci = (word)(Id >> 16);
14448     plci->adjust_b_mode = ADJUST_B_MODE_SAVE | ADJUST_B_MODE_REMOVE_L23;
14449     plci->adjust_b_state = ADJUST_B_START;
14450     dbug (1, dprintf ("[%06lx] %s,%d: HOLD save...",
14451       UnMapId (Id), (char   *)(FILE_), __LINE__));
14452   case HOLD_SAVE_COMMAND_1:
14453     Info = adjust_b_process (Id, plci, Rc);
14454     if (Info != GOOD)
14455     {
14456       dbug (1, dprintf ("[%06lx] %s,%d: HOLD save failed",
14457         UnMapId (Id), (char   *)(FILE_), __LINE__));
14458       break;
14459     }
14460     if (plci->internal_command)
14461       return;
14462   }
14463   sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14464 }
14465
14466
14467 static void retrieve_restore_command (dword Id, PLCI   *plci, byte Rc)
14468 {
14469     byte SS_Ind[] = "\x05\x03\x00\x02\x00\x00"; /* Retrieve_Ind struct*/
14470   word Info;
14471   word internal_command;
14472
14473   dbug (1, dprintf ("[%06lx] %s,%d: retrieve_restore_command %02x %04x",
14474     UnMapId (Id), (char   *)(FILE_), __LINE__, Rc, plci->internal_command));
14475
14476   Info = GOOD;
14477   internal_command = plci->internal_command;
14478   plci->internal_command = 0;
14479   switch (internal_command)
14480   {
14481   default:
14482     plci->command = 0;
14483     plci->adjust_b_parms_msg = NULL;
14484     plci->adjust_b_facilities = plci->B1_facilities;
14485     plci->adjust_b_command = RETRIEVE_RESTORE_COMMAND_1;
14486     plci->adjust_b_ncci = (word)(Id >> 16);
14487     plci->adjust_b_mode = ADJUST_B_MODE_ASSIGN_L23 | ADJUST_B_MODE_USER_CONNECT | ADJUST_B_MODE_RESTORE;
14488     plci->adjust_b_state = ADJUST_B_START;
14489     dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore...",
14490       UnMapId (Id), (char   *)(FILE_), __LINE__));
14491   case RETRIEVE_RESTORE_COMMAND_1:
14492     Info = adjust_b_process (Id, plci, Rc);
14493     if (Info != GOOD)
14494     {
14495       dbug (1, dprintf ("[%06lx] %s,%d: RETRIEVE restore failed",
14496         UnMapId (Id), (char   *)(FILE_), __LINE__));
14497       break;
14498     }
14499     if (plci->internal_command)
14500       return;
14501   }
14502   sendf (plci->appl, _FACILITY_I, Id & 0xffffL, 0, "ws", 3, SS_Ind);
14503 }
14504
14505
14506 static void init_b1_config (PLCI   *plci)
14507 {
14508
14509   dbug (1, dprintf ("[%06lx] %s,%d: init_b1_config",
14510     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14511     (char   *)(FILE_), __LINE__));
14512
14513   plci->B1_resource = 0;
14514   plci->B1_facilities = 0;
14515
14516   plci->li_bchannel_id = 0;
14517   mixer_clear_config (plci);
14518
14519
14520   ec_clear_config (plci);
14521
14522
14523   dtmf_rec_clear_config (plci);
14524   dtmf_send_clear_config (plci);
14525   dtmf_parameter_clear_config (plci);
14526
14527   adv_voice_clear_config (plci);
14528   adjust_b_clear (plci);
14529 }
14530
14531
14532 static void clear_b1_config (PLCI   *plci)
14533 {
14534
14535   dbug (1, dprintf ("[%06lx] %s,%d: clear_b1_config",
14536     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
14537     (char   *)(FILE_), __LINE__));
14538
14539   adv_voice_clear_config (plci);
14540   adjust_b_clear (plci);
14541
14542   ec_clear_config (plci);
14543
14544
14545   dtmf_rec_clear_config (plci);
14546   dtmf_send_clear_config (plci);
14547   dtmf_parameter_clear_config (plci);
14548
14549
14550   if ((plci->li_bchannel_id != 0)
14551    && (li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci == plci))
14552   {
14553     mixer_clear_config (plci);
14554     li_config_table[plci->adapter->li_base + (plci->li_bchannel_id - 1)].plci = NULL;
14555     plci->li_bchannel_id = 0;
14556   }
14557
14558   plci->B1_resource = 0;
14559   plci->B1_facilities = 0;
14560 }
14561
14562
14563 /* -----------------------------------------------------------------
14564                 XON protocol local helpers
14565    ----------------------------------------------------------------- */
14566 static void channel_flow_control_remove (PLCI   * plci) {
14567   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14568   word i;
14569   for(i=1;i<MAX_NL_CHANNEL+1;i++) {
14570     if (a->ch_flow_plci[i] == plci->Id) {
14571       a->ch_flow_plci[i] = 0;
14572       a->ch_flow_control[i] = 0;
14573     }
14574   }
14575 }
14576
14577 static void channel_x_on (PLCI   * plci, byte ch) {
14578   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14579   if (a->ch_flow_control[ch] & N_XON_SENT) {
14580     a->ch_flow_control[ch] &= ~N_XON_SENT;
14581   }
14582 }
14583
14584 static void channel_x_off (PLCI   * plci, byte ch, byte flag) {
14585   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14586   if ((a->ch_flow_control[ch] & N_RX_FLOW_CONTROL_MASK) == 0) {
14587     a->ch_flow_control[ch] |= (N_CH_XOFF | flag);
14588     a->ch_flow_plci[ch] = plci->Id;
14589     a->ch_flow_control_pending++;
14590   }
14591 }
14592
14593 static void channel_request_xon (PLCI   * plci, byte ch) {
14594   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14595
14596   if (a->ch_flow_control[ch] & N_CH_XOFF) {
14597     a->ch_flow_control[ch] |= N_XON_REQ;
14598     a->ch_flow_control[ch] &= ~N_CH_XOFF;
14599     a->ch_flow_control[ch] &= ~N_XON_CONNECT_IND;
14600   }
14601 }
14602
14603 static void channel_xmit_extended_xon (PLCI   * plci) {
14604   DIVA_CAPI_ADAPTER   * a;
14605   int max_ch = ARRAY_SIZE(a->ch_flow_control);
14606   int i, one_requested = 0;
14607
14608   if ((!plci) || (!plci->Id) || ((a = plci->adapter) == 0)) {
14609     return;
14610   }
14611
14612   for (i = 0; i < max_ch; i++) {
14613     if ((a->ch_flow_control[i] & N_CH_XOFF) &&
14614         (a->ch_flow_control[i] & N_XON_CONNECT_IND) &&
14615         (plci->Id == a->ch_flow_plci[i])) {
14616       channel_request_xon (plci, (byte)i);
14617       one_requested = 1;
14618     }
14619   }
14620
14621   if (one_requested) {
14622     channel_xmit_xon (plci);
14623   }
14624 }
14625
14626 /*
14627   Try to xmit next X_ON
14628   */
14629 static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER   * a, PLCI   * plci) {
14630   int max_ch = ARRAY_SIZE(a->ch_flow_control);
14631   int i;
14632
14633   if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
14634     return (0);
14635   }
14636
14637   if (a->last_flow_control_ch >= max_ch) {
14638     a->last_flow_control_ch = 1;
14639   }
14640   for (i=a->last_flow_control_ch; i < max_ch; i++) {
14641     if ((a->ch_flow_control[i] & N_XON_REQ) &&
14642         (plci->Id == a->ch_flow_plci[i])) {
14643       a->last_flow_control_ch = i+1;
14644       return (i);
14645     }
14646   }
14647
14648   for (i = 1; i < a->last_flow_control_ch; i++) {
14649     if ((a->ch_flow_control[i] & N_XON_REQ) &&
14650         (plci->Id == a->ch_flow_plci[i])) {
14651       a->last_flow_control_ch = i+1;
14652       return (i);
14653     }
14654   }
14655
14656   return (0);
14657 }
14658
14659 static void channel_xmit_xon (PLCI   * plci) {
14660   DIVA_CAPI_ADAPTER   * a = plci->adapter;
14661   byte ch;
14662
14663   if (plci->nl_req || !plci->NL.Id || plci->nl_remove_id) {
14664     return;
14665   }
14666   if ((ch = (byte)find_channel_with_pending_x_on (a, plci)) == 0) {
14667     return;
14668   }
14669   a->ch_flow_control[ch] &= ~N_XON_REQ;
14670   a->ch_flow_control[ch] |= N_XON_SENT;
14671
14672   plci->NL.Req = plci->nl_req = (byte)N_XON;
14673   plci->NL.ReqCh         = ch;
14674   plci->NL.X             = plci->NData;
14675   plci->NL.XNum          = 1;
14676   plci->NData[0].P       = &plci->RBuffer[0];
14677   plci->NData[0].PLength = 0;
14678
14679   plci->adapter->request(&plci->NL);
14680 }
14681
14682 static int channel_can_xon (PLCI   * plci, byte ch) {
14683   APPL   * APPLptr;
14684   DIVA_CAPI_ADAPTER   * a;
14685   word NCCIcode;
14686   dword count;
14687   word Num;
14688   word i;
14689
14690   APPLptr = plci->appl;
14691   a = plci->adapter;
14692
14693   if (!APPLptr)
14694     return (0);
14695
14696   NCCIcode = a->ch_ncci[ch] | (((word) a->Id) << 8);
14697
14698                 /* count all buffers within the Application pool    */
14699                 /* belonging to the same NCCI. XON if a first is    */
14700                 /* used.                                            */
14701   count = 0;
14702   Num = 0xffff;
14703   for(i=0; i<APPLptr->MaxBuffer; i++) {
14704     if(NCCIcode==APPLptr->DataNCCI[i]) count++;
14705     if(!APPLptr->DataNCCI[i] && Num==0xffff) Num = i;
14706   }
14707   if ((count > 2) || (Num == 0xffff)) {
14708     return (0);
14709   }
14710   return (1);
14711 }
14712
14713
14714 /*------------------------------------------------------------------*/
14715
14716 static word CPN_filter_ok(byte   *cpn,DIVA_CAPI_ADAPTER   * a,word offset)
14717 {
14718   return 1;
14719 }
14720
14721
14722
14723 /**********************************************************************************/
14724 /* function groups the listening applications according to the CIP mask and the   */
14725 /* Info_Mask. Each group gets just one Connect_Ind. Some application manufacturer */
14726 /* are not multi-instance capable, so they start e.g. 30 applications what causes */
14727 /* big problems on application level (one call, 30 Connect_Ind, ect). The         */
14728 /* function must be enabled by setting "a->group_optimization_enabled" from the   */
14729 /* OS specific part (per adapter).                                                */
14730 /**********************************************************************************/
14731 static void group_optimization(DIVA_CAPI_ADAPTER   * a, PLCI   * plci)
14732 {
14733   word i,j,k,busy,group_found;
14734   dword info_mask_group[MAX_CIP_TYPES];
14735   dword cip_mask_group[MAX_CIP_TYPES];
14736   word appl_number_group_type[MAX_APPL];
14737   PLCI   *auxplci;
14738
14739   set_group_ind_mask (plci); /* all APPLs within this inc. call are allowed to dial in */
14740
14741   if(!a->group_optimization_enabled)
14742   {
14743     dbug(1,dprintf("No group optimization"));
14744     return;
14745   }
14746
14747   dbug(1,dprintf("Group optimization = 0x%x...", a->group_optimization_enabled));
14748
14749   for(i=0;i<MAX_CIP_TYPES;i++)
14750   {
14751     info_mask_group[i] = 0;
14752     cip_mask_group [i] = 0;
14753   }
14754   for(i=0;i<MAX_APPL;i++)
14755   {
14756     appl_number_group_type[i] = 0;
14757   }
14758   for(i=0; i<max_appl; i++) /* check if any multi instance capable application is present */
14759   {  /* group_optimization set to 1 means not to optimize multi-instance capable applications (default) */
14760     if(application[i].Id && (application[i].MaxNCCI) > 1 && (a->CIP_Mask[i])  && (a->group_optimization_enabled ==1) )
14761     {
14762       dbug(1,dprintf("Multi-Instance capable, no optimization required"));
14763       return; /* allow good application unfiltered access */
14764     }
14765   }
14766   for(i=0; i<max_appl; i++) /* Build CIP Groups */
14767   {
14768     if(application[i].Id && a->CIP_Mask[i] )
14769     {
14770       for(k=0,busy=false; k<a->max_plci; k++)
14771       {
14772         if(a->plci[k].Id) 
14773         {
14774           auxplci = &a->plci[k];
14775           if(auxplci->appl == &application[i]) /* application has a busy PLCI */
14776           {
14777             busy = true;
14778             dbug(1,dprintf("Appl 0x%x is busy",i+1));
14779           }
14780           else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
14781           {
14782             busy = true;
14783             dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
14784           }
14785         }
14786       }
14787
14788       for(j=0,group_found=0; j<=(MAX_CIP_TYPES) && !busy &&!group_found; j++)     /* build groups with free applications only */
14789       {
14790         if(j==MAX_CIP_TYPES)       /* all groups are in use but group still not found */
14791         {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
14792           appl_number_group_type[i] = MAX_CIP_TYPES;
14793           group_found=true;
14794           dbug(1,dprintf("Field overflow appl 0x%x",i+1));
14795         }
14796         else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )  
14797         {                                      /* is group already present ?                  */
14798           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14799           group_found=true;
14800           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]));
14801         }
14802         else if(!info_mask_group[j])
14803         {                                      /* establish a new group                       */
14804           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
14805           info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
14806           cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
14807           group_found=true;
14808           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]));
14809         }
14810       }
14811     }
14812   }
14813         
14814   for(i=0; i<max_appl; i++) /* Build group_optimization_mask_table */
14815   {
14816     if(appl_number_group_type[i]) /* application is free, has listens and is member of a group */
14817     {
14818       if(appl_number_group_type[i] == MAX_CIP_TYPES)
14819       {
14820         dbug(1,dprintf("OverflowGroup 0x%x, valid appl = 0x%x, call enabled",appl_number_group_type[i],i+1));
14821       }
14822       else
14823       {
14824         dbug(1,dprintf("Group 0x%x, valid appl = 0x%x",appl_number_group_type[i],i+1));
14825         for(j=i+1; j<max_appl; j++)   /* search other group members and mark them as busy        */
14826         {
14827           if(appl_number_group_type[i] == appl_number_group_type[j]) 
14828           {
14829             dbug(1,dprintf("Appl 0x%x is member of group 0x%x, no call",j+1,appl_number_group_type[j]));
14830             clear_group_ind_mask_bit (plci, j);           /* disable call on other group members */
14831             appl_number_group_type[j] = 0;       /* remove disabled group member from group list */
14832           }
14833         }
14834       }
14835     }
14836     else                                                 /* application should not get a call */
14837     {
14838       clear_group_ind_mask_bit (plci, i);
14839     }
14840   }
14841
14842 }
14843
14844
14845
14846 /* OS notifies the driver about a application Capi_Register */
14847 word CapiRegister(word id)
14848 {
14849   word i,j,appls_found;
14850
14851   PLCI   *plci;
14852   DIVA_CAPI_ADAPTER   *a;
14853
14854   for(i=0,appls_found=0; i<max_appl; i++)
14855   {
14856     if( application[i].Id && (application[i].Id!=id) )
14857     {
14858       appls_found++;                       /* an application has been found */
14859     }
14860   }
14861
14862   if(appls_found) return true;
14863   for(i=0; i<max_adapter; i++)                   /* scan all adapters...    */
14864   {
14865     a = &adapter[i];
14866     if(a->request)
14867     {
14868       if(a->flag_dynamic_l1_down)  /* remove adapter from L1 tristate (Huntgroup) */
14869       {
14870         if(!appls_found)           /* first application does a capi register   */
14871         {
14872           if((j=get_plci(a)))                    /* activate L1 of all adapters */
14873           {
14874             plci = &a->plci[j-1];
14875             plci->command = 0;
14876             add_p(plci,OAD,"\x01\xfd");
14877             add_p(plci,CAI,"\x01\x80");
14878             add_p(plci,UID,"\x06\x43\x61\x70\x69\x32\x30");
14879             add_p(plci,SHIFT|6,NULL);
14880             add_p(plci,SIN,"\x02\x00\x00");
14881             plci->internal_command = START_L1_SIG_ASSIGN_PEND;
14882             sig_req(plci,ASSIGN,DSIG_ID);
14883             add_p(plci,FTY,"\x02\xff\x07"); /* l1 start */
14884             sig_req(plci,SIG_CTRL,0);
14885             send_req(plci);
14886           }
14887         }
14888       }
14889     }
14890   }
14891   return false;
14892 }
14893
14894 /*------------------------------------------------------------------*/
14895
14896 /* Functions for virtual Switching e.g. Transfer by join, Conference */
14897
14898 static void VSwitchReqInd(PLCI   *plci, dword Id, byte   **parms)
14899 {
14900  word i;
14901  /* Format of vswitch_t:
14902  0 byte length
14903  1 byte VSWITCHIE
14904  2 byte VSWITCH_REQ/VSWITCH_IND
14905  3 byte reserved
14906  4 word VSwitchcommand
14907  6 word returnerror
14908  8... Params
14909  */
14910  if(!plci ||
14911   !plci->appl ||
14912   !plci->State ||
14913   plci->Sig.Ind==NCR_FACILITY
14914   )
14915   return;
14916  
14917  for(i=0;i<MAX_MULTI_IE;i++)
14918  {
14919         if(!parms[i][0]) continue;
14920   if(parms[i][0]<7)
14921   {
14922    parms[i][0]=0; /* kill it */
14923    continue;
14924   }
14925   dbug(1,dprintf("VSwitchReqInd(%d)",parms[i][4]));
14926   switch(parms[i][4])
14927   {
14928   case VSJOIN:
14929    if(!plci->relatedPTYPLCI ||
14930     (plci->ptyState!=S_ECT && plci->relatedPTYPLCI->ptyState!=S_ECT))
14931    { /* Error */
14932     break;
14933    }
14934    /* remember all necessary informations */
14935    if(parms[i][0]!=11 || parms[i][8]!=3) /* Length Test */
14936    {
14937     break;
14938    }
14939    if(parms[i][2]==VSWITCH_IND && parms[i][9]==1)
14940    {   /* first indication after ECT-Request on Consultation Call */
14941     plci->vswitchstate=parms[i][9];
14942     parms[i][9]=2; /* State */
14943     /* now ask first Call to join */
14944    }
14945    else if(parms[i][2]==VSWITCH_REQ && parms[i][9]==3)
14946    { /* Answer of VSWITCH_REQ from first Call */
14947     plci->vswitchstate=parms[i][9];
14948     /* tell consultation call to join
14949     and the protocol capabilities of the first call */
14950    }
14951    else
14952    { /* Error */
14953     break;
14954    }    
14955    plci->vsprot=parms[i][10]; /* protocol */
14956    plci->vsprotdialect=parms[i][11]; /* protocoldialect */
14957    /* send join request to related PLCI */
14958    parms[i][1]=VSWITCHIE;
14959    parms[i][2]=VSWITCH_REQ;
14960    
14961    plci->relatedPTYPLCI->command = 0;
14962    plci->relatedPTYPLCI->internal_command = VSWITCH_REQ_PEND;
14963    add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14964    sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14965    send_req(plci->relatedPTYPLCI);
14966    break;
14967   case VSTRANSPORT:
14968   default:
14969    if(plci->relatedPTYPLCI &&
14970     plci->vswitchstate==3 &&
14971     plci->relatedPTYPLCI->vswitchstate==3)
14972    {
14973     add_p(plci->relatedPTYPLCI,ESC,&parms[i][0]);
14974     sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
14975     send_req(plci->relatedPTYPLCI);
14976    }
14977    break;
14978   }  
14979   parms[i][0]=0; /* kill it */
14980  }
14981 }
14982
14983
14984 /*------------------------------------------------------------------*/
14985
14986 static int diva_get_dma_descriptor (PLCI   *plci, dword   *dma_magic) {
14987   ENTITY e;
14988   IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
14989
14990   if (!(diva_xdi_extended_features & DIVA_CAPI_XDI_PROVIDES_RX_DMA)) {
14991     return (-1);
14992   }
14993
14994   pReq->xdi_dma_descriptor_operation.Req = 0;
14995   pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
14996
14997   pReq->xdi_dma_descriptor_operation.info.operation =     IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
14998   pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
14999   pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15000   pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15001
15002   e.user[0] = plci->adapter->Id - 1;
15003   plci->adapter->request((ENTITY*)pReq);
15004
15005   if (!pReq->xdi_dma_descriptor_operation.info.operation &&
15006       (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
15007       pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
15008     *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
15009     dbug(3,dprintf("dma_alloc, a:%d (%d-%08x)",
15010          plci->adapter->Id,
15011          pReq->xdi_dma_descriptor_operation.info.descriptor_number,
15012          *dma_magic));
15013     return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
15014   } else {
15015     dbug(1,dprintf("dma_alloc failed"));
15016     return (-1);
15017   }
15018 }
15019
15020 static void diva_free_dma_descriptor (PLCI   *plci, int nr) {
15021   ENTITY e;
15022   IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
15023
15024   if (nr < 0) {
15025     return;
15026   }
15027
15028   pReq->xdi_dma_descriptor_operation.Req = 0;
15029   pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
15030
15031   pReq->xdi_dma_descriptor_operation.info.operation =                                                IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
15032   pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
15033   pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
15034   pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
15035
15036   e.user[0] = plci->adapter->Id - 1;
15037   plci->adapter->request((ENTITY*)pReq);
15038
15039   if (!pReq->xdi_dma_descriptor_operation.info.operation) {
15040     dbug(1,dprintf("dma_free(%d)", nr));
15041   } else {
15042     dbug(1,dprintf("dma_free failed (%d)", nr));
15043   }
15044 }
15045
15046 /*------------------------------------------------------------------*/